]> arthur.barton.de Git - netatalk.git/commitdiff
Finished dbd
authorfranklahm <franklahm>
Fri, 22 May 2009 20:48:44 +0000 (20:48 +0000)
committerfranklahm <franklahm>
Fri, 22 May 2009 20:48:44 +0000 (20:48 +0000)
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
include/atalk/adouble.h
libatalk/adouble/ad_attr.c

index 9e2aef88783ced3a659c24d493d77f121b21f3c3..db290c1a63fc1aca0723b36323f51204db291e86 100644 (file)
@@ -1,5 +1,5 @@
 /* 
-   $Id: cmd_dbd.c,v 1.2 2009-05-18 09:25:25 franklahm Exp $
+   $Id: cmd_dbd.c,v 1.3 2009-05-22 20:48:44 franklahm Exp $
 
    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
    
    GNU General Public License for more details.
 */
 
+/*
+  dbd specs and implementation progress
+  =====================================
+
+  St := Status
+
+  Force option
+  ------------
+  
+  St Spec
+  -- ----
+  OK If -f is requested, ensure -e is too.
+     Check if volumes is using AFPVOL_CACHE, then wipe db from disk. Rebuild from ad-files.
+
+  1st pass: Scan volume
+  --------------------
+
+  St Type Check
+  -- ---- -----
+  OK F/D  Make sure ad file exists
+  OK D    Make sure .AppleDouble dir exist, create if missing. Error creating
+          it is fatal as that shouldn't happen as root.
+  OK F/D  Delete orphaned ad-files, log dirs in ad-dir
+  OK F/D  Check name encoding by roundtripping, log on error
+  OK F/D  try: read CNID from ad file (if cnid caching is on)
+          try: fetch CNID from database
+          -> on mismatch: use CNID from file, update database (deleting both found CNIDs first)
+          -> if no CNID in ad file: write CNID from database to ad file
+          -> if no CNID in database: add CNID from ad file to database
+          -> on no CNID at all: create one and store in both places
+  OK F/D  Add found CNID, DID, filename, dev/inode, stamp to rebuild database
+  OK F/D  Check/update stamp (implicitly done while checking CNIDs)
+
+
+  2nd pass: Delete unused CNIDs
+  -----------------------------
+
+  St Spec
+  -- ----
+  OK Step through dbd (the one on disk) and rebuild-db from pass 1 and delete any CNID from
+     dbd not in rebuild db. This in only done in exclusive mode.
+*/
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
@@ -32,6 +75,7 @@
 #include <atalk/cnid_dbd_private.h>
 #include <atalk/volinfo.h>
 #include "cmd_dbd.h"
+#include "dbd.h"
 #include "dbif.h"
 #include "db_param.h"
 
@@ -204,10 +248,11 @@ static void usage ()
            "      5. Check for directories inside AppleDouble directories\n"
            "      6. Check name encoding by roundtripping, log on error\n"
            "      Option: -f wipe database and rebuild from IDs stored in AppleDouble files,\n"
-           "                 only available for volumes with 'cachecnid' option\n\n"
+           "                 only available for volumes with 'cachecnid' option.\n"
+           "                 Implies -e."
            "General options:\n"
            "   -e only work on inactive volumes and lock them (exclusive)\n"
-           "   -x rebuild indexes\n"
+           "   -x rebuild indexes (just for completeness, mostly useless!)\n"
            "   -v verbose\n"
         );
 }
@@ -235,7 +280,7 @@ int main(int argc, char **argv)
             break;
         case 's':
             scan = 1;
-            flags = DBD_FLAGS_SCAN;
+            flags |= DBD_FLAGS_SCAN;
             break;
         case 'r':
             rebuild = 1;
@@ -245,13 +290,14 @@ int main(int argc, char **argv)
             break;
         case 'e':
             exclusive = 1;
+            flags |= DBD_FLAGS_EXCL;
             break;
         case 'x':
             rebuildindexes = 1;
             break;
         case 'f':
             force = 1;
