]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/volume.c
Merge dircache-rewrite
[netatalk.git] / etc / afpd / volume.c
index 368dd50c0c8c355c2d987318533e957796765d01..5d61d69408cdc0513858c3d4ac7140b90ada8adf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.c,v 1.115.2.2 2010-02-09 14:56:30 franklahm Exp $
+ * $Id$
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -92,45 +92,38 @@ static void             free_extmap(void);
 #define VOLOPT_CASEFOLD   5  /* character case mangling */
 #define VOLOPT_FLAGS      6  /* various flags */
 #define VOLOPT_DBPATH     7  /* path to database */
-#define VOLOPT_MAPCHARS   8  /* does mtou and utom mappings. syntax:
-                                m and u can be double-byte hex
-                                strings if necessary.
-                                m=u -> map both ways
-                                m>u -> map m to u
-                                m<u -> map u to m
-                                !u  -> make u illegal always
-                                ~u  -> make u illegal only as the first
-                                part of a double-byte character.
-                             */
+#define VOLOPT_LIMITSIZE  8  /* Limit the size of the volume */
+/* Usable slot: 9 */
 #define VOLOPT_VETO          10  /* list of veto filespec */
 #define VOLOPT_PREEXEC       11  /* preexec command */
 #define VOLOPT_ROOTPREEXEC   12  /* root preexec command */
-
 #define VOLOPT_POSTEXEC      13  /* postexec command */
 #define VOLOPT_ROOTPOSTEXEC  14  /* root postexec command */
-
 #define VOLOPT_ENCODING      15  /* mac encoding (pre OSX)*/
 #define VOLOPT_MACCHARSET    16
 #define VOLOPT_CNIDSCHEME    17
 #define VOLOPT_ADOUBLE       18  /* adouble version */
+
 #ifdef FORCE_UIDGID
 #warning UIDGID
 #include "uid.h"
 
-#define VOLOPT_FORCEUID  19  /* force uid for username x */
-#define VOLOPT_FORCEGID  20  /* force gid for group x */
+#define VOLOPT_FORCEUID      19  /* force uid for username x */
+#define VOLOPT_FORCEGID      20  /* force gid for group x */
 #endif /* FORCE_UIDGID */
 
-#define VOLOPT_UMASK     21
+#define VOLOPT_UMASK         21
 #define VOLOPT_ALLOWED_HOSTS 22
 #define VOLOPT_DENIED_HOSTS  23
-#define VOLOPT_DPERM     24  /* dperm default directories perms */
-#define VOLOPT_FPERM     25  /* fperm default files perms */
-#define VOLOPT_DFLTPERM  26  /* perm */
-#define VOLOPT_EA_VFS    27  /* Extended Attributes vfs indirection */
+#define VOLOPT_DPERM         24  /* dperm default directories perms */
+#define VOLOPT_FPERM         25  /* fperm default files perms */
+#define VOLOPT_DFLTPERM      26  /* perm */
+#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_MAX       28  /* <== IMPORTANT !!!!!! */
-#define VOLOPT_NUM       (VOLOPT_MAX + 1)
+#define VOLOPT_MAX           31  /* <== IMPORTANT !!!!!! */
+#define VOLOPT_NUM           (VOLOPT_MAX + 1)
 
 #define VOLPASSLEN  8
 #define VOLOPT_DEFAULT     ":DEFAULT:"
@@ -466,12 +459,26 @@ static void volset(struct vol_option *options, struct vol_option *save,
                 options[VOLOPT_FLAGS].i_value &= ~AFPVOL_CACHE;
             else if (strcasecmp(p, "tm") == 0)
                 options[VOLOPT_FLAGS].i_value |= AFPVOL_TM;
-            else if (strcasecmp(p, "eject") == 0)
-                options[VOLOPT_FLAGS].i_value |= AFPVOL_EJECT | AFPVOL_RO;
-
+/* Found this in branch dir-rewrite, maybe we want to use it sometimes */
+#if 0
+            else if (strcasecmp(p, "cdrom") == 0)
+                options[VOLOPT_FLAGS].i_value |= AFPVOL_CDROM | AFPVOL_RO;
+#endif
             p = strtok(NULL, ",");
         }
 
