]> arthur.barton.de Git - netatalk.git/commitdiff
Time Machine support: new volume option tm
authorfranklahm <franklahm>
Mon, 7 Sep 2009 11:35:04 +0000 (11:35 +0000)
committerfranklahm <franklahm>
Mon, 7 Sep 2009 11:35:04 +0000 (11:35 +0000)
NEWS
config/AppleVolumes.default.tmpl
etc/afpd/directory.c
etc/afpd/directory.h
etc/afpd/fork.c
etc/afpd/fork.h
etc/afpd/switch.c
etc/afpd/volume.c
etc/afpd/volume.h
include/atalk/afp.h

diff --git a/NEWS b/NEWS
index e4cc881ceb3d54982e7cbbdf378c76acaa017538..05c3ca9dcca4494f18c9b662605ac4422a4eb22f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
 Changes in 2.0.5
 ================
 
+* NEW: afpd: Time Machine support with new volume option "tm".
 * FIX: papd: Remove variable expansion for BSD printers. Fixes CVE-2008-5718.
 * FIX: afpd: .AppleDxxx folders were user accessible if option 'usedots'
        was set 
index a018421ea84ddddff6c2daf0b6bdd1bd53e08cfc..63e3e3cc8143c78115c49726c760499d6816b935 100644 (file)
@@ -74,6 +74,7 @@
 #                       requested perm
 #
 # miscellaneous options [syntax: options:option1,option2]:
+# tm                  -> enable TimeMachine support
 # prodos              -> make compatible with appleII clients.
 # crlf                -> enable crlf translation for TEXT files.
 # noadouble           -> don't create .AppleDouble unless a resource
index 85e0b3c997e787a2af2d939ae8b77be9595ecf57..0a5f0893fe71f5934556f2fb94188d99e066a502 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.71.2.4.2.15.2.13 2009-09-01 12:34:38 franklahm Exp $
+ * $Id: directory.c,v 1.71.2.4.2.15.2.14 2009-09-07 11:35:04 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -1969,6 +1969,99 @@ setdirparam_done:
     return err;
 }
 
+int afp_syncdir(obj, ibuf, ibuflen, rbuf, rbuflen )
+AFPObj  *obj _U_;
+char    *ibuf, *rbuf _U_;
+int     ibuflen _U_, *rbuflen;
+{
+#ifdef HAVE_DIRFD
+    DIR                  *dp;
+#endif
+    int                  dfd;
+    struct vol           *vol;
+    struct dir           *dir;
+    u_int32_t            did;
+    u_int16_t            vid;
+
+    *rbuflen = 0;
+    ibuf += 2;
+
+    memcpy( &vid, ibuf, sizeof( vid ));
+    ibuf += sizeof( vid );
+    if (NULL == (vol = getvolbyvid( vid )) ) {
+        return( AFPERR_PARAM );
+    }
+
+    memcpy( &did, ibuf, sizeof( did ));
+    ibuf += sizeof( did );
+
+    /* 
+     * Here's the deal:
+     * if it's CNID 2 our only choice to meet the specs is call sync.
+     * For any other CNID just sync that dir. To my knowledge the
+     * intended use of FPSyncDir is to sync the volume so all we're
+     * ever going to see here is probably CNID 2. Anyway, we' prepared.
+    */
+
+    if ( ntohl(did) == 2 ) {
+        sync();
+    } else {
+        if (NULL == ( dir = dirlookup( vol, did )) ) {
+            return afp_errno; /* was AFPERR_NOOBJ */
+        }
+        
+        if (movecwd( vol, dir ) < 0 )
+            return ( AFPERR_NOOBJ ); 
+        
+        /*
+         * Assuming only OSens that have dirfd also may require fsyncing directories
+         * in order to flush metadata e.g. Linux.
+         */
+    
+#ifdef HAVE_DIRFD
+        if (NULL == ( dp = opendir( "." )) ) {
+            switch( errno ) {
+            case ENOENT :
+                return( AFPERR_NOOBJ );
+            case EACCES :
+            return( AFPERR_ACCESS );
+            default :
+                return( AFPERR_PARAM );
+            }
+        }
+        
+        LOG(log_debug, logtype_afpd, "afp_syncdir: dir: '%s'", dir->d_u_name);
+        
+        dfd = dirfd( dp );
+        if ( fsync ( dfd ) < 0 )
+            LOG(log_error, logtype_afpd, "afp_syncdir(%s):  %s",
+                dir->d_u_name, strerror(errno) );
+        closedir(dp); /* closes dfd too */
+#endif
+        
+        if ( -1 == (dfd = open(vol->ad_path(".", ADFLAGS_DIR), O_RDWR))) {
+            switch( errno ) {
+            case ENOENT:
+                return( AFPERR_NOOBJ );
+        case EACCES:
+            return( AFPERR_ACCESS );
+            default:
+                return( AFPERR_PARAM );
+            }        
+        }
+        
+        LOG(log_debug, logtype_afpd, "afp_syncdir: ad-file: '%s'",
+            vol->ad_path(".", ADFLAGS_DIR) );
+        
+        if ( fsync(dfd) < 0 )
+            LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s",
+                vol->ad_path(dir->d_u_name, ADFLAGS_DIR), strerror(errno) );
+        close(dfd);
+    }
+
+    return ( AFP_OK );
+}
+
 int afp_createdir(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj  *obj;
 char   *ibuf, *rbuf;
index 12b64790434ca173248ec3ab7f86b0d2cf324c94..d5c6b733adde7f08a2395d416a698494c27b9842 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.h,v 1.13.2.4.2.2.2.1 2008-11-25 15:16:32 didg Exp $
+ * $Id: directory.h,v 1.13.2.4.2.2.2.2 2009-09-07 11:35:04 franklahm Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -227,6 +227,7 @@ extern int  afp_setdirparams __P((AFPObj *, char *, int, char *, int *));
 extern int      afp_closedir __P((AFPObj *, char *, int, char *, int *));
 extern int     afp_mapid __P((AFPObj *, char *, int, char *, int *));
 extern int     afp_mapname __P((AFPObj *, char *, int, char *, int *));
+extern int     afp_syncdir __P((AFPObj *, char *, int, char *, int *));
 
 /* from enumerate.c */
 extern int     afp_enumerate __P((AFPObj *, char *, unsigned int, char *, unsigned int *));
index c537c03b6ff16ad7daa79dcfd44a4cd34968d317..17a311603e204eee574e9bf6b8a27eed71e2c088 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.c,v 1.51.2.2.2.10.2.6 2008-11-25 15:16:33 didg Exp $
+ * $Id: fork.c,v 1.51.2.2.2.10.2.7 2009-09-07 11:35:04 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -1102,6 +1102,39 @@ int      ibuflen _U_, *rbuflen;
     return( AFP_OK );
 }
 