-            flags = DBD_FLAGS_FORCE;
+            flags |= DBD_FLAGS_FORCE | DBD_FLAGS_EXCL;
             break;
         case ':':
         case '?':
@@ -313,6 +359,15 @@ int main(int argc, char **argv)
         exit(EXIT_FAILURE);
     }
 
+    /* Check if -f is requested and wipe db if yes */
+    if ((flags & DBD_FLAGS_FORCE) && (volinfo.v_flags & AFPVOL_CACHE)) {
+        char cmd[8 + MAXPATHLEN];
+        snprintf(cmd, 8 + MAXPATHLEN, "rm -f %s/cnid2.db", dbpath);
+        dbd_log( LOGSTD, "Removing old database of volume: '%s'", volpath);
+        system(cmd);
+        dbd_log( LOGSTD, "Removed old database.");
+    }
+
     /* 
        Lets start with the BerkeleyDB stuff
     */
@@ -332,6 +387,11 @@ int main(int argc, char **argv)
         exit(EXIT_FAILURE);
     }
 
+    if (dbd_stamp(dbd) < 0) {
+        dbif_close(dbd);
+        exit(EXIT_FAILURE);
+    }
+
     if (dump) {
         if (dbif_dump(dbd, dumpindexes) < 0) {
             dbd_log( LOGSTD, "Error dumping database");
index 2b4c55331939c35df74fcd171f057f887371e965..170b407eb09134fce727f40eb9724d06f19ac070 100644 (file)
@@ -11,7 +11,8 @@ enum logtype {LOGSTD, LOGDEBUG};
 typedef unsigned int dbd_flags_t;
 
 #define DBD_FLAGS_SCAN     (1 << 0)
-#define DBD_FLAGS_FORCE    (1 << 0)
+#define DBD_FLAGS_FORCE    (1 << 1)
+#define DBD_FLAGS_EXCL     (1 << 2)
 
 #define ADv2_DIRNAME ".AppleDouble"
 
index 78dc6aca4bb850c380fbdb6aec320e55b542558d..30dc919f604df35e8884c54b250a63c5f61fefbb 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  $Id: cmd_dbd_scanvol.c,v 1.3 2009-05-20 10:56:02 franklahm Exp $
+  $Id: cmd_dbd_scanvol.c,v 1.4 2009-05-22 20:48:44 franklahm Exp $
 
   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
 
   GNU General Public License for more details.
 */
 
-/*
-  dbd specs and implementation progress
-  =====================================
-
-  St := Status
-
-  Force option
-  ------------
-  
-  St Spec
-  -- ----
-  -- If -f is requested, ensure -e is too.
-     Check if volumes is using AFPVOL_CACHE, then wipe db from disk.
-
-  1st pass: Scan volume
-  --------------------
-
-  St Type Check
-  -- ---- -----
-  OK F/D  Make sure ad file exists
-  OK D    Make sure .AppleDouble dir exist, create if missing. Error creating
-          it is fatal as that shouldn't happen as root.
-  OK F/D  Delete orphaned ad-files, log dirs in ad-dir
-  OK F/D  Check name encoding by roundtripping, log on error
-  OK F/D  try: read CNID from ad file (if cnid caching is on)
-          try: fetch CNID from database
-          -> on mismatch: use CNID from file, update database (deleting both found CNIDs first)
-          -> if no CNID in ad file: write CNID from database to ad file
-          -> if no CNID in database: add CNID from ad file to database
-          -> on no CNID at all: create one and store in both places
-  OK F/D  Add found CNID, DID, filename, dev/inode, stamp to rebuild database
-  OK F/D  Check/update stamp (implicitly done while checking CNIDs)
-
-  2nd pass: Delete unused CNIDs
-  -----------------------------
-
-  St Spec
-  -- ----
-  -- Step through dbd (the one on disk) and rebuild-db from pass 1 and delete any CNID from
-     dbd not in rebuild db.
-*/
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
@@ -446,9 +404,14 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
             dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno));
             return 0;
         }
