]> arthur.barton.de Git - netatalk.git/commitdiff
autogenerate UUIDs for TM volumes and store em in afp_voluuid.conf
authorFrank Lahm <franklahm@googlemail.com>
Sat, 26 Jun 2010 09:39:12 +0000 (11:39 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Sat, 26 Jun 2010 09:39:12 +0000 (11:39 +0200)
13 files changed:
bin/misc/uuidtest.c
configure.in
etc/afpd/Makefile.am
etc/afpd/acls.c
etc/afpd/acls.h
etc/afpd/afp_options.c
etc/afpd/auth.c
etc/afpd/globals.h
etc/afpd/volume.c
etc/afpd/volume.h
include/atalk/uuid.h
libatalk/acl/cache.c
libatalk/adouble/ad_open.c

index 826d3d918d184dc4b7fdefbdfd0dfebad59f52e5..524e25b7a138b8d9e4fc6a3775efa0a15581d897 100644 (file)
@@ -68,7 +68,7 @@ int main( int argc, char **argv)
 {
     int ret, i, c;
     int verbose = 0;
-    uuid_t uuid;
+    atalk_uuid_t uuid;
     uuidtype_t type;
     char *uuidstring = NULL;
     char *name = NULL;
index 4222a2221eb9d19701d3922d93a4aea36f6173e3..a8fbc9c320597356898cc527f439bdd98c669594 100644 (file)
@@ -1283,6 +1283,14 @@ fi
 dnl --------------------- Netatalk Webmin
 NETATALK_WEBMIN
 
+dnl --------------------- Check for libuuid which is required for TimeMachine
+AC_SEARCH_LIBS([uuid_generate],
+               [uuid], ,
+               AC_MSG_ERROR([missing library libuuid required for TimeMachine]))
+AC_CHECK_HEADER([uuid/uuid.h],
+                AC_DEFINE([HAVE_UUID], 1, [have libuuid]),
+                AC_MSG_ERROR([missing header <uuid/uuid.> from libuuid required for TimeMachine]))
+
 dnl --------------------- last minute substitutions
 
 AC_SUBST(LIBS)
index f539d899d7a5506ca0f136ccc539e7e75be89efc..d08b87029e1fc4ee3db62a747d2e5815be28a3b7 100644 (file)
@@ -25,6 +25,7 @@ afpd_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys \
         -D_PATH_AFPDSIGCONF=\"$(pkgconfdir)/afp_signature.conf\" \
         -D_PATH_AFPDUAMPATH=\"$(UAMS_PATH)/\" \
         -D_PATH_ACL_LDAPCONF=\"$(pkgconfdir)/afp_ldap.conf\" \
+        -D_PATH_AFPDUUIDCONF=\"$(pkgconfdir)/afp_voluuid.conf\" \
         -DAPPLCNAME \
         -DSERVERTEXT=\"$(SERVERTEXT)/\"
 
index 2f5b49b89076dfcb0f48cf8434ef1e00ba8be59b..1ab8b7e3b6edd3a564190a33f28667c860a3dae9 100644 (file)
@@ -1233,7 +1233,7 @@ int afp_setacl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
 void acltoownermode(char *path, struct stat *st, uid_t uid, struct maccess *ma)
 {
     struct passwd *pw;
-    uuid_t uuid;
+    atalk_uuid_t uuid;
     int r_ok, w_ok, x_ok;
 
     if ( ! (AFPobj->options.flags & OPTION_UUID) || ! (AFPobj->options.flags & OPTION_ACL2OS9MODE))
index 4965c56b852a4d8b2876b89d474143a33038a16d..fb0792c3af19e7b3972284b51fc90b26bdabc1a1 100644 (file)
@@ -19,7 +19,7 @@
 #include <sys/acl.h>
 #endif
 
-#include <atalk/uuid.h>                /* for uuid_t */
+#include <atalk/uuid.h>                /* for atalk_uuid_t */
 
 /*
  * This is what Apple says about ACL flags in sys/kauth.h:
@@ -93,7 +93,7 @@ enum {
 
 /* Access Control List Entry (ACE) */
 typedef struct {
-    uuid_t      darwin_ace_uuid;
+    atalk_uuid_t      darwin_ace_uuid;
     uint32_t    darwin_ace_flags;
     uint32_t    darwin_ace_rights;
 } darwin_ace_t;
index 92b7454286c0995c7fd8db43e5b3a00928903e35..8c329972f60dcecfb7a46720a0cf1562c8199ca3 100644 (file)
@@ -165,6 +165,7 @@ void afp_options_init(struct afp_options *options)
     options->systemvol.name = _PATH_AFPDSYSVOL;
     options->configfile = _PATH_AFPDCONF;
     options->sigconffile = _PATH_AFPDSIGCONF;
+    options->uuidconf = _PATH_AFPDUUIDCONF;
     options->uampath = _PATH_AFPDUAMPATH;
     options->uamlist = "uams_dhx.so,uams_dhx2.so";
     options->guest = "nobody";
index 13fade675bc382953de66acf62bde5c3d902b1a8..8dc59ec2ed926665fbb8dcb8eaf3d278878a5612 100644 (file)
@@ -1002,7 +1002,7 @@ int afp_getuserinfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf,
 #ifdef HAVE_ACLS
     if (bitmap & USERIBIT_UUID) {
         int ret;
-        uuid_t uuid;
+        atalk_uuid_t uuid;
         char *uuidstring;
 
         if ( ! (obj->options.flags & OPTION_UUID))
index b604cf22c41eeba27099aa77eb11378a7e8ce3dd..5fbb048b1bde766f2304fc59499db22bcdb91763 100644 (file)
@@ -64,6 +64,7 @@ struct afp_options {
     char *uampath, *fqdn;
     char *pidfile;
     char *sigconffile;
+    char *uuidconf;
     struct afp_volume_name defaultvol, systemvol, uservol;
     int  closevol;
 
index c2c18f2f9f6f616f7b5b5bbbbc27f2f10a45c290..cfa2ea0a67ed93fe95d652dcb484d93de3971631 100644 (file)
@@ -35,6 +35,9 @@ char *strchr (), *strrchr ();
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+
+#include <uuid/uuid.h>
+
 #include <atalk/asp.h>
 #include <atalk/dsi.h>
 #include <atalk/adouble.h>
@@ -119,9 +122,8 @@ static void             free_extmap(void);
 #define VOLOPT_EA_VFS        27  /* Extended Attributes vfs indirection */
 #define VOLOPT_CNIDSERVER    28  /* CNID Server ip address*/
 #define VOLOPT_CNIDPORT      30  /* CNID server tcp port */
-#define VOLOPT_UUID          31  /* CNID server tcp port */
 
-#define VOLOPT_MAX           32  /* <== IMPORTANT !!!!!! */
+#define VOLOPT_MAX           31  /* <== IMPORTANT !!!!!! */
 #define VOLOPT_NUM           (VOLOPT_MAX + 1)
 
 #define VOLPASSLEN  8
@@ -569,9 +571,6 @@ static void volset(struct vol_option *options, struct vol_option *save,
     } else if (optionok(tmp, "volsizelimit:", val)) {
         options[VOLOPT_LIMITSIZE].i_value = (uint32_t)strtoul(val + 1, NULL, 10);
 
-    } else if (optionok(tmp, "uuid:", val)) {
-        setoption(options, save, VOLOPT_UUID, val);
-
     } else {
         /* ignore unknown options */
         LOG(log_debug, logtype_afpd, "ignoring unknown volume option: %s", tmp);
@@ -793,9 +792,6 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
         if (options[VOLOPT_LIMITSIZE].i_value)
             volume->v_limitsize = options[VOLOPT_LIMITSIZE].i_value;
 
-        if (options[VOLOPT_UUID].c_value)
-            volume->v_uuid = strdup(options[VOLOPT_UUID].c_value);
-
         /* Mac to Unix conversion flags*/
         volume->v_mtou_flags = 0;
         if (!(volume->v_flags & AFPVOL_NOHEX))
@@ -857,6 +853,20 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
         check_ea_sys_support(volume);
     initvol_vfs(volume);
 
+    /* get/store uuid from file */
+    if (volume->v_flags & AFPVOL_TM) {
+        char *uuid = get_uuid(obj, volume->v_localname);
+        if (!uuid) {
+            LOG(log_error, logtype_afpd, "Volume '%s': couldn't get UUID, disabling TM support",
+                volume->v_localname);
+            volume->v_flags &= ~AFPVOL_TM;
+        } else {
+            volume->v_uuid = uuid;
+            LOG(log_debug, logtype_afpd, "Volume '%s': UUID '%s'",
+                volume->v_localname, volume->v_uuid);
+        }
+    }
+
     volume->v_next = Volumes;
     Volumes = volume;
     return 0;
@@ -1317,6 +1327,8 @@ static void volume_free(struct vol *vol)
     free(vol->v_forceuid);
     free(vol->v_forcegid);
 #endif /* FORCE_UIDGID */
+    if (vol->v_uuid)
+        free(vol->v_uuid);
 }
 
 /* ------------------------------- */
@@ -1747,7 +1759,7 @@ void load_volumes(AFPObj *obj)
     if ( obj->options.flags & OPTION_USERVOLFIRST ) {
         readvolfile(obj, &obj->options.systemvol, NULL, 0, pwent );
     }
-    
+
     if ( obj->options.closevol ) {
         struct vol *vol;
 
@@ -1889,7 +1901,7 @@ static int volume_openDB(struct vol *volume)
     LOG(log_info, logtype_afpd, "CNID server: %s:%s",
         volume->v_cnidserver ? volume->v_cnidserver : Cnid_srv,
         volume->v_cnidport ? volume->v_cnidport : Cnid_port);
-    
+
 #if 0
 /* Found this in branch dir-rewrite, maybe we want to use it sometimes */
 
@@ -1942,11 +1954,11 @@ static int volume_openDB(struct vol *volume)
     return (!volume->v_cdb)?-1:0;
 }
 
-/* 
-   Check if the underlying filesystem supports EAs for ea:sys volumes.
-   If not, switch to ea:ad.
-   As we can't check (requires write access) on ro-volumes, we switch ea:auto
-   volumes that are options:ro to ea:none.
+/*
+  Check if the underlying filesystem supports EAs for ea:sys volumes.
+  If not, switch to ea:ad.
+  As we can't check (requires write access) on ro-volumes, we switch ea:auto
+  volumes that are options:ro to ea:none.
 */
 static void check_ea_sys_support(struct vol *vol)
 {
@@ -2111,7 +2123,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
     if ((tmp = strdup(volume->v_path)) == NULL) {
         free(volume->v_path);
         return AFPERR_MISC;
-    } 
+    }
     free(volume->v_path);
     volume->v_path = tmp;
 #endif
@@ -2578,7 +2590,7 @@ static int create_special_folder (const struct vol *vol, const struct _special_f
             free(q);
             return (-1);
         }
-        
+
         ad_setname(&ad, folder->name);
 
         ad_getattr(&ad, &attr);
@@ -2623,3 +2635,92 @@ void unload_volumes_and_extmap(void)
     free_extmap();
     free_volumes();
 }
+
+/* 
+ * Get a volumes UUID from the config file.
+ * If there is none, it is generated and stored there.
+ *
+ * Returns pointer to allocated storage on success, NULL on error.
+ */
+char *get_uuid(const AFPObj *obj, const char *volname)
+{
+    struct stat st;
+
+    char *usersign;
+    int fd, i;
+    struct stat tmpstat;
+    char *volname_conf;
+    int header = 0;
+    char buf[1024], uuid[UUID_PRINTABLE_STRING_LENGTH], *p;
+    FILE *fp, *randomp;
+    size_t len;
+    
+    if ((fp = fopen(obj->options.uuidconf, "r")) != NULL) {  /* read open? */
+        /* scan in the conf file */
+        while (fgets(buf, sizeof(buf), fp) != NULL) { 
+            p = buf;
+            while (p && isblank(*p))
+                p++;
+            if (!p || (*p == '#') || (*p == '\n'))
+                continue;                             /* invalid line */
+            if (*p == '"') {
+                p++;
+                if ((volname_conf = strtok( p, "\"" )) == NULL)
+                    continue;                         /* syntax error */
+            } else {
+                if ((volname_conf = strtok( p, " \t" )) == NULL)
+                    continue;                         /* syntax error: invalid name */
+            }
+            p = strchr(p, '\0');
+            p++;
+            if (*p == '\0')
+                continue;                             /* syntax error */
+            
+            if (strcmp(volname, volname_conf) != 0)
+                continue;                             /* another volume name */
+                
+            while (p && isblank(*p))
+                p++;
+
+            if (sscanf(p, "%36s", uuid) == 1 ) {
+                LOG(log_debug, logtype_afpd, "get_uuid('%s'): UUID: '%s'", volname, uuid);
+                fclose(fp);
+                return strdup(uuid);
+            }
+        }
+    }
+
+    if (fp)
+        fclose(fp);
+
+    /*  not found or no file, reopen in append mode */
+    if ((fp = fopen(obj->options.uuidconf, "a+")) == NULL) {
+        LOG(log_error, logtype_afpd, "Cannot create or append to %s (%s).",
+            obj->options.uuidconf, strerror(errno));
+        return NULL;
+    }
+    fseek(fp, 0L, SEEK_END);
+    if(ftell(fp) == 0) {                     /* size = 0 */
+        fprintf(fp, "# DON'T TOUCH NOR COPY THOUGHTLESSLY!\n");
+        fprintf(fp, "# This file is auto-generated by afpd.\n");
+        fprintf(fp, "# \n");
+        fprintf(fp, "# This file stores UUIDs for all volumes, either auto-generated ones\n");
+        fprintf(fp, "# or the value from AppleVolumes.default:uuid\n");
+        fprintf(fp, "# \n");
+        fprintf(fp, "# If both values differ, the one from AppleVolumes.default is used.\n\n");
+    } else {
+        fseek(fp, -1L, SEEK_END);
+        if(fgetc(fp) != '\n') fputc('\n', fp); /* last char is \n? */
+    }                    
+    
+    /* generate uuid and write to file */
+    uuid_t id;
+    uuid_generate(id);
+    uuid_unparse(id, uuid);
+    LOG(log_debug, logtype_afpd, "get_uuid('%s'): generated UUID '%s'", volname, uuid);
+
+    fprintf(fp, "\"%s\"\t%36s\n", volname, uuid);
+    fclose(fp);
+    
+    return strdup(uuid);
+}
index 58dae44dc0d4eab5f0f0b8c66d534d6ba45b9740..7402a9a450c9793c9d3119664175e5ba855704b1 100644 (file)
@@ -35,6 +35,7 @@ extern int              readvolfile(AFPObj *obj,
                                     struct passwd *pwent);
 extern const struct vol *getvolumes(void);
 extern void             unload_volumes_and_extmap(void);
+extern char             *get_uuid(const AFPObj *obj, const char *volname);
 
 /* FP functions */
 int afp_openvol      (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size_t *rbuflen);
index 30c14ebfa269e402d3fa25e1000316783096eb09..2c2d502f378e4c25df677445d76d0e8aff85e344 100644 (file)
@@ -20,7 +20,7 @@
 #define UUID_STRINGSIZE 36
 
 typedef char *uuidp_t;
-typedef char uuid_t[UUID_BINSIZE];
+typedef char atalk_uuid_t[UUID_BINSIZE];
 
 typedef enum {UUID_USER = 1, UUID_GROUP} uuidtype_t;
 extern char *uuidtype[];
index 3b3a888f8682629393038d799b0782e9abe19cb4..538ff33d8ddd85d09acd1864e82182b96ba2bd55 100644 (file)
@@ -103,7 +103,7 @@ static unsigned char hashstring(unsigned char *str) {
     return index;
 }
 
-/* hash uuid_t into unsigned char */
+/* hash atalk_uuid_t into unsigned char */
 static unsigned char hashuuid(uuidp_t uuid) {
     unsigned char index = 83;
     int i;
index 90d3e3627ec02459fca16673aa2aa02cbf2aeb9d..cf957c6c2bad7c5075fbc27097248c37731f4fa3 100644 (file)
@@ -1080,8 +1080,8 @@ ad_mkdir( const char *path, int mode)
     int st_invalid;
     struct stat stbuf;
 
-    LOG(log_debug, logtype_default, "ad_mkdir: creating ad-directory '%s/%s' with mode %04o",
-        getcwdpath(), path, mode);
+    LOG(log_debug, logtype_default, "ad_mkdir: creating ad-directory '%s' with mode %04o",
+        path, mode);
 
     st_invalid = ad_mode_st(path, &mode, &stbuf);
     ret = mkdir( path, mode );
@@ -1383,7 +1383,7 @@ int ad_open( const char *path, int adflags, int oflags, int mode, struct adouble
              * here.
              * if ((oflags & O_CREAT) ==> (oflags & O_RDWR)
              */
-            LOG(log_debug, logtype_default, "ad_open: creating new adouble file: %s/%s", getcwdpath(), ad_p);
+            LOG(log_debug, logtype_default, "ad_open: creating new adouble file: %s", ad_p);
             admode = mode;
             errno = 0;
             st_invalid = ad_mode_st(ad_p, &admode, &st_dir);