+/*
+  FIXME
+  There is a lot to tell about fsync, fdatasync, F_FULLFSYNC.
+  fsync(2) on OSX is implemented differently than on other platforms.
+  see: http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf.
+ */
+int afp_syncfork(obj, ibuf, ibuflen, rbuf, rbuflen )
+    AFPObj  *obj _U_;
+    char    *ibuf, *rbuf _U_;
+    int     ibuflen _U_, *rbuflen;
+{
+    struct ofork        *ofork;
+    u_int16_t           ofrefnum;
+
+    *rbuflen = 0;
+    ibuf += 2;
+
+    memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
+    ibuf += sizeof( ofrefnum );
+
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
+        LOG(log_error, logtype_afpd, "afpd_syncfork: of_find(%d) could not locate fork", ofrefnum );
+        return( AFPERR_PARAM );
+    }
+
+    if ( flushfork( ofork ) < 0 ) {
+       LOG(log_error, logtype_afpd, "flushfork(%s): %s", of_name(ofork), strerror(errno) );
+       return AFPERR_MISC;
+    }
+
+    return( AFP_OK );
+}
+
 /* this is very similar to closefork */
 int flushfork( ofork )
 struct ofork   *ofork;
index 0e7f7739f231b1e32972fc37f5f5cbddf4974137..8a67974fdfb47de5da6d5b7e74a445732942d4ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.h,v 1.8.6.2.2.3 2008-11-25 15:16:33 didg Exp $
+ * $Id: fork.h,v 1.8.6.2.2.4 2009-09-07 11:35:04 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -87,4 +87,5 @@ extern int    afp_closefork __P((AFPObj *, char *, int, char *, int *));
 extern int     afp_bytelock_ext __P((AFPObj *, char *, int, char *, int *));
 extern int     afp_read_ext __P((AFPObj *, char *, int, char *, int *));
 extern int     afp_write_ext __P((AFPObj *, char *, int, char *, int *));
+extern int  afp_syncfork __P((AFPObj *, char *, int, char *, int *));
 #endif
