]> arthur.barton.de Git - netatalk.git/commitdiff
Fixes
authorFrank Lahm <franklahm@googlemail.com>
Wed, 11 Jan 2012 16:09:19 +0000 (17:09 +0100)
committerFrank Lahm <franklahm@googlemail.com>
Wed, 11 Jan 2012 16:09:19 +0000 (17:09 +0100)
etc/afpd/fork.c
include/atalk/adouble.h
libatalk/adouble/ad_flush.c
libatalk/adouble/ad_open.c
libatalk/adouble/ad_read.c
libatalk/adouble/ad_write.c

index 40ae7cdad88b56e6aa63ad821bf419f4207ab79f..6eff75a8f163960cf7cfdcdb975c2acbd251657d 100644 (file)
@@ -1137,6 +1137,9 @@ static ssize_t write_file(struct ofork *ofork, int eid,
         }
     }
 
+    LOG(log_debug, logtype_afpd, "write_file(off: %ju, size: %zu)",
+        (uintmax_t)offset, rbuflen);
+
     if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
                         rbuf, rbuflen)) < 0 ) {
         switch ( errno ) {
@@ -1242,15 +1245,16 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s
     case AFPPROTO_DSI:
     {
         DSI *dsi = obj->handle;
-
         /* find out what we have already and write it out. */
         cc = dsi_writeinit(dsi, rbuf, *rbuflen);
+
         if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
             dsi_writeflush(dsi);
             *rbuflen = 0;
             ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
             return cc;
         }
+
         offset += cc;
 
 #if 0 /*def HAVE_SENDFILE_WRITE*/
index 4539bed828672fc5c6ca54d523ba7a378f0266f7..513308851a1c62ada63482ce33ea737cae5a8dea 100644 (file)
@@ -359,6 +359,7 @@ extern int ad_rebuild_sfm_header (struct adouble *);
 extern int ad_copy_header (struct adouble *, struct adouble *);
 extern int ad_flush (struct adouble *);
 extern int ad_close (struct adouble *, int);
+extern int fsetrsrcea(struct adouble *ad, int fd, const char *eaname, const void *value, size_t size, int flags);
 
 /* ad_lock.c */
 extern int ad_testlock      (struct adouble *adp, int eid, off_t off);
index 0685646667d2d2fab3eaf11b8cdf2f047d5a60a8..52f24f17b36dbd84104eddb54f898dda95d8c766 100644 (file)
@@ -48,6 +48,46 @@ static const uint32_t set_eid[] = {
 
 #define EID_DISK(a) (set_eid[a])
 
+int fsetrsrcea(struct adouble *ad, int fd, const char *eaname, const void *value, size_t size, int flags)
+{
+    if ((ad->ad_maxeafssize == 0) || (ad->ad_maxeafssize >= size)) {
+        LOG(log_debug, logtype_default, "fsetrsrcea(\"%s\"): size: %zu", eaname, size);
+        if (sys_fsetxattr(fd, eaname, value, size, 0) == -1)
+            return -1;
+        return 0;
+    }
+
+    /* rsrcfork is larger then maximum EA support by fs so we have to split it */
+    int i;
+    int eas = (size / ad->ad_maxeafssize);
+    size_t remain = size - (eas * ad->ad_maxeafssize);
+    bstring eachunk;
+
+    LOG(log_debug, logtype_default, "fsetrsrcea(\"%s\"): size: %zu, maxea: %zu, eas: %d, remain: %zu",
+        eaname, size, ad->ad_maxeafssize, eas, remain);
+
+    for (i = 0; i < eas; i++) {
+        if ((eachunk = bformat("%s.%d", eaname, i + 1)) == NULL)
+            return -1;
+        if (sys_fsetxattr(fd, bdata(eachunk), value + (i * ad->ad_maxeafssize), ad->ad_maxeafssize, 0) == -1) {
+            LOG(log_error, logtype_default, "fsetrsrcea(\"%s\"): %s", bdata(eachunk), strerror(errno));
+            bdestroy(eachunk);
+            return -1;
+        }
+        bdestroy(eachunk);
+    }
+
+    if ((eachunk = bformat("%s.%d", eaname, i + 1)) == NULL)
+        return -1;
+    if (sys_fsetxattr(fd, bdata(eachunk), value + (i * ad->ad_maxeafssize), remain, 0) == -1) {
+        LOG(log_error, logtype_default, "fsetrsrcea(\"%s\"): %s", bdata(eachunk), strerror(errno));
+        return -1;
+    }
+    bdestroy(eachunk);
+
+    return 0;
+}
+
 /*
  * Rebuild any header information that might have changed.
  */
@@ -147,6 +187,9 @@ int ad_copy_header(struct adouble *add, struct adouble *ads)
 int ad_flush(struct adouble *ad)
 {
     int len;
+
+    LOG(log_debug, logtype_default, "ad_flush(%s)", adflags2logstr(ad->ad_adflags));
+
     struct ad_fd *adf;
 
     switch (ad->ad_vers) {
@@ -179,11 +222,19 @@ int ad_flush(struct adouble *ad)
             }
             break;
         case AD_VERSION_EA:
-            if (sys_fsetxattr(ad_data_fileno(ad), AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) != 0) {
-                LOG(log_error, logtype_afpd, "ad_flush: sys_fsetxattr error: %s",
-                    strerror(errno));
-                return -1;
+            if (AD_META_OPEN(ad)) {
+                if (sys_fsetxattr(ad_data_fileno(ad), AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) != 0) {
+                    LOG(log_error, logtype_afpd, "ad_flush: sys_fsetxattr error: %s",
+                        strerror(errno));
+                    return -1;
+                }
+            }
+#ifndef HAVE_EAFD
+            if (AD_RSRC_OPEN(ad) && (ad->ad_rlen > 0)) {
+                if (fsetrsrcea(ad, ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1)
+                    return -1;
             }
+#endif
             break;
         default:
             LOG(log_error, logtype_afpd, "ad_flush: unexpected adouble version");
@@ -194,6 +245,21 @@ int ad_flush(struct adouble *ad)
     return( 0 );
 }
 
+static int ad_data_closefd(struct adouble *ad)
+{
+    int ret = 0;
+
+    if (ad_data_fileno(ad) == -2) {
+        free(ad->ad_data_fork.adf_syml);
+        ad->ad_data_fork.adf_syml = NULL;
+    } else {
+        if (close(ad_data_fileno(ad)) < 0)
+            ret = -1;
+    }
+    ad_data_fileno(ad) = -1;
+    return ret;
+}
+
 /*!
  * Close a struct adouble freeing all resources
  */
@@ -209,14 +275,8 @@ int ad_close(struct adouble *ad, int adflags)
     if ((adflags & ADFLAGS_DF)
         && (ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */
         && --ad->ad_data_fork.adf_refcount == 0) {
-        if (ad->ad_data_fork.adf_syml != NULL) {
-            free(ad->ad_data_fork.adf_syml);
-            ad->ad_data_fork.adf_syml = 0;
-        } else {
-            if ( close( ad_data_fileno(ad) ) < 0 )
-                err = -1;
-        }
-        ad_data_fileno(ad) = -1;
+        if (ad_data_closefd(ad) < 0)
+            err = -1;
         adf_lock_free(&ad->ad_data_fork);
     }
 
@@ -234,9 +294,8 @@ int ad_close(struct adouble *ad, int adflags)
         case AD_VERSION_EA:
             if ((ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */ 
                 && !(--ad->ad_data_fork.adf_refcount)) {
-                if (close( ad_data_fileno(ad) ) < 0)
+                if (ad_data_closefd(ad) < 0)
                     err = -1;
-                ad_data_fileno(ad) = -1;
                 adf_lock_free(&ad->ad_data_fork);
             }
             break;
@@ -255,12 +314,21 @@ int ad_close(struct adouble *ad, int adflags)
             break;
 
         case AD_VERSION_EA:
+#ifndef HAVE_EAFD
+            LOG(log_debug, logtype_default, "ad_close: ad->ad_rlen: %zu", ad->ad_rlen);
+            if (ad->ad_rlen > 0)
+                if (fsetrsrcea(ad, ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1)
+                    err = -1;
+#endif
             if ((ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */ 
                 && !(--ad->ad_data_fork.adf_refcount)) {
-                if (close( ad_data_fileno(ad) ) < 0)
+                if (ad_data_closefd(ad) < 0)
                     err = -1;
-                ad_data_fileno(ad) = -1;
                 adf_lock_free(&ad->ad_data_fork);
+                if (ad->ad_resforkbuf)
+                    free(ad->ad_resforkbuf);
+                ad->ad_resforkbuf = NULL;
+                ad->ad_rlen = 0;
             }
             break;
 
index 537cdf6de3bb0f66a8449288f138786a0dc7ca31..e5bc2d102c9d06e40bcb7144d58ed48686abee65 100644 (file)
@@ -469,24 +469,35 @@ static int ad_header_read_ea(struct adouble *ad, struct stat *hst _U_)
     return 0;
 }
 
-static int ad_rsrc_len_ea(struct adouble *ad)
+static int ad_read_rf_ea(struct adouble *ad)
 {
+    EC_INIT;
     ssize_t rlen;
 
     if ((rlen = sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, NULL, 0)) <= 0) {
         switch (errno) {
         case ENOATTR:
         case ENOENT:
-            ad->ad_rlen = 0;
-            break;
+            return 0;
         default:
             LOG(log_error, logtype_default, "ad_refresh_rsrc_len_ea: %s", strerror(errno));
-            ad->ad_rlen = 0;
             return -1;
         }
     }
+
+    if (ad->ad_resforkbuf == NULL) {
+        EC_NULL_LOG( ad->ad_resforkbuf = malloc(rlen) );
+    } else {
+        if (rlen > ad->ad_rlen) {
+            EC_ZERO_LOG( ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, rlen) );
+        }
+    }
     ad->ad_rlen = rlen;
-    return 0;
+
+    EC_NEG1_LOG( sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen) );
+
+EC_CLEANUP:
+    EC_EXIT;
 }
 
 static int ad_mkrf(const char *path)
@@ -909,7 +920,7 @@ static int ad_open_hf(const char *path, int adflags, int mode, struct adouble *a
  */
 static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *ad)
 {
-    int ret = 0;
+    EC_INIT;
     int oflags;
     ssize_t rlen;
 
@@ -931,19 +942,22 @@ static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *a
             return -1;
         }
     } else {
-        if ((ad_data_fileno(ad) = open(path, oflags)) == -1)
-            goto exit;
+        EC_NEG1( (ad_data_fileno(ad) = open(path, oflags)) );
         ad->ad_data_fork.adf_flags = oflags;
         adf_lock_init(&ad->ad_data_fork);
+#ifndef HAVE_EAFD
+        EC_ZERO_LOG( ad_read_rf_ea(ad) );
+#endif
     }
 
-    if ((ret = ad_rsrc_len_ea(ad)) != 0)
-        goto exit;
-
     ad->ad_data_fork.adf_refcount++;
 
-exit:
-    return ret;
+EC_CLEANUP:
+    if (ret != 0) {
+        ad->ad_rlen = 0;
+        ad->ad_adflags &= ~ADFLAGS_RF;
+    }
+    EC_EXIT;
 }
 
 /***********************************************************************************
@@ -1133,6 +1147,8 @@ static void ad_init_func(struct adouble *ad)
     ad->ad_data_fork.adf_refcount = 0;
     ad->ad_data_fork.adf_syml = 0;
     ad->ad_inited = 0;
+//    ad->ad_maxeafssize = 3500;  /* FIXME: option from vol */
+    ad->ad_maxeafssize = 0;     /* no limit */
     return;
 }
 
@@ -1147,8 +1163,6 @@ void ad_init(struct adouble *ad, const struct vol * restrict vol)
 {
     ad->ad_vers = vol->v_adouble;
     ad->ad_options = vol->v_ad_options;
-//    ad->ad_maxeafssize = 3500;  /* FIXME: option from vol */
-    ad->ad_maxeafssize = 0;     /* no limit */
     ad_init_func(ad);
 }
 
@@ -1314,8 +1328,10 @@ int ad_refresh(struct adouble *ad)
     case AD_VERSION_EA:
         if (ad_data_fileno(ad) == -1)
             return -1;
-        if (ad_rsrc_len_ea(ad) != 0)
+#ifndef HAVE_EAFD
+        if (ad_read_rf_ea(ad) != 0)
             return -1;
+#endif
         return ad->ad_ops->ad_header_read(ad, NULL);
         break;
     default:
index 7b8841bb619b01cdf05e22ff0a305572f0f2d01f..9974293f750dd1fde698936d0db7c1ebcbc97885 100644 (file)
@@ -106,46 +106,17 @@ ssize_t ad_read( struct adouble *ad, const uint32_t eid, off_t off, char *buf, c
             break;
 
         case AD_VERSION_EA:
-            if ((rlen = sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, NULL, 0)) <= 0) {
-                switch (errno) {
-                case ENOATTR:
-                case ENOENT:
-                    cc = ad->ad_rlen = 0;
-                    break;
-                default:
-                    LOG(log_error, logtype_default, "ad_read: %s", strerror(errno));
-                    return -1;
-                }
-            }
-            ad->ad_rlen = rlen;
-
+#ifndef HAVE_EAFD
             if (off > ad->ad_rlen) {
                 errno = ERANGE;
                 return -1;
             }
-
-            if (ad->ad_resforkbuf == NULL) {
-                if ((ad->ad_resforkbuf = malloc(ad->ad_rlen)) == NULL) {
-                    ad->ad_rlen = 0;
-                    return -1;
-                }
-            } else {
-                if ((ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, ad->ad_rlen)) == NULL) {
-                    ad->ad_rlen = 0;
-                    return -1;
-                } 
-            }
-
-            if (sys_fgetxattr(ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen) == -1) {
-                ad->ad_rlen = 0;
-                return -1;
-            }       
-
             if ((off + buflen) > ad->ad_rlen)
-                cc = ad->ad_rlen;
+                cc = off + buflen - ad->ad_rlen;
             memcpy(buf, ad->ad_resforkbuf + off, cc);
+#endif
             break;
-        } /* switch (ad->ad_vers) */
+        }
     }
 
     return( cc );
