]> arthur.barton.de Git - netatalk.git/commitdiff
Merge 2-1
authorFrank Lahm <franklahm@googlemail.com>
Thu, 21 Apr 2011 12:00:23 +0000 (14:00 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Thu, 21 Apr 2011 12:00:23 +0000 (14:00 +0200)
1  2 
etc/cnid_dbd/cmd_dbd.c
etc/cnid_dbd/cmd_dbd.h
etc/cnid_dbd/cmd_dbd_scanvol.c
etc/cnid_dbd/dbif.c
etc/cnid_dbd/dbif.h
etc/cnid_dbd/main.c

index 2359defde738e2bb9770483c840f27cfe841b1fd,7fd2ce02d4e3ab0484606d83ac83f4cc42a72f84..5493a28059461cb525f49f99ecaa0cbf16dbb15d
@@@ -452,19 -369,13 +384,18 @@@ int main(int argc, char **argv
      /* Check if -f is requested and wipe db if yes */
      if ((flags & DBD_FLAGS_FORCE) && rebuild && (volinfo.v_flags & AFPVOL_CACHE)) {
          char cmd[8 + MAXPATHLEN];
-         if ((db_locked = get_lock(0, NULL)) != 0)
+         if ((db_locked = get_lock(LOCK_FREE, NULL)) != 0)
              goto exit_failure;
 -        snprintf(cmd, 8 + MAXPATHLEN, "rm -f %s/*", dbpath);
 +
 +        snprintf(cmd, 8 + MAXPATHLEN, "rm -rf \"%s\"", dbpath);
          dbd_log( LOGDEBUG, "Removing old database of volume: '%s'", volpath);
          system(cmd);
 +        if ((mkdir(dbpath, 0755)) != 0) {
 +            dbd_log( LOGSTD, "Can't create dbpath \"%s\": %s", dbpath, strerror(errno));
 +            exit(EXIT_FAILURE);
 +        }
          dbd_log( LOGDEBUG, "Removed old database.");
-         if ((db_locked = get_lock(1, dbpath)) == -1)
+         if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
              goto exit_failure;
      }
  
              dbif_close(dbd);
              goto exit_failure;
          }
 -
 -        if (dbd_stamp(dbd) < 0) {
 -            dbif_close(dbd);
 -            goto exit_failure;
 -        }
      }
  