-        ad_cnid = ad_getid(&ad, st->st_dev, st->st_ino, did, stamp);
+
+        if (dbd_flags & DBD_FLAGS_FORCE)
+            ad_cnid = ad_forcegetid(&ad);
+        else
+            ad_cnid = ad_getid(&ad, st->st_dev, st->st_ino, did, stamp);            
         if (ad_cnid == 0)
             dbd_log( LOGSTD, "Incorrect CNID data in .AppleDouble data for '%s/%s' (bad stamp?)", cwdbuf, name);
+
         ad_close_metadata(&ad);
     }
 
@@ -697,6 +660,92 @@ static int scanvol(struct volinfo *vi, dbd_flags_t flags)
     return 0;
 }
 
+/* 
+   Remove all CNIDs from dbd that are not in dbd_rebuild
+*/
+void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
+{
+    int ret, deleted = 0;
+    cnid_t dbd_cnid = 0, rebuild_cnid = 0;
+    struct cnid_dbd_rqst rqst;
+    struct cnid_dbd_rply rply;
+
+    /* jump over rootinfo key */
+    if ( dbif_idwalk(dbd, &dbd_cnid, 0) != 1)
+        return;
+    if ( dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0) != 1)
+        return;
+
+    /* Get first id from dbd_rebuild */
+    if ((dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0)) == -1)
+        return;
+
+    /* Start main loop through dbd: get CNID from dbd */
+    while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) {
+
+        if (deleted > 50) {
+            deleted = 0;
+            if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
+                dbd_log(LOGSTD, "Error checkpointing!");
+                goto cleanup;
+            }
+        }
+
+        /* This should be the normal case: CNID is in both dbs */
+        if (dbd_cnid == rebuild_cnid) {
+            /* Get next CNID from rebuild db */
+            if ((ret = dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0)) == -1) {
+                /* Some error */
+                goto cleanup;
+            } else if (ret == 0) {
+                /* end of rebuild_cnid, delete all remaining CNIDs from dbd */
+                while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) {
+                    dbd_log(LOGSTD, "Orphaned CNID in database: %u", dbd_cnid);
+                    if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
+                        rqst.cnid = htonl(dbd_cnid);
+                        ret = dbd_delete(dbd, &rqst, &rply);
+                        dbif_txn_close(dbd, ret);
+                        deleted++;
+                    }
+                }
+                return;
+            } else
+                /* Normal case (ret=1): continue while loop */
+                continue;
+        }
+
+        if (dbd_cnid < rebuild_cnid) {
+            /* CNID is orphaned -> delete */
+            dbd_log(LOGSTD, "Orphaned CNID in database: %u.", dbd_cnid);
+            if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
+                rqst.cnid = htonl(dbd_cnid);
+                ret = dbd_delete(dbd, &rqst, &rply);
+                dbif_txn_close(dbd, ret);
+                deleted++;
+            }
+            continue;
+        }
+
+        if (dbd_cnid > rebuild_cnid) {
+            dbd_log(LOGSTD, "Ghost CNID: %u. This is fatal! Dumping rebuild db:\n", rebuild_cnid);
+            dbif_dump(dbd_rebuild, 0);
+            dbd_log(LOGSTD, "Send this dump and a `dbd -d ...` dump to the Netatalk Dev team!");
+            dbif_txn_close(dbd, ret);
+            dbif_idwalk(dbd, NULL, 1); /* Close cursor */
+            dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
+            goto cleanup;
+        }
+    }
+
+cleanup:
+    dbif_idwalk(dbd, NULL, 1); /* Close cursor */
+    dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
+    return;
+}
+
+/*
+  Main func called from cmd_dbd.c
+*/
 int cmd_dbd_scanvol(DBD *dbd_ref, struct volinfo *volinfo, dbd_flags_t flags)
 {
     int ret = 0;
@@ -724,8 +773,6 @@ int cmd_dbd_scanvol(DBD *dbd_ref, struct volinfo *volinfo, dbd_flags_t flags)
     if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild)))
         goto exit_cleanup;
 
