From: franklahm Date: Mon, 7 Sep 2009 11:35:04 +0000 (+0000) Subject: Time Machine support: new volume option tm X-Git-Tag: netatalk-2-0-5-rc1~1 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=commitdiff_plain;h=5447b10e1ea30a83c7af9790b557fea7337be400 Time Machine support: new volume option tm --- diff --git a/NEWS b/NEWS index e4cc881c..05c3ca9d 100644 --- 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 diff --git a/config/AppleVolumes.default.tmpl b/config/AppleVolumes.default.tmpl index a018421e..63e3e3cc 100644 --- a/config/AppleVolumes.default.tmpl +++ b/config/AppleVolumes.default.tmpl @@ -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 diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index 85e0b3c9..0a5f0893 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -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; diff --git a/etc/afpd/directory.h b/etc/afpd/directory.h index 12b64790..d5c6b733 100644 --- a/etc/afpd/directory.h +++ b/etc/afpd/directory.h @@ -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 *)); diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index c537c03b..17a31160 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -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; diff --git a/etc/afpd/fork.h b/etc/afpd/fork.h index 0e7f7739..8a67974f 100644 --- a/etc/afpd/fork.h +++ b/etc/afpd/fork.h @@ -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 diff --git a/etc/afpd/switch.c b/etc/afpd/switch.c index 7fa02425..dce70959 100644 --- a/etc/afpd/switch.c +++ b/etc/afpd/switch.c @@ -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, diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index 243e7498..4dc14c3b 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -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 )); diff --git a/etc/afpd/volume.h b/etc/afpd/volume.h index 5aafab77..dcd62e9b 100644 --- a/etc/afpd/volume.h +++ b/etc/afpd/volume.h @@ -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 diff --git a/include/atalk/afp.h b/include/atalk/afp.h index 85a79747..5b7ef635 100644 --- a/include/atalk/afp.h +++ b/include/atalk/afp.h @@ -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