+     /* Downgrade db lock if not running exclusive */
+     if (!exclusive && (db_locked == LOCK_EXCL)) {
+         if (get_lock(LOCK_UNLOCK, NULL) != 0)
+             goto exit_failure;
+         if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD)
+             goto exit_failure;
+     }
      /* Now execute given command scan|rebuild|dump */
      if (dump && ! nocniddb) {
          if (dbif_dump(dbd, dumpindexes) < 0) {
Simple merge
Simple merge
index 646385cbe267d392e955e8261220c49ff80dc933,c79189c504523d801287b7c94b627b8e62800427..792ebe915a4c8dcf7f5085dea7b8e4ce06dbac3f
@@@ -321,6 -174,127 +321,91 @@@ exit
      return ret;
  }
  
 -/* --------------- */
 -int dbif_stamp(DBD *dbd, void *buffer, int size)
 -{
 -    struct stat st;
 -    int         rc,cwd;
 -
 -    if (size < 8)
 -        return -1;
 -
 -    /* Remember cwd */
 -    if ((cwd = open(".", O_RDONLY)) < 0) {
 -        LOG(log_error, logtype_cnid, "error opening cwd: %s", strerror(errno));
 -        return -1;
 -    }
 -
 -    /* chdir to db_envhome */
 -    if ((chdir(dbd->db_envhome)) != 0) {
 -        LOG(log_error, logtype_cnid, "error chdiring to db_env '%s': %s", dbd->db_envhome, strerror(errno));        
 -        return -1;
 -    }
 -
 -    if ((rc = stat(dbd->db_table[DBIF_CNID].name, &st)) < 0) {
 -        LOG(log_error, logtype_cnid, "error stating database %s: %s", dbd->db_table[DBIF_CNID].name, db_strerror(errno));
 -        return -1;
 -    }
 -    memset(buffer, 0, size);
 -    memcpy(buffer, &st.st_ctime, sizeof(st.st_ctime));
 -
 -    if ((fchdir(cwd)) != 0) {
 -        LOG(log_error, logtype_cnid, "error chdiring back: %s", strerror(errno));        
 -        return -1;
 -    }
 -
 -    return 0;
 -}
 -
+ /*!
+  * Get lock on db lock file
+  *
+  * @args cmd       (r) lock command:
+  *                     LOCK_FREE:   close lockfd
+  *                     LOCK_UNLOCK: unlock lockm keep lockfd open
+  *                     LOCK_EXCL:   F_WRLCK on lockfd
+  *                     LOCK_SHRD:   F_RDLCK on lockfd
+  * @args dbpath    (r) path to lockfile, only used on first call,
+  *                     later the stored fd is used
+  * @returns            LOCK_FREE/LOCK_UNLOCK return 0 on success, -1 on error
+  *                     LOCK_EXCL/LOCK_SHRD return LOCK_EXCL or LOCK_SHRD respectively on
+  *                     success, 0 if the lock couldn't be acquired, -1 on other errors
+  */
+ int get_lock(int cmd, const char *dbpath)
+ {
+     static int lockfd = -1;
+     int ret;
+     char lockpath[PATH_MAX];
+     struct stat st;
+     switch (cmd) {
+     case LOCK_FREE:
+         if (lockfd == -1)
+             return -1;
+         close(lockfd);
+         lockfd = -1;
+         return 0;
+     case LOCK_UNLOCK:
+         if (lockfd == -1)
+             return -1;
+         return unlock(lockfd, 0, SEEK_SET, 0);
+     case LOCK_EXCL:
+     case LOCK_SHRD:
+         if (lockfd == -1) {
+             if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) {
+                 LOG(log_error, logtype_cnid, ".AppleDB pathname too long");
+                 return -1;
+             }
+             strncpy(lockpath, dbpath, PATH_MAX - 1);
+             strcat(lockpath, "/");
+             strcat(lockpath, LOCKFILENAME);
+             if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) {
+                 LOG(log_error, logtype_cnid, "Error opening lockfile: %s", strerror(errno));
+                 return -1;
+             }
+             if ((stat(dbpath, &st)) != 0) {
+                 LOG(log_error, logtype_cnid, "Error statting lockfile: %s", strerror(errno));
+                 return -1;
+             }
+             if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) {
+                 LOG(log_error, logtype_cnid, "Error inheriting lockfile permissions: %s",
+                          strerror(errno));
+                 return -1;
+             }
+         }
+     
+         if (cmd == LOCK_EXCL)
+             ret = write_lock(lockfd, 0, SEEK_SET, 0);
+         else
+             ret = read_lock(lockfd, 0, SEEK_SET, 0);
+         if (ret != 0) {
+             if (cmd == LOCK_SHRD)
+                 LOG(log_error, logtype_cnid, "Volume CNID db is locked, try again...");
+             return 0; 
+         }
+         LOG(log_debug, logtype_cnid, "get_lock: got %s lock",
+             cmd == LOCK_EXCL ? "LOCK_EXCL" : "LOCK_SHRD");    
+         return cmd;
+     default:
+         return -1;
+     } /* switch(cmd) */
+     /* deadc0de, never get here */
+     return -1;
+ }
  /* --------------- */
  DBD *dbif_init(const char *envhome, const char *filename)
  {
index f5d3759fca5affba4013d724e2b32813b70309dd,1a4a0b8e685dbb227df4cf617b48af6be583a7ee..c936a2b93705daf7b5bf1a8061131f7a3174dd37
  #define DBIF_CNID          0
  #define DBIF_IDX_DEVINO    1
  #define DBIF_IDX_DIDNAME   2
 +#define DBIF_IDX_NAME      3
  
+ /* get_lock cmd and return value */
+ #define LOCKFILENAME  "lock"
+ #define LOCK_FREE          0
+ #define LOCK_UNLOCK        1
+ #define LOCK_EXCL          2
+ #define LOCK_SHRD          3
  /* Structures */
  typedef struct {
      char     *name;
index 9b9d963134c4a02b5feee5bc0f248ef2e689c1bc,bf71b72d5945e8a63772d2da4639e3c204490197..dbb55b4e2dfe6af3b061896fbb1330975350c660
@@@ -366,34 -296,23 +299,41 @@@ int main(int argc, char *argv[]
      logconfig = strdup(argv[4]);
      setuplog(logconfig);
  
 -    switch_to_user(dir);
 +    /* Load .volinfo file */
 +    if (loadvolinfo(argv[1], &volinfo) == -1) {
 +        LOG(log_error, logtype_cnid, "Cant load volinfo for \"%s\"", argv[1]);
 +        exit(EXIT_FAILURE);
 +    }
 +    /* Put "/.AppleDB" at end of volpath, get path from volinfo file */
 +    char dbpath[MAXPATHLEN+1];
 +    if ((strlen(volinfo.v_dbpath) + strlen("/.AppleDB")) > MAXPATHLEN ) {
 +        LOG(log_error, logtype_cnid, "CNID db pathname too long: \"%s\"", volinfo.v_dbpath);
 +        exit(EXIT_FAILURE);
 +    }
 +    strncpy(dbpath, volinfo.v_dbpath, MAXPATHLEN - strlen("/.AppleDB"));
 +    strcat(dbpath, "/.AppleDB");
 +
 +    if (vol_load_charsets(&volinfo) == -1) {
 +        LOG(log_error, logtype_cnid, "Error loading charsets!");
 +        exit(EXIT_FAILURE);
 +    }
 +    LOG(log_debug, logtype_cnid, "db dir: \"%s\"", dbpath);
 +
 +    switch_to_user(dbpath);
  
-     /* Before we do anything else, check if there is an instance of cnid_dbd
-        running already and silently exit if yes. */
-     if ((db_locked = get_lock(1)) == -1) {
+     /* Get db lock */
+     if ((db_locked = get_lock(LOCK_EXCL, dir)) == -1) {
+         LOG(log_error, logtype_cnid, "main: fatal db lock error");
          exit(1);
      }
+     if (db_locked != LOCK_EXCL) {
+         /* Couldn't get exclusive lock, try shared lock  */
+         if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD) {
+             LOG(log_error, logtype_cnid, "main: fatal db lock error");
+             exit(1);
+         }
+     }
  
 -    LOG(log_info, logtype_cnid, "Startup, DB dir %s", dir);
 -
      set_signal();
  
      /* SIGINT and SIGTERM are always off, unless we are in pselect */
      }
      LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases");
  
 -    if (dbd_stamp(dbd) < 0) {
 -        dbif_close(dbd);
 -        exit(5);
 -    }
 -    LOG(log_maxdebug, logtype_cnid, "Finished checking database stamp");
 -
+     /* Downgrade db lock  */
+     if (db_locked == LOCK_EXCL) {
+         if (get_lock(LOCK_UNLOCK, NULL) != 0) {
+             dbif_close(dbd);
+             exit(2);
+         }
+         if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD) {
+             dbif_close(dbd);
+             exit(2);
+         }
+     }
      if (comm_init(dbp, ctrlfd, clntfd) < 0) {
          dbif_close(dbd);
          exit(3);
      if (dbif_close(dbd) < 0)
          err++;
  
 -    if (dbif_prep_upgrade(dir) < 0)
 +    if (dbif_env_remove(dbpath) < 0)
          err++;
  
-     (void)get_lock(0);
      if (err)
          exit(4);
      else if (exit_sig)