+    } else if (optionok(tmp, "cnidserver:", val)) {
+        setoption(options, save, VOLOPT_CNIDSERVER, val);
+
+        char *p = strrchr(val + 1, ':');
+        if (p) {
+            *p = 0;
+            setoption(options, save, VOLOPT_CNIDPORT, p);
+        }
+
+        LOG(log_debug, logtype_afpd, "CNID Server for volume '%s': %s:%s",
+            volname, val + 1, p ? p + 1 : Cnid_port);
+
     } else if (optionok(tmp, "dbpath:", val)) {
         setoption(options, save, VOLOPT_DBPATH, val);
 
@@ -483,9 +490,6 @@ static void volset(struct vol_option *options, struct vol_option *save,
         options[VOLOPT_FPERM].i_value = (int)strtol(val+1, NULL, 8);
     } else if (optionok(tmp, "perm:", val)) {
         options[VOLOPT_DFLTPERM].i_value = (int)strtol(val+1, NULL, 8);
-    } else if (optionok(tmp, "mapchars:",val)) {
-        setoption(options, save, VOLOPT_MAPCHARS, val);
-
     } else if (optionok(tmp, "password:", val)) {
         setoption(options, save, VOLOPT_PASSWORD, val);
 
@@ -524,6 +528,9 @@ static void volset(struct vol_option *options, struct vol_option *save,
         else if (strcasecmp(val + 1, "none") == 0)
             options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_NONE;
 
+    } else if (optionok(tmp, "volsizelimit:", val)) {
+        options[VOLOPT_LIMITSIZE].i_value = (uint32_t)strtoul(val + 1, NULL, 10);
+
     } else {
         /* ignore unknown options */
         LOG(log_debug, logtype_afpd, "ignoring unknown volume option: %s", tmp);
@@ -719,6 +726,12 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
         if (options[VOLOPT_CNIDSCHEME].c_value)
             volume->v_cnidscheme = strdup(options[VOLOPT_CNIDSCHEME].c_value);
 
+        if (options[VOLOPT_CNIDSERVER].c_value)
+            volume->v_cnidserver = strdup(options[VOLOPT_CNIDSERVER].c_value);
+
+        if (options[VOLOPT_CNIDPORT].c_value)
+            volume->v_cnidport = strdup(options[VOLOPT_CNIDPORT].c_value);
+
         if (options[VOLOPT_UMASK].i_value)
             volume->v_umask = (mode_t)options[VOLOPT_UMASK].i_value;
 
@@ -736,6 +749,9 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
         else
             volume->v_adouble = AD_VERSION;
 
+        if (options[VOLOPT_LIMITSIZE].i_value)
+            volume->v_limitsize = options[VOLOPT_LIMITSIZE].i_value;
+
         /* Mac to Unix conversion flags*/
         volume->v_mtou_flags = 0;
         if (!(volume->v_flags & AFPVOL_NOHEX))
@@ -984,12 +1000,12 @@ static void setextmap(char *ext, char *type, char *creator, int user)
     }
 
     if ( *type == '\0' ) {
-        memcpy(em->em_type, "????", sizeof( em->em_type ));
+        memcpy(em->em_type, "\0\0\0\0", sizeof( em->em_type ));
     } else {
         memcpy(em->em_type, type, sizeof( em->em_type ));
     }
     if ( *creator == '\0' ) {
-        memcpy(em->em_creator, "UNIX", sizeof( em->em_creator ));
+        memcpy(em->em_creator, "\0\0\0\0", sizeof( em->em_creator ));
     } else {
         memcpy(em->em_creator, creator, sizeof( em->em_creator ));
     }
@@ -1347,8 +1363,7 @@ static int getvolspace(struct vol *vol,
     }
 #endif
 
-    if (( rc = ustatfs_getvolspace( vol, xbfree, xbtotal,
-                                    bsize)) != AFP_OK ) {
+    if (( rc = ustatfs_getvolspace( vol, xbfree, xbtotal, bsize)) != AFP_OK ) {
         return( rc );
     }
 
@@ -1366,6 +1381,13 @@ static int getvolspace(struct vol *vol,
     vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_USTATFS;
 
 getvolspace_done:
+    if (vol->v_limitsize) {
+        /* FIXME: Free could be limit minus (total minus used), */
+        /* which will confuse the client less ? */
+        *xbfree = min(*xbfree, (vol->v_limitsize * 1024 * 1024));
+        *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024));
+    }
+
     *bfree = min( *xbfree, maxsize);
     *btotal = min( *xbtotal, maxsize);
     return( AFP_OK );
@@ -1821,6 +1843,13 @@ static int volume_openDB(struct vol *volume)
         LOG(log_info, logtype_afpd, "Volume %s use CNID scheme %s.", volume->v_path, volume->v_cnidscheme);
     }
 
+    LOG(log_info, logtype_afpd, "%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 */
+
     /* Legacy pre 2.1 way of sharing eg CD-ROM */
     if (strcmp(volume->v_cnidscheme, "last") == 0) {
         /* "last" is gone. We support it by switching to in-memory "tdb" */
@@ -1829,7 +1858,7 @@ static int volume_openDB(struct vol *volume)
     }
 
     /* New way of sharing CD-ROM */
-    if (volume->v_flags & AFPVOL_EJECT) {
+    if (volume->v_flags & AFPVOL_CDROM) {
         flags |= CNID_FLAG_MEMORY;
         if (strcmp(volume->v_cnidscheme, "tdb") != 0) {
             free(volume->v_cnidscheme);
@@ -1838,17 +1867,21 @@ static int volume_openDB(struct vol *volume)
                 volume->v_path, volume->v_cnidscheme);
         }
     }
+#endif
+
+    volume->v_cdb = cnid_open(volume->v_dbpath ? volume->v_dbpath : volume->v_path,
+                              volume->v_umask,
+                              volume->v_cnidscheme,
+                              flags,
+                              volume->v_cnidserver ? volume->v_cnidserver : Cnid_srv,
+                              volume->v_cnidport ? volume->v_cnidport : Cnid_port);
 
-    if (volume->v_dbpath)
-        volume->v_cdb = cnid_open (volume->v_dbpath, volume->v_umask, volume->v_cnidscheme, flags);
-    else
-        volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, volume->v_cnidscheme, flags);
 
     if ( ! volume->v_cdb && ! (flags & CNID_FLAG_MEMORY)) {
         /* The first attempt failed and it wasn't yet an attempt to open in-memory */
         flags |= CNID_FLAG_MEMORY;
         LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.", volume->v_path);
-        volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, "tdb", flags);
+        volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, "tdb", flags, NULL, NULL);
 #ifdef SERVERTEXT
         /* kill ourself with SIGUSR2 aka msg pending */
         if (volume->v_cdb) {
@@ -2015,6 +2048,27 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
         return AFPERR_MISC;
     }
 
