]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/volume.c
Merge remote branch 'sf/master'
[netatalk.git] / etc / afpd / volume.c
index b5b843bc6c1cb3452f280d63a9bddd601509e434..f2269bd407a441b85d78312336bb48fb6b966e35 100644 (file)
@@ -36,6 +36,7 @@ char *strchr (), *strrchr ();
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <inttypes.h>
+#include <time.h>
 
 #include <atalk/asp.h>
 #include <atalk/dsi.h>
@@ -49,12 +50,13 @@ char *strchr (), *strrchr ();
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
 #include <atalk/ftw.h>
+#include <atalk/globals.h>
+#include <atalk/fce_api.h>
 
 #ifdef CNID_DB
 #include <atalk/cnid.h>
 #endif /* CNID_DB*/
 
-#include "globals.h"
 #include "directory.h"
 #include "file.h"
 #include "volume.h"
@@ -70,17 +72,6 @@ extern int afprun(int root, char *cmd, int *outfd);
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
 #endif /* ! MIN */
 
-#ifndef NO_LARGE_VOL_SUPPORT
-#if BYTE_ORDER == BIG_ENDIAN
-#define hton64(x)       (x)
-#define ntoh64(x)       (x)
-#else /* BYTE_ORDER == BIG_ENDIAN */
-#define hton64(x)       ((u_int64_t) (htonl(((x) >> 32) & 0xffffffffLL)) | \
-                         (u_int64_t) ((htonl(x) & 0xffffffffLL) << 32))
-#define ntoh64(x)       (hton64(x))
-#endif /* BYTE_ORDER == BIG_ENDIAN */
-#endif /* ! NO_LARGE_VOL_SUPPORT */
-
 #ifndef UUID_PRINTABLE_STRING_LENGTH
 #define UUID_PRINTABLE_STRING_LENGTH 37
 #endif
@@ -512,11 +503,10 @@ static void volset(struct vol_option *options, struct vol_option *save,
                 options[VOLOPT_FLAGS].i_value |= AFPVOL_TM;
             else if (strcasecmp(p, "searchdb") == 0)
                 options[VOLOPT_FLAGS].i_value |= AFPVOL_SEARCHDB;
-/* 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
+            else if (strcasecmp(p, "nonetids") == 0)
+                options[VOLOPT_FLAGS].i_value |= AFPVOL_NONETIDS;
+            else if (strcasecmp(p, "noacls") == 0)
+                options[VOLOPT_FLAGS].i_value &= ~AFPVOL_ACLS;
             p = strtok(NULL, ",");
         }
 
@@ -757,9 +747,8 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
     volume->v_vid = ++lastvid;
     volume->v_vid = htons(volume->v_vid);
 #ifdef HAVE_ACLS
-    if (check_vol_acl_support(volume))
-        volume->v_flags |= AFPVOL_ACLS
-;
+    if (!check_vol_acl_support(volume))
+        volume->v_flags &= ~AFPVOL_ACLS;
 #endif
 
     /* handle options */
@@ -1217,18 +1206,31 @@ static int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int us
         p1->mtime = st.st_mtime;
     }
 