-//    dbif_dump(dbd_rebuild, 0);
-
     if (setjmp(jmp) != 0)
         goto exit_cleanup;      /* Got signal, jump from dbd_readdir */
 
@@ -733,7 +780,10 @@ int cmd_dbd_scanvol(DBD *dbd_ref, struct volinfo *volinfo, dbd_flags_t flags)
     if ( (scanvol(volinfo, flags)) != 0)
         return -1;
 
-//    dbif_dump(dbd_rebuild, 0);
+    /* We can only do this in excluse mode, otherwise we might delete CNIDs added from
+       other clients in between our pass 1 and 2 */
+    if (flags & DBD_FLAGS_EXCL)
+        delete_orphaned_cnids(dbd, dbd_rebuild, flags);
 
 exit_cleanup:
     dbif_close(dbd_rebuild);
index 726c958087de06cec2c35eb877a3c6b6ddd3a3a6..38401fc577be5f46a39de489fdbbb4ea4adb0e54 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbif.c,v 1.11 2009-05-18 09:54:14 franklahm Exp $
+ * $Id: dbif.c,v 1.12 2009-05-22 20:48:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * Copyright (C) Frank Lahm 2009
@@ -55,11 +55,23 @@ static int upgrade_required()
 int dbif_stamp(DBD *dbd, void *buffer, int size)
 {
     struct stat st;
-    int         rc;
+    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(rc));
         return -1;
@@ -67,6 +79,11 @@ int dbif_stamp(DBD *dbd, void *buffer, int size)
     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;
 }
 
@@ -260,7 +277,7 @@ int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags)
 }
 
 /* --------------- */
