]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/desktop.c
Merge master
[netatalk.git] / etc / afpd / desktop.c
index c03f07691d689119001d603adbf40dcf78ab0f1d..2a408467f1591badfe13eac47ea339c4e3484b0c 100644 (file)
 #include <atalk/util.h>
 #include <atalk/logger.h>
 #include <atalk/globals.h>
+#include <atalk/netatalk_conf.h>
+#include <atalk/unix.h>
+
 #include "volume.h"
 #include "directory.h"
 #include "fork.h"
 #include "desktop.h"
 #include "mangle.h"
 
+typedef struct _special_folder {
+    const char *name;
+    int precreate;
+    mode_t mode;
+    int hide;
+} _special_folder;
+
+static const _special_folder special_folders[] = {
+    {".AppleDesktop",            1,  0777,  0},
+    {NULL, 0, 0, 0}};
+
+/*
+ * precreate a folder
+ * this is only intended for folders in the volume root
+ * It will *not* work if the folder name contains extended characters
+ */
+static int create_special_folder (const struct vol *vol, const struct _special_folder *folder)
+{
+    char        *p,*q,*r;
+    struct adouble  ad;
+    uint16_t   attr;
+    struct stat st;
+    int     ret;
+
+
+    p = (char *) malloc ( strlen(vol->v_path)+strlen(folder->name)+2);
+    if ( p == NULL) {
+        LOG(log_error, logtype_afpd,"malloc failed");
+        exit (EXITERR_SYS);
+    }
+
+    q=strdup(folder->name);
+    if ( q == NULL) {
+        LOG(log_error, logtype_afpd,"malloc failed");
+        exit (EXITERR_SYS);
+    }
+
+    strcpy(p, vol->v_path);
+    strcat(p, "/");
+
+    r=q;
+    while (*r) {
+        if ((vol->v_casefold & AFPVOL_MTOUUPPER))
+            *r=toupper(*r);
+        else if ((vol->v_casefold & AFPVOL_MTOULOWER))
+            *r=tolower(*r);
+        r++;
+    }
+    strcat(p, q);
+
+    if ( (ret = stat( p, &st )) < 0 ) {
+        if (folder->precreate) {
+            if (ad_mkdir(p, folder->mode)) {
+                LOG(log_debug, logtype_afpd,"Creating '%s' failed in %s: %s", p, vol->v_path, strerror(errno));
+                free(p);
+                free(q);
+                return -1;
+            }
+            ret = 0;
+        }
+    }
+
+    if ( !ret && folder->hide) {
+        /* Hide it */
+        ad_init(&ad, vol);
+        if (ad_open(&ad, p, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0) {
+            free(p);
+            free(q);
+            return (-1);
+        }
+
+        ad_setname(&ad, folder->name);
+
+        ad_getattr(&ad, &attr);
+        attr |= htons( ntohs( attr ) | ATTRBIT_INVISIBLE );
+        ad_setattr(&ad, attr);
+
+        /* do the same with the finder info */
+        if (ad_entry(&ad, ADEID_FINDERI)) {
+            memcpy(&attr, ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, sizeof(attr));
+            attr   |= htons(FINDERINFO_INVISIBLE);
+            memcpy(ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF,&attr, sizeof(attr));
+        }
+
+        ad_flush(&ad);
+        ad_close(&ad, ADFLAGS_HF);
+    }
+    free(p);
+    free(q);
+    return 0;
+}
+
+static void create_appledesktop_folder(const struct vol * vol)
+{
+    const _special_folder *p = &special_folders[0];
+
+    become_root();
+
+    for (; p->name != NULL; p++) {
+        create_special_folder (vol, p);
+    }
+
+    unbecome_root();
+}
 
 int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
 {
@@ -48,6 +155,8 @@ int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size
         return( AFPERR_PARAM );
     }
 
+    create_appledesktop_folder(vol);
+
     memcpy( rbuf, &vid, sizeof(vid));
     *rbuflen = sizeof(vid);
     return( AFP_OK );
@@ -204,42 +313,34 @@ int afp_addicon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
      */
 addicon_err:
     if ( cc < 0 ) {
-        if (obj->proto == AFPPROTO_DSI) {
-            dsi_writeinit(obj->dsi, rbuf, buflen);
-            dsi_writeflush(obj->dsi);
-        }
+        dsi_writeinit(obj->dsi, rbuf, buflen);
+        dsi_writeflush(obj->dsi);
         return cc;
     }
 
-    switch (obj->proto) {
-    case AFPPROTO_DSI:
-        {
-            DSI *dsi = obj->dsi;
+    DSI *dsi = obj->dsi;
 
-            iovcnt = dsi_writeinit(dsi, rbuf, buflen);
+    iovcnt = dsi_writeinit(dsi, rbuf, buflen);
 
-            /* add headers at end of file */
-            if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
-                LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
-                dsi_writeflush(dsi);
-                return AFPERR_PARAM;
-            }
+    /* add headers at end of file */
+    if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
+        LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
+        dsi_writeflush(dsi);
+        return AFPERR_PARAM;
+    }
 
-            if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
-                LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
-                dsi_writeflush(dsi);
-                return AFPERR_PARAM;
-            }
+    if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
+        LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
+        dsi_writeflush(dsi);
+        return AFPERR_PARAM;
+    }
 