+    /* Normalize volume path */
+#ifdef REALPATH_TAKES_NULL
+    if ((volume->v_path = realpath(path, NULL)) == NULL)
+        return AFPERR_MISC;
+#else
+    if ((volume->v_path = malloc(MAXPATHLEN+1)) == NULL)
+        return AFPERR_MISC;
+    if (realpath(path, volume->v_path) == NULL) {
+        free(volume->v_path);
+        return AFPERR_MISC;
+    }
+    /* Safe some memory */
+    char *tmp;
+    if ((tmp = strdup(volume->v_path)) == NULL) {
+        free(volume->v_path);
+        return AFPERR_MISC;
+    } 
+    free(volume->v_path);
+    volume->v_path = tmp;
+#endif
+
     if (volume_codepage(obj, volume) < 0) {
         ret = AFPERR_MISC;
         goto openvol_err;
@@ -2077,7 +2131,9 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
 
         if (!(volume->v_flags & AFPVOL_RO)) {
             handle_special_folders( volume );
-            savevolinfo(volume, Cnid_srv, Cnid_port);
+            savevolinfo(volume,
+                        volume->v_cnidserver ? volume->v_cnidserver : Cnid_srv,
+                        volume->v_cnidport   ? volume->v_cnidport   : Cnid_port);
         }
 
         /*
@@ -2470,18 +2526,13 @@ static int create_special_folder (const struct vol *vol, const struct _special_f
     if ( !ret && folder->hide) {
         /* Hide it */
         ad_init(&ad, vol->v_adouble, vol->v_ad_options);
-        if (ad_open( p, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR|O_CREAT, 0666, &ad) < 0) {
+        if (ad_open_metadata( p, ADFLAGS_DIR, O_CREAT, &ad) < 0) {
             free (p);
             free(q);
             return (-1);
         }
-        if ((ad_get_HF_flags( &ad ) & O_CREAT) ) {
-            if (ad_getentryoff(&ad, ADEID_NAME)) {
-                ad_setentrylen( &ad, ADEID_NAME, strlen(folder->name));
-                memcpy(ad_entry( &ad, ADEID_NAME ), folder->name,
-                       ad_getentrylen( &ad, ADEID_NAME ));
-            }
-        }
+        
+        ad_setname(&ad, folder->name);
 
         ad_getattr(&ad, &attr);
         attr |= htons( ntohs( attr ) | ATTRBIT_INVISIBLE );
@@ -2495,7 +2546,7 @@ static int create_special_folder (const struct vol *vol, const struct _special_f
         }
 
         ad_flush( &ad );
-        ad_close( &ad, ADFLAGS_HF );
+        ad_close_metadata( &ad);
     }
     free(p);
     free(q);