-int dbif_open(DBD *dbd, struct db_param *dbp _U_, int do_truncate)
+int dbif_open(DBD *dbd, struct db_param *dbp _U_, int reindex)
 {
     int ret;
     int i;
@@ -295,7 +312,7 @@ int dbif_open(DBD *dbd, struct db_param *dbp _U_, int do_truncate)
         if (dbd->db_errlog != NULL)
             dbd->db_table[i].db->set_errfile(dbd->db_table[i].db, dbd->db_errlog);
 
-        if (do_truncate && i > 0) {
+        if (reindex && i > 0) {
             LOG(log_info, logtype_cnid, "Truncating CNID index.");
             if ((ret = dbd->db_table[i].db->truncate(dbd->db_table[i].db, NULL, &count, 0))) {
                 LOG(log_error, logtype_cnid, "error truncating database %s: %s",
@@ -308,32 +325,32 @@ int dbif_open(DBD *dbd, struct db_param *dbp _U_, int do_truncate)
     /* TODO: Implement CNID DB versioning info on new databases. */
 
     /* Associate the secondary with the primary. */
-    if (do_truncate)
+    if (reindex)
         LOG(log_info, logtype_cnid, "Reindexing did/name index...");
     if ((ret = dbd->db_table[0].db->associate(dbd->db_table[DBIF_CNID].db,
                                               dbd->db_txn,
                                               dbd->db_table[DBIF_IDX_DIDNAME].db, 
                                               didname,
-                                              (do_truncate) ? DB_CREATE : 0))
+                                              (reindex) ? DB_CREATE : 0))
          != 0) {
         LOG(log_error, logtype_cnid, "Failed to associate didname database: %s",db_strerror(ret));
         return -1;
     }
-    if (do_truncate)
+    if (reindex)
         LOG(log_info, logtype_cnid, "... done.");
 
-    if (do_truncate)
+    if (reindex)
         LOG(log_info, logtype_cnid, "Reindexing dev/ino index...");
     if ((ret = dbd->db_table[0].db->associate(dbd->db_table[0].db, 
                                               dbd->db_txn,
                                               dbd->db_table[DBIF_IDX_DEVINO].db, 
                                               devino,
-                                              (do_truncate) ? DB_CREATE : 0))
+                                              (reindex) ? DB_CREATE : 0))
         != 0) {
         LOG(log_error, logtype_cnid, "Failed to associate devino database: %s",db_strerror(ret));
         return -1;
     }
-    if (do_truncate)
+    if (reindex)
         LOG(log_info, logtype_cnid, "... done.");
     
     return 0;
@@ -470,6 +487,12 @@ int dbif_del(DBD *dbd, const int dbi, DBT *key, u_int32_t flags)
 {
     int ret;
 
+    /* For cooperation with the dbd utility and its usage of a cursor */
+    if (dbd->db_cur) {
+        dbd->db_cur->close(dbd->db_cur);
+        dbd->db_cur = NULL;
+    }    
+
     if (dbif_txn_begin(dbd) < 0) {
         LOG(log_error, logtype_cnid, "error deleting key/value from %s: %s", 
             dbd->db_table[dbi].name, db_strerror(errno));
@@ -798,3 +821,57 @@ int dbif_dump(DBD *dbd, int dumpindexes)
     return 0;
 }
 
+/* 
+   Iterates over dbd, returning cnids.
+   Uses in-value of cnid to seek to that cnid, then gets next and return that in cnid.
+   If close=1, close cursor.
+   Return -1 on error, 0 on EOD (end-of-database), 1 if returning cnid.
+*/
+int dbif_idwalk(DBD *dbd, cnid_t *cnid, int close)
+{
+    int rc;
+    int flag;
+    cnid_t id;
+
+    static DBT key = { 0 }, data = { 0 };
+    DB *db = dbd->db_table[DBIF_CNID].db;
+
+    if (close && dbd->db_cur) {
+        dbd->db_cur->close(dbd->db_cur);
+        dbd->db_cur = NULL;
+        return 0;
+    }
+
+    /* An dbif_del will have closed our cursor too */
+    if ( ! dbd->db_cur ) {
+        if (db->cursor(db, NULL, &dbd->db_cur, 0) != 0) {
+            LOG(log_error, logtype_cnid, "Couldn't create cursor: %s", db_strerror(errno));
+            return -1;
+        }
+        flag = DB_SET_RANGE;    /* This will seek to next cnid after the one just deleted */
+        id = htonl(*cnid);
+        key.data = &id;
+        key.size = sizeof(cnid_t);
+    } else
+        flag = DB_NEXT;
+
+    if ((rc = dbd->db_cur->get(dbd->db_cur, &key, &data, flag)) == 0) {
+        memcpy(cnid, key.data, sizeof(cnid_t));
+        *cnid = ntohl(*cnid);
+        return 1;
+    }
+
+    if (rc != DB_NOTFOUND) {
+        LOG(log_error, logtype_cnid, "Error iterating over btree: %s", db_strerror(errno));
+        dbd->db_cur->close(dbd->db_cur);
+        dbd->db_cur = NULL;
+        return -1;
+    }
+
+    if (dbd->db_cur) {
+        dbd->db_cur->close(dbd->db_cur);
+        dbd->db_cur = NULL;
+    }    
+
+    return 0;
+}
index fcb8b0bde516663b51ac5eafe945500030fe7941..a14c02d3ba1fe13f603da96eca2df92037c77c64 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  $Id: dbif.h,v 1.6 2009-05-14 13:46:08 franklahm Exp $
+  $Id: dbif.h,v 1.7 2009-05-22 20:48:44 franklahm Exp $
  
   Copyright (C) Joerg Lenneis 2003
   Copyright (C) Frank Lahm 2009
@@ -48,6 +48,7 @@
 
 #include <sys/cdefs.h>
 #include <db.h>
+#include <atalk/adouble.h>
 #include "db_param.h"
 
 #define DBIF_DB_CNT 3
@@ -68,6 +69,7 @@ typedef struct {
 typedef struct {
     DB_ENV   *db_env;
     DB_TXN   *db_txn;
+    DBC      *db_cur;              /* for dbif_walk */
     char     *db_envhome;
     char     *db_filename;
     FILE     *db_errlog;
@@ -77,14 +79,13 @@ typedef struct {
 /* Functions */
 extern DBD *dbif_init(const char *envhome, const char *dbname);
 extern int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags);
-extern int dbif_open(DBD *dbd, struct db_param *dbp, int do_truncate);
+extern int dbif_open(DBD *dbd, struct db_param *dbp, int reindex);
 extern int dbif_close(DBD *dbd);
 
 extern int dbif_get(DBD *, const int, DBT *, DBT *, u_int32_t);
 extern int dbif_pget(DBD *, const int, DBT *, DBT *, DBT *, u_int32_t);
 extern int dbif_put(DBD *, const int, DBT *, DBT *, u_int32_t);
 extern int dbif_del(DBD *, const int, DBT *, u_int32_t);
-
 extern int dbif_count(DBD *, const int, u_int32_t *);
 extern int dbif_stamp(DBD *, void *, int);
 extern int dbif_copy_rootinfokey(DBD *srcdbd, DBD *destdbd);
@@ -94,6 +95,6 @@ extern int dbif_txn_abort(DBD *);
 extern void dbif_txn_close(DBD *dbd, int ret); /* Switch between commit+abort */
 extern int dbif_txn_checkpoint(DBD *, u_int32_t, u_int32_t, u_int32_t);
 
-extern int dbif_dump(DBD *, int dumpindexes);
-
+extern int dbif_dump(DBD *dbd, int dumpindexes);
+extern int dbif_idwalk(DBD *dbd, cnid_t *cnid, int close);
 #endif
index e4cf9753ea90ce677660b51708c1685a978ff1c8..9ff6498b94ce0208e79427ebccc7608c97a04a90 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: adouble.h,v 1.33 2008-12-03 18:35:44 didg Exp $
+ * $Id: adouble.h,v 1.34 2009-05-22 20:48:44 franklahm Exp $
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
  *
@@ -529,6 +529,7 @@ extern int ad_setname __P((struct adouble *, const char *));
 #if AD_VERSION == AD_VERSION2
 extern int ad_setid __P((struct adouble *, const dev_t dev,const ino_t ino, const u_int32_t, const u_int32_t, const void *));
 extern u_int32_t ad_getid __P((struct adouble *, const dev_t, const ino_t, const cnid_t, const void *));
+extern u_int32_t ad_forcegetid __P((struct adouble *adp));
 #else
 #define ad_setid(a, b, c)
 #endif
index e95e36e647c9533b096bd347572f26e6ddd39c86..791682e256581f37060fa469121df3612ab91734 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_attr.c,v 1.6 2006-09-29 09:39:16 didg Exp $
+ * $Id: ad_attr.c,v 1.7 2009-05-22 20:48:44 franklahm Exp $
  */
 
 #ifdef HAVE_CONFIG_H
 
 int ad_getattr(const struct adouble *ad, u_int16_t *attr)
 {
-   *attr = 0;
-        
-   if (ad->ad_version == AD_VERSION1) {
-       if (ad_getentryoff(ad, ADEID_FILEI)) {
-           memcpy(attr, ad_entry(ad, ADEID_FILEI) + FILEIOFF_ATTR,
-                 sizeof(u_int16_t));
-       }
-   }
+    *attr = 0;
+
+    if (ad->ad_version == AD_VERSION1) {
+        if (ad_getentryoff(ad, ADEID_FILEI)) {
+            memcpy(attr, ad_entry(ad, ADEID_FILEI) + FILEIOFF_ATTR,
+                   sizeof(u_int16_t));
+        }
+    }
 #if AD_VERSION == AD_VERSION2
-   else if (ad->ad_version == AD_VERSION2) {
-       if (ad_getentryoff(ad, ADEID_AFPFILEI)) {
-           memcpy(attr, ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR,
-                 sizeof(u_int16_t));
-       }
-   }      
+    else if (ad->ad_version == AD_VERSION2) {
+        if (ad_getentryoff(ad, ADEID_AFPFILEI)) {
+            memcpy(attr, ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR,
+                   sizeof(u_int16_t));
+        }
+    }
 #endif
-   else 
-      return -1;
+    else
+        return -1;
 
-   *attr |= htons(ad->ad_open_forks);
+    *attr |= htons(ad->ad_open_forks);
 
-   return 0;
+    return 0;
 }
 
 /* ----------------- */
 int ad_setattr(const struct adouble *ad, const u_int16_t attribute)
 {
-   /* we don't save open forks indicator */
-   u_int16_t attr = attribute & ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN);
-
-   if (ad->ad_version == AD_VERSION1) {
-       if (ad_getentryoff(ad, ADEID_FILEI)) {
-           memcpy(ad_entry(ad, ADEID_FILEI) + FILEIOFF_ATTR, &attr,
-                  sizeof(attr));
-       }
-   }      
+    /* we don't save open forks indicator */
+    u_int16_t attr = attribute & ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN);
+
+    if (ad->ad_version == AD_VERSION1) {
+        if (ad_getentryoff(ad, ADEID_FILEI)) {
+            memcpy(ad_entry(ad, ADEID_FILEI) + FILEIOFF_ATTR, &attr,
+                   sizeof(attr));
+        }
+    }
 #if AD_VERSION == AD_VERSION2
-   else if (ad->ad_version == AD_VERSION2) {
-       if (ad_getentryoff(ad, ADEID_AFPFILEI)) {
+    else if (ad->ad_version == AD_VERSION2) {
+        if (ad_getentryoff(ad, ADEID_AFPFILEI)) {
             memcpy(ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, &attr,
-                   sizeof(attr));
-       }
-   }      
+                   sizeof(attr));
+        }
+    }
 #endif
-   else 
-      return -1;
+    else
+        return -1;
 
-   return 0;
+    return 0;
 }
 
-/* -------------- 
+/* --------------
  * save file/folder ID in AppleDoubleV2 netatalk private parameters
  * return 1 if resource fork has been modified
-*/
+ */
 #if AD_VERSION == AD_VERSION2
 int ad_setid (struct adouble *adp, const dev_t dev, const ino_t ino , const u_int32_t id, const cnid_t did, const void *stamp)
 {
     if (adp->ad_flags == AD_VERSION2  && ( adp->ad_options & ADVOL_CACHE) &&
-                ad_getentryoff(adp, ADEID_PRIVDEV) &&
-                sizeof(dev_t) == ADEDLEN_PRIVDEV && sizeof(ino_t) == ADEDLEN_PRIVINO) 
+        ad_getentryoff(adp, ADEID_PRIVDEV) &&
+        sizeof(dev_t) == ADEDLEN_PRIVDEV && sizeof(ino_t) == ADEDLEN_PRIVINO)
     {
         ad_setentrylen( adp, ADEID_PRIVDEV, sizeof(dev_t));
-       if ((adp->ad_options & ADVOL_NODEV)) {
+        if ((adp->ad_options & ADVOL_NODEV)) {
             memset(ad_entry( adp, ADEID_PRIVDEV ), 0, sizeof(dev_t));
         }
-       else {
+        else {
             memcpy(ad_entry( adp, ADEID_PRIVDEV ), &dev, sizeof(dev_t));
         }
 
         ad_setentrylen( adp, ADEID_PRIVINO, sizeof(ino_t));
         memcpy(ad_entry( adp, ADEID_PRIVINO ), &ino, sizeof(ino_t));
 
-       ad_setentrylen( adp, ADEID_PRIVID, sizeof(id));
+        ad_setentrylen( adp, ADEID_PRIVID, sizeof(id));
         memcpy(ad_entry( adp, ADEID_PRIVID ), &id, sizeof(id));
 
         ad_setentrylen( adp, ADEID_DID, sizeof(did));
@@ -102,43 +102,59 @@ int ad_setid (struct adouble *adp, const dev_t dev, const ino_t ino , const u_in
 /* ----------------------------- */
 u_int32_t ad_getid (struct adouble *adp, const dev_t st_dev, const ino_t st_ino , const cnid_t did, const void *stamp)
 {
-u_int32_t aint = 0;
-dev_t  dev;
-ino_t  ino;
-cnid_t a_did;
-char   temp[ADEDLEN_PRIVSYN];
+    u_int32_t aint = 0;
+    dev_t  dev;
+    ino_t  ino;
+    cnid_t a_did;
+    char   temp[ADEDLEN_PRIVSYN];
 
-    /* look in AD v2 header 
+    /* look in AD v2 header
      * note inode and device are opaques and not in network order
      * only use the ID if adouble is writable for us.
-    */
+     */
     if (adp && ( adp->ad_options & ADVOL_CACHE) && ( adp->ad_md->adf_flags & O_RDWR )
-            && sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)
-            && sizeof(ino_t) == ad_getentrylen(adp,ADEID_PRIVINO)
-            && sizeof(temp) == ad_getentrylen(adp,ADEID_PRIVSYN)
-            && sizeof(cnid_t) == ad_getentrylen(adp, ADEID_DID)
-            && sizeof(cnid_t) == ad_getentrylen(adp, ADEID_PRIVID)
-    ) {
+        && sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)
+        && sizeof(ino_t) == ad_getentrylen(adp,ADEID_PRIVINO)
+        && sizeof(temp) == ad_getentrylen(adp,ADEID_PRIVSYN)
+        && sizeof(cnid_t) == ad_getentrylen(adp, ADEID_DID)
+        && sizeof(cnid_t) == ad_getentrylen(adp, ADEID_PRIVID)
+        ) {
         memcpy(&dev, ad_entry(adp, ADEID_PRIVDEV), sizeof(dev_t));
         memcpy(&ino, ad_entry(adp, ADEID_PRIVINO), sizeof(ino_t));
         memcpy(temp, ad_entry(adp, ADEID_PRIVSYN), sizeof(temp));
         memcpy(&a_did, ad_entry(adp, ADEID_DID), sizeof(cnid_t));
 
         if (  ((adp->ad_options & ADVOL_NODEV) || dev == st_dev)
-              && ino == st_ino && a_did == did 
-              && !memcmp(stamp, temp, sizeof(temp))) { 
+              && ino == st_ino && a_did == did
+              && !memcmp(stamp, temp, sizeof(temp))) {
             memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
             return aint;
         }
     }
-    return 0; 
+    return 0;
 }
 
+/* ----------------------------- */
+u_int32_t ad_forcegetid (struct adouble *adp)
+{
+    u_int32_t aint = 0;
+
+    if (adp && ( adp->ad_options & ADVOL_CACHE)
+        && sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)
+        && sizeof(ino_t) == ad_getentrylen(adp,ADEID_PRIVINO)
+        && sizeof(cnid_t) == ad_getentrylen(adp, ADEID_DID)
+        && sizeof(cnid_t) == ad_getentrylen(adp, ADEID_PRIVID)
+        ) {
+        memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
+        return aint;
+    }
+    return 0;
+}
 #endif
 
-/* ----------------- 
+/* -----------------
  * set resource fork filename attribute.
-*/
+ */
 int ad_setname(struct adouble *ad, const char *path)
 {
     if (ad_getentryoff(ad, ADEID_NAME)) {