]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/cnid/tdb/cnid_tdb_add.c
Support for using $u username variable in AFP volume definitions
[netatalk.git] / libatalk / cnid / tdb / cnid_tdb_add.c
index fe5d36286d11675c38441c145a333b0a03bd10ab..b3babcd35f2b87f58d9f08474dbf9bea15099ccd 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: cnid_tdb_add.c,v 1.3 2005-05-03 14:55:15 didg Exp $
- *
  * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
  * All Rights Reserved. See COPYRIGHT.
  *
 #include <unistd.h>
 #include <atalk/logger.h>
 
-/* add an entry to the CNID databases. we do this as a transaction
- * to prevent messiness. */
+static void make_devino_data(unsigned char *buf, dev_t dev, ino_t ino)
+{
+    buf[CNID_DEV_LEN - 1] = dev; dev >>= 8;
+    buf[CNID_DEV_LEN - 2] = dev; dev >>= 8;
+    buf[CNID_DEV_LEN - 3] = dev; dev >>= 8;
+    buf[CNID_DEV_LEN - 4] = dev; dev >>= 8;
+    buf[CNID_DEV_LEN - 5] = dev; dev >>= 8;
+    buf[CNID_DEV_LEN - 6] = dev; dev >>= 8;
+    buf[CNID_DEV_LEN - 7] = dev; dev >>= 8;
+    buf[CNID_DEV_LEN - 8] = dev;
+
+    buf[CNID_DEV_LEN + CNID_INO_LEN - 1] = ino; ino >>= 8;
+    buf[CNID_DEV_LEN + CNID_INO_LEN - 2] = ino; ino >>= 8;
+    buf[CNID_DEV_LEN + CNID_INO_LEN - 3] = ino; ino >>= 8;
+    buf[CNID_DEV_LEN + CNID_INO_LEN - 4] = ino; ino >>= 8;
+    buf[CNID_DEV_LEN + CNID_INO_LEN - 5] = ino; ino >>= 8;
+    buf[CNID_DEV_LEN + CNID_INO_LEN - 6] = ino; ino >>= 8;
+    buf[CNID_DEV_LEN + CNID_INO_LEN - 7] = ino; ino >>= 8;
+    buf[CNID_DEV_LEN + CNID_INO_LEN - 8] = ino;    
+}
+
+unsigned char *make_tdb_data(uint32_t flags, const struct stat *st,const cnid_t did,
+                     const char *name, const size_t len)
+{
+    static unsigned char start[CNID_HEADER_LEN + MAXPATHLEN + 1];
+    unsigned char *buf = start  +CNID_LEN;
+    uint32_t i;
+
+    if (len > MAXPATHLEN)
+        return NULL;
 
+    make_devino_data(buf, !(flags & CNID_FLAG_NODEV)?st->st_dev:0, st->st_ino);
+    buf += CNID_DEVINO_LEN;
+
+    i = S_ISDIR(st->st_mode)?1:0;
+    i = htonl(i);
+    memcpy(buf, &i, sizeof(i));
+    buf += sizeof(i);
+    
+    /* did is already in network byte order */
+    memcpy(buf, &did, sizeof(did));
+    buf += sizeof(did);
+
+    memcpy(buf, name, len);
+    *(buf + len) = '\0';
+
+    return start;
+}    
+
+/* add an entry to the CNID databases. we do this as a transaction
+ * to prevent messiness. 
+ * key:   cnid
+ * data:
+ */
 static int add_cnid (struct _cnid_tdb_private *db, TDB_DATA *key, TDB_DATA *data) {
     TDB_DATA altkey, altdata;
 
@@ -35,8 +84,8 @@ static int add_cnid (struct _cnid_tdb_private *db, TDB_DATA *key, TDB_DATA *data
     }
 
     /* dev/ino database */
-    altkey.dptr = data->dptr;
-    altkey.dsize = TDB_DEVINO_LEN;
+    altkey.dptr = data->dptr +CNID_DEVINO_OFS;
+    altkey.dsize = CNID_DEVINO_LEN;
     altdata.dptr = key->dptr;
     altdata.dsize = key->dsize;
     if (tdb_store(db->tdb_devino, altkey, altdata, TDB_REPLACE)) {
@@ -44,8 +93,8 @@ static int add_cnid (struct _cnid_tdb_private *db, TDB_DATA *key, TDB_DATA *data
     }
 
     /* did/name database */
-    altkey.dptr = (char *) data->dptr + TDB_DEVINO_LEN;
-    altkey.dsize = data->dsize - TDB_DEVINO_LEN;
+    altkey.dptr = data->dptr +CNID_DID_OFS;
+    altkey.dsize = data->dsize -CNID_DID_OFS;
     if (tdb_store(db->tdb_didname, altkey, altdata, TDB_REPLACE)) {
         goto abort;
     }
@@ -63,7 +112,7 @@ static cnid_t get_cnid(struct _cnid_tdb_private *db)
     
     memset(&rootinfo_key, 0, sizeof(rootinfo_key));
     memset(&data, 0, sizeof(data));
-    rootinfo_key.dptr = ROOTINFO_KEY;
+    rootinfo_key.dptr = (unsigned char *)ROOTINFO_KEY;
     rootinfo_key.dsize = ROOTINFO_KEYLEN;
     
     tdb_chainlock(db->tdb_didname, rootinfo_key);  
@@ -83,11 +132,11 @@ static cnid_t get_cnid(struct _cnid_tdb_private *db)
         hint = htonl(id);
     }
     else {
-        hint = htonl(TDB_START);
+        hint = htonl(CNID_START);
     }
     
     memset(&data, 0, sizeof(data));
-    data.dptr = (char *)&hint;
+    data.dptr = (unsigned char *)&hint;
     data.dsize = sizeof(hint);
     if (tdb_store(db->tdb_didname, rootinfo_key, data, TDB_REPLACE)) {
         goto cleanup;
@@ -103,7 +152,7 @@ cleanup:
 
 /* ------------------------ */
 cnid_t cnid_tdb_add(struct _cnid_db *cdb, const struct stat *st,
-                     const cnid_t did, char *name, const size_t len, cnid_t hint)
+                    cnid_t did, const char *name, size_t len, cnid_t hint)
 {
     const struct stat *lstp;
     cnid_t id;
@@ -111,14 +160,14 @@ cnid_t cnid_tdb_add(struct _cnid_db *cdb, const struct stat *st,
     TDB_DATA key, data; 
     int rc;      
     
-    if (!cdb || !(priv = cdb->_private) || !st || !name) {
+    if (!cdb || !(priv = cdb->cnid_db_private) || !st || !name) {
         errno = CNID_ERR_PARAM;
         return CNID_INVALID;
     }
     /* Do a lookup. */
     id = cnid_tdb_lookup(cdb, st, did, name, len);
     /* ... Return id if it is valid, or if Rootinfo is read-only. */
-    if (id || (priv->flags & TDBFLAG_DB_RO)) {
+    if (id || (priv->flags & CNIDFLAG_DB_RO)) {
         return id;
     }
 
@@ -132,19 +181,20 @@ cnid_t cnid_tdb_add(struct _cnid_db *cdb, const struct stat *st,
     memset(&key, 0, sizeof(key));
     memset(&data, 0, sizeof(data));
 
-    key.dptr = (char *)&hint;
+    key.dptr = (unsigned char *)&hint;
     key.dsize = sizeof(cnid_t);
-    if ((data.dptr = make_tdb_data(lstp, did, name, len)) == NULL) {
+    if ((data.dptr = make_tdb_data(cdb->cnid_db_flags, lstp, did, name, len)) == NULL) {
         LOG(log_error, logtype_default, "tdb_add: Path name is too long");
         errno = CNID_ERR_PATH;
         return CNID_INVALID;
     }
-    data.dsize = TDB_HEADER_LEN + len + 1;
+    data.dsize = CNID_HEADER_LEN + len + 1;
     hint = get_cnid(priv);
     if (hint == 0) {
         errno = CNID_ERR_DB;
         return CNID_INVALID;
     }
+    memcpy(data.dptr, &hint, sizeof(hint));
     
     /* Now we need to add the CNID data to the databases. */
     rc = add_cnid(priv, &key, &data);