]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/cnid/cnid_lookup.c
MFH:
[netatalk.git] / libatalk / cnid / cnid_lookup.c
index 5987c12d84bb0ed820676a9389e19840ab580ea6..f061cb4891cf14ebbc2b35d5d5413d632cb14946 100644 (file)
@@ -1,16 +1,17 @@
 /*
- * $Id: cnid_lookup.c,v 1.2 2001-06-29 14:14:46 rufustfirefly Exp $
+ * $Id: cnid_lookup.c,v 1.14.2.1 2003-02-08 03:16:53 jmarcus Exp $
  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
+#ifdef CNID_DB
 #include <stdio.h>
 #include <string.h>
 #include <sys/param.h>
 #include <sys/stat.h>
-#include <syslog.h>
+#include <atalk/logger.h>
 #include <errno.h>
 
 #include <db.h>
 #define LOGFILEMAX    100  /* kbytes */
 #define CHECKTIMEMAX   30  /* minutes */
 
-/* this returns the cnid corresponding to a particular file. it will
-   also fix up the various databases if there's a problem. */
-cnid_t cnid_lookup(void *CNID,
-                  const struct stat *st, const cnid_t did, 
-                  const char *name, const int len)
+/* This returns the CNID corresponding to a particular file.  It will
+ * also fix up the various databases if there's a problem. */
+cnid_t cnid_lookup(void *CNID, const struct stat *st, const cnid_t did,
+                   const char *name, const int len)
 {
-  char *buf;
-  CNID_private *db;
-  DBT key, devdata, diddata;
-  DB_TXNMGR *txnp;
-  int devino = 1, didname = 1;
-  cnid_t id = 0;
-  
-  if (!(db = CNID) || !st || !name)
-    return 0;
-
-  /* do a little checkpointing if necessary. i stuck it here as 
-   * cnid_lookup gets called when we do directory lookups. only do 
-   * this if we're using a read-write database. */
-  if ((db->flags & CNIDFLAG_DB_RO) == 0) {
-    txnp = db->dbenv.tx_info;
-    errno = txn_checkpoint(txnp, LOGFILEMAX, CHECKTIMEMAX);
-    while (errno == DB_INCOMPLETE)
-      errno = txn_checkpoint(txnp, 0, 0);
-  }
-
- if ((buf = make_cnid_data(st, did, name, len)) == NULL) {
-    syslog(LOG_ERR, "cnid_lookup: path name too long");
-    return 0;
-  }
-
-  memset(&key, 0, sizeof(key));
-  memset(&devdata, 0, sizeof(devdata));
-
-  /* look for a CNID. we have two options: dev/ino or did/name. if we
-     only get a match on one of them, that means a file has moved. */
-  key.data = buf; /* dev/ino is the first part of the buffer */
-  key.size = CNID_DEVINO_LEN;
-  while (errno = db->db_devino->get(db->db_devino, NULL,
-                                   &key, &devdata, 0)) {
-    if (errno == EAGAIN)
-      continue;
-    
-    if (errno == DB_NOTFOUND) {
-      devino = 0;
-      break;
+    char *buf;
+    CNID_private *db;
+    DBT key, devdata, diddata;
+    int devino = 1, didname = 1;
+    cnid_t id = 0;
+    int rc;
+
+    if (!(db = CNID) || !st || !name) {
+        return 0;
     }
-    
-    syslog(LOG_ERR, "cnid_lookup: can't get CNID(%u/%u)",
-          st->st_dev, st->st_ino);
-    return 0;
-  }
-
-  /* did/name is right afterwards. */
-  key.data = buf + CNID_DEVINO_LEN; 
-  key.size = CNID_DID_LEN + len + 1;
-  memset(&diddata, 0, sizeof(diddata));
-  while (errno = db->db_didname->get(db->db_didname, NULL,
-                                      &key, &diddata, 0)) {
-    if (errno == EAGAIN)
-      continue;
-
-    if (errno == DB_NOTFOUND) {
-      didname = 0;
-      break;
+
+#ifndef CNID_DB_CDB
+    /* Do a little checkpointing if necessary.  I stuck it here as cnid_lookup
+     * gets called when we do directory lookups.  Only do this if we're using
+     * a read-write database. */
+    if ((db->flags & CNIDFLAG_DB_RO) == 0) {
+#ifdef DEBUG
+        LOG(log_info, logtype_default, "cnid_lookup: Running database checkpoint");
+#endif
+#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
+        db->dbenv->txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0)
+#else
+#if DB_VERSION_MAJOR >= 4
+        switch (rc = db->dbenv->txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0)) {
+#else
+        switch (rc = txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0)) {
+#endif /* DB_VERSION_MAJOR >= 4 */
+        case 0:
+        case DB_INCOMPLETE:
+            break;
+        default:
+            LOG(log_error, logtype_default, "cnid_lookup: txn_checkpoint: %s",
+                db_strerror(rc));
+            return 0;
+        }
+    }
+#endif /* DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) */
+#endif /* CNID_DB_CDB */
+
+        if ((buf = make_cnid_data(st, did, name, len)) == NULL) {
+            LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long");
+            return 0;
+        }
+
+        memset(&key, 0, sizeof(key));
+        memset(&devdata, 0, sizeof(devdata));
+        memset(&diddata, 0, sizeof(diddata));
+
+        /* 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. */
+        key.data = buf;
+        key.size = CNID_DEVINO_LEN;
+        while ((rc = db->db_devino->get(db->db_devino, NULL, &key, &devdata, 0))) {
+#ifndef CNID_DB_CDB
+            if (rc == DB_LOCK_DEADLOCK) {
+                continue;
+            }
+#endif /* CNID_DB_CDB */
+
+            if (rc == DB_NOTFOUND) {
+                devino = 0;
+                break;
+            }
+
+            LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID dev %u, ino %u: %s",
+                st->st_dev, st->st_ino, db_strerror(rc));
+            return 0;
+        }
+
+        /* did/name now */
+        key.data = buf + CNID_DEVINO_LEN;
+        key.size = CNID_DID_LEN + len + 1;
+        while ((rc = db->db_didname->get(db->db_didname, NULL, &key, &diddata, 0))) {
+#ifndef CNID_DB_CDB
+            if (rc == DB_LOCK_DEADLOCK) {
+                continue;
+            }
+#endif /* CNID_DB_CDB */
+
+            if (rc == DB_NOTFOUND) {
+                didname = 0;
+                break;
+            }
+
+            LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID %u, name %s: %s",
+                ntohl(did), name, db_strerror(rc));
+            return 0;
+        }
+
+        /* Set id.  Honor did/name over dev/ino as dev/ino isn't necessarily
+         * 1-1. */
+        if (didname) {
+            memcpy(&id, diddata.data, sizeof(id));
+        }
+        else if (devino) {
+            memcpy(&id, devdata.data, sizeof(id));
+        }
+
+        /* Either entries are in both databases or neither of them. */
+        if ((devino && didname) || !(devino || didname)) {
+#ifdef DEBUG
+            LOG(log_info, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u",
+                ntohl(did), name, ntohl(id));
+#endif
+            return id;
+        }
+
+        /* Fix up the database. */
+        cnid_update(db, id, st, did, name, len);
+#ifdef DEBUG
+        LOG(log_info, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u (needed update)", ntohl(did), name, ntohl(id));
+#endif
+        return id;
     }
+#endif /* CNID_DB */
+
 
-    syslog(LOG_ERR, "cnid_lookup: can't get CNID(%u:%s)",
-          did, name);
-    return 0;
-  }
-
-  /* set id. honor did/name over dev/ino as dev/ino isn't necessarily 
-   * 1-1. */
-  if (didname) {
-    memcpy(&id, diddata.data, sizeof(id));
-  } else if (devino) {
-    memcpy(&id, devdata.data, sizeof(id));
-  } 
-
-  /* either entries in both databases exist or neither of them do. */
-  if ((devino && didname) || !(devino || didname)) 
-    return id;
-
-  /* fix up the databases */
-  cnid_update(db, id, st, did, name, len);
-  return id;
-}