]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/vfs/ea_ad.c
afpd: Solaris locking problem, bug #559
[netatalk.git] / libatalk / vfs / ea_ad.c
index 032c045d3973a7eb9b358a33416eeb595f0a1261..5b99a5c321b2052866307aa161615188ca61b59d 100644 (file)
@@ -25,6 +25,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <dirent.h>
+#include <arpa/inet.h>
 
 #include <atalk/adouble.h>
 #include <atalk/ea.h>
@@ -34,6 +35,7 @@
 #include <atalk/vfs.h>
 #include <atalk/util.h>
 #include <atalk/unix.h>
+#include <atalk/compat.h>
 
 /*
  * Store Extended Attributes inside .AppleDouble folders as follows:
@@ -77,7 +79,7 @@ static char *mtoupath(const struct vol *vol, const char *mpath)
     char         *u;
     size_t       inplen;
     size_t       outlen;
-    uint16_t     flags = CONV_ESCAPEHEX | CONV_ALLOW_COLON;
+    uint16_t     flags = CONV_ESCAPEHEX;
 
     if (!mpath)
         return NULL;
@@ -122,26 +124,30 @@ static int unpack_header(struct ea * restrict ea)
 {
     int ret = 0;
     unsigned int count = 0;
+    uint16_t uint16;
     uint32_t uint32;
     char *buf;
 
     /* Check magic and version */
     buf = ea->ea_data;