-    if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) {
-        LOG(log_error, logtype_afpd, "readvolfile: can't lock volume file \"%s\"", path);
-        if ( fclose( fp ) != 0 ) {
-            LOG(log_error, logtype_afpd, "readvolfile: fclose: %s", strerror(errno) );
+    /* try putting a read lock on the volume file twice, sleep 1 second if first attempt fails */
+    int retries = 2;
+    while (1) {
+        if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) {
+            retries--;
+            if (!retries) {
+                LOG(log_error, logtype_afpd, "readvolfile: can't lock volume file \"%s\"", path);
+                if ( fclose( fp ) != 0 ) {
+                    LOG(log_error, logtype_afpd, "readvolfile: fclose: %s", strerror(errno) );
+                }
+                return -1;
+            }
+            sleep(1);
+            continue;
         }
-        return -1;
+        break;
     }
 
     memset(save_options, 0, sizeof(save_options));
 
     /* Enable some default options for all volumes */
     save_options[VOLOPT_FLAGS].i_value |= AFPVOL_CACHE;
+#ifdef HAVE_ACLS
+    save_options[VOLOPT_FLAGS].i_value |= AFPVOL_ACLS;
+#endif
     save_options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AUTO;
     LOG(log_maxdebug, logtype_afpd, "readvolfile: seeding default umask: %04o",
         obj->options.umask);
@@ -1451,6 +1453,7 @@ static int getused_stat(const char *path,
     return 0;
 }
 
+#define GETUSED_CACHETIME 5
 /*!
  * Calculate used size of a volume with nftw
  *
@@ -1462,22 +1465,27 @@ static int getused_stat(const char *path,
  *       longer then 30 sec ago
  * 1c) - the last volume modification is less then 30 sec old
  *
- * @param vol     (r) volume to calculate
+ * @param vol     (rw) volume to calculate
  */
-static int getused(const struct vol *vol)
+static int getused(struct vol *vol)
 {
     static time_t vol_mtime = 0;
     int ret = 0;
     time_t now = time(NULL);
 
     if (!vol_mtime
-        || (!vol->v_mtime && ((vol_mtime + 30) < now))
-        || (vol->v_mtime && ((vol_mtime + 30) < vol->v_mtime))
+        || (!vol->v_mtime && ((vol_mtime + GETUSED_CACHETIME) < now))
+        || (vol->v_mtime && ((vol_mtime + GETUSED_CACHETIME) < vol->v_mtime))
         ) {
         vol_mtime = now;
         getused_size = 0;
+        vol->v_written = 0;
         ret = nftw(vol->v_path, getused_stat, NULL, 20, FTW_PHYS); /* 2 */
+        LOG(log_debug, logtype_afpd, "volparams: from nftw: %" PRIu64 " bytes",
+            getused_size);
     } else {
+        getused_size += vol->v_written;
+        vol->v_written = 0;
         LOG(log_debug, logtype_afpd, "volparams: cached used: %" PRIu64 " bytes",
             getused_size);
     }
@@ -1534,6 +1542,7 @@ getvolspace_done:
             return AFPERR_MISC;
         LOG(log_debug, logtype_afpd, "volparams: used on volume: %" PRIu64 " bytes",
             getused_size);
+        vol->v_tm_used = getused_size;
 
         *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024));
         *xbfree = min(*xbfree, *xbtotal < getused_size ? 0 : *xbtotal - getused_size);
@@ -1544,6 +1553,22 @@ getvolspace_done:
     return( AFP_OK );
 }
 
+#define FCE_TM_DELTA 10  /* send notification every 10 seconds */
+void vol_fce_tm_event(void)
+{
+    static time_t last;
+    time_t now = time(NULL);
+    struct vol  *vol = Volumes;
+
+    if ((last + FCE_TM_DELTA) < now) {
+        last = now;
+        for ( ; vol; vol = vol->v_next ) {
+            if (vol->v_flags & AFPVOL_TM)
+                (void)fce_register_tm_size(vol->v_path, vol->v_tm_used + vol->v_written);
+        }
+    }
+}
+
 /* -----------------------
  * set volume creation date
  * avoid duplicate, well at least it tries
@@ -1654,7 +1679,8 @@ static int getvolparams( u_int16_t bitmap, struct vol *vol, struct stat *st, cha
                         ashort |= VOLPBIT_ATTR_UNIXPRIV;
                     if (vol->v_flags & AFPVOL_TM)
                         ashort |= VOLPBIT_ATTR_TM;
-
+                    if (vol->v_flags & AFPVOL_NONETIDS)
+                        ashort |= VOLPBIT_ATTR_NONETIDS;
                     if (afp_version >= 32) {
                         if (vol->v_vfs_ea)
                             ashort |= VOLPBIT_ATTR_EXT_ATTRS;
@@ -2715,6 +2741,14 @@ static int create_special_folder (const struct vol *vol, const struct _special_f
 static void handle_special_folders (const struct vol * vol)
 {
     const _special_folder *p = &special_folders[0];
+    uid_t process_uid;
+
+    process_uid = geteuid();
+    if (process_uid) {
+        if (seteuid(0) == -1) {
+            process_uid = 0;
+        }
+    }
 
     if ((vol->v_flags & AFPVOL_RO))
         return;
@@ -2722,6 +2756,13 @@ static void handle_special_folders (const struct vol * vol)
     for (; p->name != NULL; p++) {
         create_special_folder (vol, p);
     }
+
+    if (process_uid) {
+        if (seteuid(process_uid) == -1) {
+            LOG(log_error, logtype_logger, "can't seteuid back %s", strerror(errno));
+            exit(EXITERR_SYS);
+        }
+    }
 }
 
 const struct vol *getvolumes(void)