-            while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
-                if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
-                    LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
-                    dsi_writeflush(dsi);
-                    return AFPERR_PARAM;
-                }
-            }
+    while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
+        if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
+            LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
+            dsi_writeflush(dsi);
+            return AFPERR_PARAM;
         }
-        break;
     }
 
     close( si.sdt_fd );
@@ -441,7 +542,7 @@ int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
 #define min(a,b)       ((a)<(b)?(a):(b))
     rc = min( bsize, rsize );
 
-    if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
+    if (buflen < rc) {
         DSI *dsi = obj->dsi;
         struct stat st;
         off_t size;
@@ -459,21 +560,19 @@ int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
          * a problem. much confusion results otherwise. */
         while (*rbuflen > 0) {
 #ifdef WITH_SENDFILE
-            if (!obj->options.flags & OPTION_DEBUG) {
-                if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) {
-                    switch (errno) {
-                    case ENOSYS:
-                    case EINVAL:  /* there's no guarantee that all fs support sendfile */
-                        break;
-                    default:
-                        goto geticon_exit;
-                    }
-                }
-                else {
-                    dsi_readdone(dsi);
-                    return AFP_OK;
+            if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) {
+                switch (errno) {
+                case ENOSYS:
+                case EINVAL:  /* there's no guarantee that all fs support sendfile */
+                    break;
+                default:
+                    goto geticon_exit;
                 }
             }
+            else {
+                dsi_readdone(dsi);
+                return AFP_OK;
+            }
 #endif
             buflen = read(si.sdt_fd, rbuf, *rbuflen);
             if (buflen < 0)
@@ -626,7 +725,7 @@ utompath_error:
 }
 
 /* ------------------------- */
-static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
+static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf)
 {
     struct ofork        *of;
     char                *name, *upath;
@@ -638,7 +737,7 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
     clen = min( clen, 199 );
 
     upath = path->u_name;
-    if (check_access(upath, OPENACC_WR ) < 0) {
+    if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
         return AFPERR_ACCESS;
     }
     
@@ -673,7 +772,7 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
 }
 
 /* ----------------------------- */
-int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
+int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 {
     struct vol         *vol;
     struct dir         *dir;
@@ -704,7 +803,7 @@ int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _
         ibuf++;
     }
 
-    return ad_addcomment(vol, path, ibuf);
+    return ad_addcomment(obj, vol, path, ibuf);
 }
 
 /* -------------------- */
@@ -782,7 +881,7 @@ int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf,
 }
 
 /* ----------------------- */
-static int ad_rmvcomment(struct vol *vol, struct path *path)
+static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path)
 {
     struct adouble     ad, *adp;
     struct ofork        *of;
@@ -790,7 +889,7 @@ static int ad_rmvcomment(struct vol *vol, struct path *path)
     char               *upath;
 
     upath = path->u_name;
-    if (check_access(upath, OPENACC_WR ) < 0) {
+    if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
         return AFPERR_ACCESS;
     }
 
@@ -848,5 +947,5 @@ int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _
        return get_afp_errno(AFPERR_NOOBJ);
     }
     
-    return ad_rmvcomment(vol, s_path);
+    return ad_rmvcomment(obj, vol, s_path);
 }