index e745777c58efd53c1253218597662074d85854a6..5ebc73957538b8b97867cbc7d5b75dfb74ca8aae 100644 (file)
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
 #include <atalk/logger.h>
-
-#ifndef MIN
-#define MIN(a,b)       ((a)<(b)?(a):(b))
-#endif /* ! MIN */
-
-static int fsetrsrcea(struct adouble *ad, int fd, const char *eaname, const void *value, size_t size, int flags)
-{
-    if ((ad->ad_maxeafssize == 0) || (ad->ad_maxeafssize >= size)) {
-        if (sys_fsetxattr(fd, eaname, value, size, 0) == -1)
-            return -1;
-        return 0;
-    }
-
-    /* rsrcfork is larger then maximum EA support by fs so we have to split it */
-    int i;
-    int eas = (size / ad->ad_maxeafssize);
-    size_t remain = size - (eas * ad->ad_maxeafssize);
-    bstring eachunk;
-
-    LOG(log_debug, logtype_default, "fsetrsrcea(\"%s\"): size: %zu, maxea: %zu, eas: %d, remain: %zu",
-        eaname, size, ad->ad_maxeafssize, eas, remain);
-
-    for (i = 0; i < eas; i++) {
-        if ((eachunk = bformat("%s.%d", eaname, i + 1)) == NULL)
-            return -1;
-        if (sys_fsetxattr(fd, bdata(eachunk), value + (i * ad->ad_maxeafssize), ad->ad_maxeafssize, 0) == -1) {
-            LOG(log_error, logtype_default, "fsetrsrcea(\"%s\"): %s", bdata(eachunk), strerror(errno));
-            bdestroy(eachunk);
-            return -1;
-        }
-        bdestroy(eachunk);
-    }
-
-    if ((eachunk = bformat("%s.%d", eaname, i + 1)) == NULL)
-        return -1;
-    if (sys_fsetxattr(fd, bdata(eachunk), value + (i * ad->ad_maxeafssize), remain, 0) == -1) {
-        LOG(log_error, logtype_default, "fsetrsrcea(\"%s\"): %s", bdata(eachunk), strerror(errno));
-        return -1;
-    }
-    bdestroy(eachunk);
-
-    return 0;
-}
-
-
+#include <atalk/util.h>
+#include <atalk/errchk.h>
 
 /* XXX: locking has to be checked before each stream of consecutive
  *      ad_writes to prevent a lock in the middle from causing problems. 
@@ -92,6 +49,7 @@ ssize_t adf_pwrite(struct ad_fd *ad_fd, const void *buf, size_t count, off_t off
 /* end is always 0 */
 ssize_t ad_write(struct adouble *ad, uint32_t eid, off_t off, int end, const char *buf, size_t buflen)
 {
+    EC_INIT;
     struct stat                st;
     ssize_t            cc;
     size_t roundup;
@@ -102,6 +60,9 @@ ssize_t ad_write(struct adouble *ad, uint32_t eid, off_t off, int end, const cha
         errno = EACCES;
         return -1;
     }
+
+    LOG(log_debug, logtype_default, "ad_write: off: %ju, size: %zu, eabuflen: %zu",
+        (uintmax_t)off, buflen, ad->ad_rlen);
     
     if ( eid == ADEID_DFORK ) {
         if ( end ) {
@@ -131,23 +92,25 @@ ssize_t ad_write(struct adouble *ad, uint32_t eid, off_t off, int end, const cha
             break;
 
         case AD_VERSION_EA:
-            if (ad->ad_resforkbuf == NULL) {
+#ifndef HAVE_EAFD
+            LOG(log_debug, logtype_default, "ad_write: off: %ju, size: %zu, eabuflen: %zu",
+                (uintmax_t)off, buflen, ad->ad_rlen);
+            if (ad->ad_rlen == 0) {
+                EC_NULL_LOG( ad->ad_resforkbuf = malloc(off + buflen) );
                 ad->ad_rlen = off + buflen;
-                if ((ad->ad_resforkbuf = malloc(ad->ad_rlen)) == NULL) {
-                    ad->ad_rlen = 0;
-                    return -1;
-                }
-            }
-            if ((off + buflen) > ad->ad_rlen) {                
-                if ((ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, off + buflen)) == NULL)
-                    return -1;
+            } else if ((off + buflen) > ad->ad_rlen) {                
+                EC_NULL_LOG( ad->ad_resforkbuf = realloc(ad->ad_resforkbuf, off + buflen) );
                 ad->ad_rlen = off + buflen;
             }
+
             memcpy(ad->ad_resforkbuf + off, buf, buflen);
-            
-            if (fsetrsrcea(ad, ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1)
-                return -1;
+            if (ad->ad_rlen > 0)
+                if (fsetrsrcea(ad, ad_data_fileno(ad), AD_EA_RESO, ad->ad_resforkbuf, ad->ad_rlen, 0) == -1)
+                    ret = -1;
             cc = buflen;
+            LOG(log_debug, logtype_default, "ad_write: off: %ju, size: %zu, eabuflen: %zu",
+                (uintmax_t)off, buflen, ad->ad_rlen);
+#endif
             break;
 
         default:
@@ -157,6 +120,9 @@ ssize_t ad_write(struct adouble *ad, uint32_t eid, off_t off, int end, const cha
         return -1; /* we don't know how to write if it's not a ressource or data fork */
     }
 
+EC_CLEANUP:
+    if (ret != 0)
+        return ret;
     return( cc );
 }