-    if (*(uint32_t *)buf != htonl(EA_MAGIC)) {
-        LOG(log_error, logtype_afpd, "unpack_header: wrong magic 0x%08x", *(uint32_t *)buf);
+    memcpy(&uint32, buf, sizeof(uint32_t));
+    if (uint32 != htonl(EA_MAGIC)) {
+        LOG(log_error, logtype_afpd, "unpack_header: wrong magic 0x%08x", uint32);
         ret = -1;
         goto exit;
     }
     buf += 4;
-    if (*(uint16_t *)buf != htons(EA_VERSION)) {
-        LOG(log_error, logtype_afpd, "unpack_header: wrong version 0x%04x", *(uint16_t *)buf);
+    memcpy(&uint16, buf, sizeof(uint16_t));
+    if (uint16 != htons(EA_VERSION)) {
+        LOG(log_error, logtype_afpd, "unpack_header: wrong version 0x%04x", uint16);
         ret = -1;
         goto exit;
     }
     buf += 2;
 
     /* Get EA count */
-    ea->ea_count = ntohs(*(uint16_t *)buf);
+    memcpy(&uint16, buf, sizeof(uint16_t));
+    ea->ea_count = ntohs(uint16);
     LOG(log_debug, logtype_afpd, "unpack_header: number of EAs: %u", ea->ea_count);
     buf += 2;
 
@@ -389,6 +395,8 @@ static int create_ea_header(const char * restrict uname,
 {
     int fd = -1, err = 0;
     char *ptr;
+    uint16_t uint16;
+    uint32_t uint32;
 
     if ((fd = open(uname, O_RDWR | O_CREAT | O_EXCL, 0666 & ~ea->vol->v_umask)) == -1) {
         LOG(log_error, logtype_afpd, "ea_create: open race condition with ea header for file: %s", uname);
@@ -404,11 +412,15 @@ static int create_ea_header(const char * restrict uname,
 
     /* Now init it */
     ptr = ea->ea_data;
-    *(uint32_t *)ptr = htonl(EA_MAGIC);
+    uint32 = htonl(EA_MAGIC);
+    memcpy(ptr, &uint32, sizeof(uint32_t));
     ptr += EA_MAGIC_LEN;
-    *(uint16_t *)ptr = htons(EA_VERSION);
+
+    uint16 = htons(EA_VERSION);
+    memcpy(ptr, &uint16, sizeof(uint16_t));
     ptr += EA_VERSION_LEN;
-    *(uint16_t *)ptr = 0;       /* count */
+
+    memset(ptr, 0, 2);          /* count */
 
     ea->ea_size = EA_HEADER_SIZE;
     ea->ea_inited = EA_INITED;
@@ -514,13 +526,15 @@ static int ea_delentry(struct ea * restrict ea, const char * restrict attruname)
     unsigned int count = 0;
 
     if (ea->ea_count == 0) {
-        LOG(log_error, logtype_afpd, "ea_delentry('%s'): illegal ea_count of 0 on deletion");
+        LOG(log_error, logtype_afpd, "ea_delentry('%s'): illegal ea_count of 0 on deletion",
+            attruname);
         return -1;
     }
 
     while (count < ea->ea_count) {
         /* search matching EA */
-        if (strcmp(attruname, (*ea->ea_entries)[count].ea_name) == 0) {
+        if ((*ea->ea_entries)[count].ea_name &&
+            strcmp(attruname, (*ea->ea_entries)[count].ea_name) == 0) {
             free((*ea->ea_entries)[count].ea_name);
             (*ea->ea_entries)[count].ea_name = NULL;
 
@@ -892,7 +906,7 @@ int ea_close(struct ea * restrict ea)
             if (ea->ea_count == 0) {
                 /* Check if EA header exists and remove it */
                 eaname = ea_path(ea, NULL, 0);
-                if ((lstatat(ea->dirfd, eaname, &st)) == 0) {
+                if ((statat(ea->dirfd, eaname, &st)) == 0) {
                     if ((netatalk_unlinkat(ea->dirfd, eaname)) != 0) {
                         LOG(log_error, logtype_afpd, "ea_close('%s'): unlink: %s",
                             eaname, strerror(errno));
@@ -1051,7 +1065,7 @@ int get_easize(VFS_FUNC_ARGS_EA_GETSIZE)
  */
 int get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT)
 {
-    int ret = AFPERR_MISC, fd = -1;
+    int ret = AFPERR_MISC;
     unsigned int count = 0;
     uint32_t uint32;
     size_t toread;
@@ -1393,8 +1407,8 @@ int ea_renamefile(VFS_FUNC_ARGS_RENAMEFILE)
     if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
         if (errno == ENOENT) {
             /* Possibly the .AppleDouble folder didn't exist, we create it and try again */
-            ad_init(&ad, vol->v_adouble, vol->v_ad_options); 
-            if ((ad_open(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666)) != 0) {
+            ad_init(&ad, vol); 
+            if ((ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666)) != 0) {
                 LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): ad_open error: '%s'", src, dst, dst);
                 ret = AFPERR_MISC;
                 goto exit;
@@ -1490,8 +1504,8 @@ int ea_copyfile(VFS_FUNC_ARGS_COPYFILE)
     if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
         if (errno == ENOENT) {
             /* Possibly the .AppleDouble folder didn't exist, we create it and try again */
-            ad_init(&ad, vol->v_adouble, vol->v_ad_options); 
-            if ((ad_open(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666)) != 0) {
+            ad_init(&ad, vol);
+            if ((ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666)) != 0) {
                 LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): ad_open error: '%s'", src, dst, dst);
                 ret = AFPERR_MISC;
                 goto exit;
@@ -1569,7 +1583,7 @@ int ea_chown(VFS_FUNC_ARGS_CHOWN)
         }
     }
 
-    if ((lchown(ea_path(&ea, NULL, 0), uid, gid)) != 0) {
+    if ((ochown(ea_path(&ea, NULL, 0), uid, gid, vol_syml_opt(vol))) != 0) {
         switch (errno) {
         case EPERM:
         case EACCES:
@@ -1586,7 +1600,7 @@ int ea_chown(VFS_FUNC_ARGS_CHOWN)
             ret = AFPERR_MISC;
             goto exit;
         }
-        if ((lchown(eaname, uid, gid)) != 0) {
+        if ((ochown(eaname, uid, gid, vol_syml_opt(vol))) != 0) {
             switch (errno) {
             case EPERM:
             case EACCES:
@@ -1630,7 +1644,7 @@ int ea_chmod_file(VFS_FUNC_ARGS_SETFILEMODE)
     }
 
     /* Set mode on EA header file */
-    if ((setfilmode(ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL, vol->v_umask)) != 0) {
+    if ((setfilmode(vol, ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL)) != 0) {
         LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): %s", ea_path(&ea, NULL, 0), strerror(errno));
         switch (errno) {
         case EPERM:
@@ -1649,7 +1663,7 @@ int ea_chmod_file(VFS_FUNC_ARGS_SETFILEMODE)
             ret = AFPERR_MISC;
             goto exit;
         }
-        if ((setfilmode(eaname, ea_mode(mode), NULL, vol->v_umask)) != 0) {
+        if ((setfilmode(vol, eaname, ea_mode(mode), NULL)) != 0) {
             LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): %s", eaname, strerror(errno));
             switch (errno) {
             case EPERM:
@@ -1680,33 +1694,25 @@ int ea_chmod_dir(VFS_FUNC_ARGS_SETDIRUNIXMODE)
 
     int ret = AFP_OK;
     unsigned int count = 0;
-    uid_t uid;
     const char *eaname;
     const char *eaname_safe = NULL;
     struct ea ea;
 
     LOG(log_debug, logtype_afpd, "ea_chmod_dir('%s')", name);
     /* .AppleDouble already might be inaccesible, so we must run as id 0 */
-    uid = geteuid();
-    if (seteuid(0)) {
-        LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): seteuid: %s", name, strerror(errno));
-        return AFPERR_MISC;
-    }
+    become_root();
 
     /* Open EA stuff */
     if ((ea_open(vol, name, EA_RDWR, &ea)) != 0) {
         /* ENOENT --> no EA files, nothing to do */
         if (errno != ENOENT)
             ret = AFPERR_MISC;
-        if (seteuid(uid) < 0) {
-            LOG(log_error, logtype_afpd, "can't seteuid back: %s", strerror(errno));
-            exit(EXITERR_SYS);
-        }
+        unbecome_root();
         return ret;
     }
 
     /* Set mode on EA header */
-    if ((setfilmode(ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL, vol->v_umask)) != 0) {
+    if ((setfilmode(vol, ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL)) != 0) {
         LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): %s", ea_path(&ea, NULL, 0), strerror(errno));
         switch (errno) {
         case EPERM:
@@ -1736,7 +1742,7 @@ int ea_chmod_dir(VFS_FUNC_ARGS_SETDIRUNIXMODE)
             ret = AFPERR_MISC;
             goto exit;
         }
-        if ((setfilmode(eaname, ea_mode(mode), NULL, vol->v_umask)) != 0) {
+        if ((setfilmode(vol, eaname, ea_mode(mode), NULL)) != 0) {
             LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): %s", eaname, strerror(errno));
             switch (errno) {
             case EPERM:
@@ -1754,10 +1760,7 @@ int ea_chmod_dir(VFS_FUNC_ARGS_SETDIRUNIXMODE)
     }
 
 exit:
-    if (seteuid(uid) < 0) {
-        LOG(log_error, logtype_afpd, "can't seteuid back: %s", strerror(errno));
-        exit(EXITERR_SYS);
-    }
+    unbecome_root();
 
     if ((ea_close(&ea)) != 0) {
         LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): error closing ea handle", name);