index 7fa024252fa6b7daeebf325a7a4f81dd0d2b4b86..dce7095987c24507e2176732c2f5ed88dbd6450d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: switch.c,v 1.12.8.1 2005-09-27 10:40:41 didg Exp $
+ * $Id: switch.c,v 1.12.8.2 2009-09-07 11:35:04 franklahm Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -152,7 +152,7 @@ int (*postauth_switch[])() = {
     NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL,                                    /*  64 -  71 */
     NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL,                                    /*  72 -  79 */
+    NULL, NULL, afp_syncdir, afp_syncfork,     /*  72 -  79 */
     NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL,                                    /*  80 -  87 */
     NULL, NULL, NULL, NULL,
index 243e7498c0edb2eaa734c78d290c9faf71c1db78..4dc14c3b22f4eaa413f130d784d5d2f4b74067e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.c,v 1.51.2.7.2.33.2.24 2009-03-26 11:53:32 franklahm Exp $
+ * $Id: volume.c,v 1.51.2.7.2.33.2.25 2009-09-07 11:35:04 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -175,6 +175,7 @@ static const _vol_opt_name vol_opt_names[] = {
     {AFPVOL_NODEV,      "NODEV"},       /* always use 0 for device number in cnid calls */
     {AFPVOL_EILSEQ,     "ILLEGALSEQ"},  /* encode illegal sequence */
     {AFPVOL_CACHE,      "CACHEID"},     /* Use adouble v2 CNID caching, default don't use it */
+    {AFPVOL_TM,         "TM"},          /* Set "kSupportsTMLockSteal" is volume attributes */
     {0, NULL}
 };
 
@@ -480,6 +481,8 @@ static void volset(struct vol_option *options, struct vol_option *save,
                 options[VOLOPT_FLAGS].i_value |= AFPVOL_EILSEQ;
             else if (strcasecmp(p, "cachecnid") == 0)
                 options[VOLOPT_FLAGS].i_value |= AFPVOL_CACHE;
+            else if (strcasecmp(p, "tm") == 0)
+                options[VOLOPT_FLAGS].i_value |= AFPVOL_TM;
 
             p = strtok(NULL, ",");
         }
@@ -1401,8 +1404,10 @@ int              *buflen;
             ashort |= VOLPBIT_ATTR_CATSEARCH;
             if (afp_version >= 30) {
                 ashort |= VOLPBIT_ATTR_UTF8;
-               if (vol->v_flags & AFPVOL_UNIX_PRIV)
-                   ashort |= VOLPBIT_ATTR_UNIXPRIV;
+                if (vol->v_flags & AFPVOL_UNIX_PRIV)
+                    ashort |= VOLPBIT_ATTR_UNIXPRIV;
+                if (vol->v_flags & AFPVOL_TM)
+                    ashort |= VOLPBIT_ATTR_TM;
             }
             ashort = htons(ashort);
             memcpy(data, &ashort, sizeof( ashort ));
index 5aafab77378cb26b45ad1c9c853f08094269a98f..dcd62e9b7be674aadff78b07a311b1b0541589f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.h,v 1.19.2.5.2.7.2.5 2009-01-28 05:37:58 didg Exp $
+ * $Id: volume.h,v 1.19.2.5.2.7.2.6 2009-09-07 11:35:05 franklahm Exp $
  *
  * Copyright (c) 1990,1994 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -124,6 +124,7 @@ this is going away. */
 
 #define AFPVOL_CACHE     (1 << 21)   /* Use adouble v2 CNID caching, default don't use it */
 #define AFPVOL_INV_DOTS  (1 << 22)   /* dots files are invisible */
+#define AFPVOL_TM        (1 << 23)   /* Supports TimeMachine */
 
 /* FPGetSrvrParms options */
 #define AFPSRVR_CONFIGINFO     (1 << 0)
@@ -157,6 +158,7 @@ int wincheck(const struct vol *vol, const char *path);
 #define VOLPBIT_ATTR_UNIXPRIV     (1 << 5)
 #define VOLPBIT_ATTR_UTF8         (1 << 6)
 #define VOLPBIT_ATTR_NONETUID     (1 << 7)
+#define VOLPBIT_ATTR_TM           (1 << 13)
 
 #define VOLPBIT_ATTR   0
 #define VOLPBIT_SIG    1
index 85a79747b770197df3d2dc1b5448352a2079f185..5b7ef635b914b38cfebb29284aa80e3dde8b715a 100644 (file)
@@ -199,6 +199,7 @@ typedef enum {
 
 /* version 3.1 */
 #define AFP_ENUMERATE_EXT2      68
+#define AFP_SYNCDIR             78
+#define AFP_SYNCFORK            79
 #define AFP_ZZZ                 122
-
 #endif