]> arthur.barton.de Git - netatalk.git/commitdiff
fixes for tdb remaining errors vs cdb
authordidg <didg>
Sat, 21 Nov 2009 11:12:49 +0000 (11:12 +0000)
committerdidg <didg>
Sat, 21 Nov 2009 11:12:49 +0000 (11:12 +0000)
libatalk/cnid/tdb/cnid_tdb_lookup.c
libatalk/cnid/tdb/cnid_tdb_update.c

index c693341450ff3e9705a9826ac03c7b7889376f30..ba47e36837f197c42f6b302f0a22ed78ca68e77c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cnid_tdb_lookup.c,v 1.5 2009-11-20 19:25:05 didg Exp $
+ * $Id: cnid_tdb_lookup.c,v 1.6 2009-11-21 11:12:49 didg Exp $
  */
 
 #ifdef HAVE_CONFIG_H
@@ -15,9 +15,15 @@ cnid_t cnid_tdb_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t
 {
     char *buf;
     struct _cnid_tdb_private *db;
-    TDB_DATA key, devdata, diddata;
+    TDB_DATA key, devdata, diddata, cniddata;
     int devino = 1, didname = 1;
-    cnid_t id = 0;
+    char dev[CNID_DEV_LEN];
+    char ino[CNID_INO_LEN];  
+    u_int32_t type_devino  = (unsigned)-1;
+    u_int32_t type_didname = (unsigned)-1;
+    u_int32_t type;
+    int update = 0;
+    cnid_t id_devino = 0, id_didname = 0,id = 0;
 
     if (!cdb || !(db = cdb->_private) || !st || !name) {
         return 0;
@@ -27,39 +33,119 @@ cnid_t cnid_tdb_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t
         LOG(log_error, logtype_default, "tdb_lookup: Pathname is too long");
         return 0;
     }
+    memcpy(&type, buf +CNID_TYPE_OFS, sizeof(type));
+    type = ntohl(type);
 
     memset(&key, 0, sizeof(key));
     memset(&devdata, 0, sizeof(devdata));
     memset(&diddata, 0, sizeof(diddata));
+    memset(&cniddata, 0, sizeof(cniddata));
 
     /* Look for a CNID.  We have two options: dev/ino or did/name.  If we
     * only get a match in one of them, that means a file has moved. */
+    memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
+    memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN);
+
     key.dptr = buf +CNID_DEVINO_OFS;
     key.dsize  = CNID_DEVINO_LEN;
-    devdata = tdb_fetch(db->tdb_devino, key);
-    if (!devdata.dptr) {
+    cniddata = tdb_fetch(db->tdb_devino, key);
+    if (!cniddata.dptr) {
          devino = 0;
     }
+    else {
+        
+        key.dptr = cniddata.dptr;
+        key.dsize = sizeof(id);
+
+        devdata = tdb_fetch(db->tdb_cnid, key);
+        free(cniddata.dptr);
+        if (devdata.dptr) {
+            memcpy(&id_devino, devdata.dptr, sizeof(cnid_t));
+            memcpy(&type_devino, (char *)devdata.dptr +CNID_TYPE_OFS, sizeof(type_devino));
+            type_devino = ntohl(type_devino);
+        }
+        else {
+             devino = 0;
+        }
+    }
+
     /* did/name now */
     key.dptr = buf + CNID_DID_OFS;
     key.dsize = CNID_DID_LEN + len + 1;
-    diddata = tdb_fetch(db->tdb_didname, key);
-    if (!diddata.dptr) {
+    cniddata = tdb_fetch(db->tdb_didname, key);
+    if (!cniddata.dptr) {
         didname = 0;
     }
+    else {
+        
+        key.dptr = cniddata.dptr;
+        key.dsize = sizeof(id);
+
+        diddata = tdb_fetch(db->tdb_cnid, key);
+        free(cniddata.dptr);
+        if (diddata.dptr) {
+            memcpy(&id_didname, diddata.dptr, sizeof(cnid_t));
+            memcpy(&type_didname, (char *)diddata.dptr +CNID_TYPE_OFS, sizeof(type_didname));
+            type_didname = ntohl(type_didname);
+        }
+        else {
+             didname = 0;
+        }
+    }
     /* Set id.  Honor did/name over dev/ino as dev/ino isn't necessarily
      * 1-1. */
+    if (!devino && !didname) {  
+        free(devdata.dptr);
+        free(diddata.dptr);
+        return 0;
+    }
+
+    if (devino && didname && id_devino == id_didname && type_devino == type) {
+        /* the same */
+        free(devdata.dptr);
+        free(diddata.dptr);
+        return id_didname;
+    }
     if (didname) {
-        memcpy(&id, diddata.dptr, sizeof(id));
+        id = id_didname;
+        /* we have a did:name 
+         * if it's the same dev or not the same type
+         * just delete it
+        */
+        if (!memcmp(dev, (char *)diddata.dptr + CNID_DEV_OFS, CNID_DEV_LEN) ||
+                   type_didname != type) {
+            if (cnid_tdb_delete(cdb, id) < 0) {
+                free(devdata.dptr);
+                free(diddata.dptr);
+                return 0;
+            }
+        }
+        else {
+            update = 1;
+        }
     }
-    else if (devino) {
-        memcpy(&id, devdata.dptr, sizeof(id));
+
+    if (devino) {
+        id = id_devino;
+        if (type_devino != type) {
+            /* same dev:inode but not same type one is a folder the other 
+             * is a file,it's an inode reused, delete the record
+            */
+            if (cnid_tdb_delete(cdb, id) < 0) {
+                free(devdata.dptr);
+                free(diddata.dptr);
+                return 0;
+            }
+        }
+        else {
+            update = 1;
+        }
     }
     free(devdata.dptr);
     free(diddata.dptr);
-    /* Either entries are in both databases or neither of them. */
-    if ((devino && didname) || !(devino || didname)) {
-        return id;
+    if (!update) {
+        return 0;
     }
 
     /* Fix up the database. */
index 44873ac998276fce2867da944f9ae6e2c708ec69..8c4d35e379dd535b7085719df8c6eb783c719d1e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cnid_tdb_update.c,v 1.5 2009-11-20 19:25:05 didg Exp $
+ * $Id: cnid_tdb_update.c,v 1.6 2009-11-21 11:12:49 didg Exp $
  */
 
 #ifdef HAVE_CONFIG_H
@@ -78,6 +78,7 @@ int cnid_tdb_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st
     /* Make a new entry. */
     data.dptr = make_tdb_data(cdb->flags, st, did, name, len);
     data.dsize = CNID_HEADER_LEN + len + 1;
+    memcpy(data.dptr, &id, sizeof(id));
 
     /* Update the old CNID with the new info. */
     key.dptr = (char *) &id;