]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/directory.c
Add some description of dir caching in afpd
[netatalk.git] / etc / afpd / directory.c
index 810c1c248e3325ed6476d2f496c55586d2dcef9d..a2b746eef79a8767728d7527530ec24e68d86803 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.119 2009-11-19 10:41:23 franklahm Exp $
+ * $Id: directory.c,v 1.126 2010-01-06 15:37:01 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -62,6 +62,41 @@ char *strchr (), *strrchr ();
 extern void addir_inherit_acl(const struct vol *vol);
 #endif
 
+/* 
+ * Directory caches
+ * ================
+ *
+ * There are currently two cache structures where afpd caches directory information
+ * a) a DID/dirname cache in a hashtable 
+ * b) a (red-black) tree with CNIDs as key
+ *
+ * a) is for searching by DID/dirname
+ * b) is for searching by CNID
+ *
+ * Through additional parent, child, previous and next pointers, b) is also used to
+ * represent the on-disk layout of the filesystem. parent and child point to parent
+ * and child directory respectively, linking 2 or more subdirectories in one
+ * directory with previous and next pointers.
+ *
+ * Usage examples, highlighting the main functions:
+ * 
+ * a) is eg used in enumerate():
+ * if IS_DIR
+ *     dir = dirsearch_byname() // search in cache
+ *     if (dir == NULL)         // not found
+ *         dir = adddir()       // add to cache
+ *      getdirparams()
+ *
+ * b) is eg used in afp_getfildirparams()
+ * dirlookup()             // wrapper for cache and db search
+ *   => dir = dirsearch()  // search in cache
+ *      if (dir)           // found
+ *          return
+ *      else               // not found,
+ *          cnid_resolve() // resolve with CNID database
+ *      cname()            // add to cache
+ */
+
 struct dir  *curdir;
 int             afp_errno;
 
@@ -988,6 +1023,7 @@ adddir(struct vol *vol, struct dir *dir, struct path *path)
         dirfreename(edir);
         edir->d_m_name = cdir->d_m_name;
         edir->d_u_name = cdir->d_u_name;
+        edir->d_u_name_len = cdir->d_u_name_len;
         edir->d_m_name_ucs2 = cdir->d_m_name_ucs2;
         free(cdir);
         cdir = edir;
@@ -1645,7 +1681,7 @@ int getdirparams(const struct vol *vol,
                    (1 << DIRPBIT_FINFO)))) {
 
         ad_init(&ad, vol->v_adouble, vol->v_ad_options);
-        if ( !ad_metadata( upath, ADFLAGS_DIR, &ad) ) {
+        if ( !ad_metadata( upath, ADFLAGS_CREATE|ADFLAGS_DIR, &ad) ) {
             isad = 1;
         }
     }
@@ -2079,7 +2115,7 @@ int setdirparams(struct vol *vol,
     }
     ad_init(&ad, vol->v_adouble, vol->v_ad_options);
 
-    if (ad_open_metadata( upath, vol_noadouble(vol)|ADFLAGS_DIR, O_CREAT, &ad) < 0) {
+    if (ad_open_metadata( upath, ADFLAGS_DIR, O_CREAT, &ad) < 0) {
         /*
          * Check to see what we're trying to set.  If it's anything
          * but ACCESS, UID, or GID, give an error.  If it's any of those
@@ -2430,7 +2466,7 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_
     }
 
     ad_init(&ad, vol->v_adouble, vol->v_ad_options);
-    if (ad_open_metadata( ".", vol_noadouble(vol)|ADFLAGS_DIR, O_CREAT, &ad ) < 0)  {
+    if (ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad ) < 0)  {
         if (vol_noadouble(vol))
             goto createdir_done;
         return( AFPERR_ACCESS );
@@ -2535,6 +2571,7 @@ int renamedir(const struct vol *vol, char *src, char *dst,
         dir->d_u_name = buf;
         strcpy( dir->d_u_name, dst );
     }
+    dir->d_u_name_len = strlen(dir->d_u_name);
 
     if (dir->d_m_name_ucs2)
         free(dir->d_m_name_ucs2);
@@ -2576,6 +2613,7 @@ int deletecurdir(struct vol *vol)
     fdir = curdir;
 
     ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+    /* we never want to create a resource fork here, we are going to delete it */
     if ( ad_metadata( ".", ADFLAGS_DIR, &ad) == 0 ) {
 
         ad_getattr(&ad, &ashort);
@@ -2689,6 +2727,7 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r
         if ((afp_version < 32) || !(obj->options.flags & OPTION_UUID ))
             return AFPERR_PARAM;
         LOG(log_debug, logtype_afpd, "afp_mapid: valid UUID request");
+        uuidtype_t type;
         len = getnamefromuuid( ibuf, &name, &type);
         if (len != 0)       /* its a error code, not len */
             return AFPERR_NOITEM;