]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/catsearch.c
Merge from branch-2-1
[netatalk.git] / etc / afpd / catsearch.c
index 24094c8dce784ae4d47a83decf2e44eba8d355e1..70c93f15207a1ff7d48e2fdeb93fd91ba8a89947 100644 (file)
 #ifdef CNID_DB
 #include <atalk/cnid.h>
 #endif /* CNID_DB */
+
+#include <atalk/util.h>
+#include <atalk/bstradd.h>
+
 #include "desktop.h"
 #include "directory.h"
 #include "dircache.h"
@@ -118,8 +122,6 @@ struct dsitem {
  
 
 #define DS_BSIZE 128
-static u_int32_t cur_pos = 0;    /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */
-static DIR *dirpos = NULL; /* UNIX structure describing currently opened directory. */
 static int save_cidx = -1; /* Saved index of currently scanned directory. */
 
 static struct dsitem *dstack = NULL; /* Directory stack data... */
@@ -145,6 +147,7 @@ static int addstack(char *uname, struct dir *dir, int pidx)
        /* Put new element. Allocate and copy lname and path. */
        ds = dstack + dsidx++;
        ds->dir = dir;
+    dir->d_flags |= DIRF_CACHELOCK;
        ds->pidx = pidx;
        ds->checked = 0;
        if (pidx >= 0) {
@@ -177,6 +180,7 @@ static int reducestack(void)
        while (dsidx > 0) {
                if (dstack[dsidx-1].checked) {
                        dsidx--;
+            dstack[dsidx].dir->d_flags &= ~DIRF_CACHELOCK;
                        free(dstack[dsidx].path);
                } else
                        return dsidx - 1;
@@ -190,6 +194,7 @@ static void clearstack(void)
        save_cidx = -1;
        while (dsidx > 0) {
                dsidx--;
+        dstack[dsidx].dir->d_flags &= ~DIRF_CACHELOCK;
                free(dstack[dsidx].path);
        }
 } 
@@ -238,13 +243,13 @@ static struct finderinfo *unpack_buffer(struct finderinfo *finfo, char *buffer)
 
 /* -------------------- */
 static struct finderinfo *
-unpack_finderinfo(struct vol *vol, struct path *path, struct adouble **adp, struct finderinfo *finfo)
+unpack_finderinfo(struct vol *vol, struct path *path, struct adouble **adp, struct finderinfo *finfo, int islnk)
 {
        packed_finder  buf;
        void           *ptr;
        
     *adp = adl_lkup(vol, path, *adp);
-       ptr = get_finderinfo(vol, path->u_name, *adp, &buf);
+       ptr = get_finderinfo(vol, path->u_name, *adp, &buf,islnk);
        return unpack_buffer(finfo, ptr);
 }
 
@@ -266,6 +271,8 @@ static int crit_check(struct vol *vol, struct path *path) {
        u_int32_t ac_date, ab_date;
        static char convbuf[514]; /* for convert_charset dest_len parameter +2 */
        size_t len;
+    int islnk;
+    islnk=S_ISLNK(path->st.st_mode);
 
        if (S_ISDIR(path->st.st_mode)) {
                if (!c1.dbitmap)
@@ -380,7 +387,7 @@ static int crit_check(struct vol *vol, struct path *path) {
 
         /* Check file type ID */
        if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.f_type != 0) {
-           finfo = unpack_finderinfo(vol, path, &adp, &finderinfo);
+           finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                if (finfo->f_type != c1.finfo.f_type)
                        goto crit_check_ret;
        }
@@ -388,7 +395,7 @@ static int crit_check(struct vol *vol, struct path *path) {
        /* Check creator ID */
        if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.creator != 0) {
                if (!finfo) {
-                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo);
+                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                }
                if (finfo->creator != c1.finfo.creator)
                        goto crit_check_ret;
@@ -397,7 +404,7 @@ static int crit_check(struct vol *vol, struct path *path) {
        /* Check finder info attributes */
        if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.attrs != 0) {
                if (!finfo) {
-                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo);
+                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                }
 
                if ((finfo->attrs & c2.finfo.attrs) != c1.finfo.attrs)
@@ -407,7 +414,7 @@ static int crit_check(struct vol *vol, struct path *path) {
        /* Check label */
        if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.label != 0) {
                if (!finfo) {
-                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo);
+                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                }
                if ((finfo->label & c2.finfo.label) != c1.finfo.label)
                        goto crit_check_ret;
@@ -491,6 +498,8 @@ static int rslt_add ( struct vol *vol, struct path *path, char **buf, int ext)
 static int catsearch(struct vol *vol, struct dir *dir,  
                     int rmatches, u_int32_t *pos, char *rbuf, u_int32_t *nrecs, int *rsize, int ext)
 {
+    static u_int32_t cur_pos;    /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */
+    static DIR *dirpos;                 /* UNIX structure describing currently opened directory. */
        int cidx, r;
        struct dirent *entry;
        int result = AFP_OK;
@@ -500,8 +509,8 @@ static int catsearch(struct vol *vol, struct dir *dir,
        char *rrbuf = rbuf;
     time_t start_time;
     int num_rounds = NUM_ROUNDS;
-    int cached;
     int cwd = -1;
+    int error;
         
        if (*pos != 0 && *pos != cur_pos) {
                result = AFPERR_CATCHNG;
@@ -510,8 +519,6 @@ static int catsearch(struct vol *vol, struct dir *dir,
 
        /* FIXME: Category "offspring count ! */
 
-       /* So we are beginning... */
-    start_time = time(NULL);
 
        /* We need to initialize all mandatory structures/variables and change working directory appropriate... */
        if (*pos == 0) {
@@ -534,14 +541,19 @@ static int catsearch(struct vol *vol, struct dir *dir,
         goto catsearch_end;
     }
        
+       /* So we are beginning... */
+    start_time = time(NULL);
+
        while ((cidx = reducestack()) != -1) {
-               cached = 1;
-               if (dirpos == NULL) {
+               error = lchdir(dstack[cidx].path);
+
+               if (!error && dirpos == NULL)
+                       dirpos = opendir(".");
+
+               if (dirpos == NULL)
                        dirpos = opendir(dstack[cidx].path);
-// FIXME dircache rewrite
-//                     cached = (dstack[cidx].dir->d_child != NULL);
-               }
-               if (dirpos == NULL) {
+
+               if (error || dirpos == NULL) {
                        switch (errno) {
                        case EACCES:
                                dstack[cidx].checked = 1;
@@ -558,10 +570,7 @@ static int catsearch(struct vol *vol, struct dir *dir,
                        } /* switch (errno) */
                        goto catsearch_end;
                }
-               /* FIXME error in chdir, what do we do? */
-               chdir(dstack[cidx].path);
                
-
                while ((entry=readdir(dirpos)) != NULL) {
                        (*pos)++;
 
@@ -591,18 +600,15 @@ static int catsearch(struct vol *vol, struct dir *dir,
                                   ALL dirsearch_byname will fail.
                                */
                 int unlen = strlen(path.u_name);
-                               if (cached)
-                       path.d_dir = dircache_search_by_name(vol, dstack[cidx].dir->d_did, path.u_name, unlen);
-               else
-                       path.d_dir = NULL;
-               if (!path.d_dir) {
+                path.d_dir = dircache_search_by_name(vol, dstack[cidx].dir, path.u_name, unlen, path.st.st_ctime);
+               if (path.d_dir == NULL) {
                        /* path.m_name is set by adddir */
                    if (NULL == (path.d_dir = dir_add( vol, dstack[cidx].dir, &path, unlen) ) ) {
                                                result = AFPERR_MISC;
                                                goto catsearch_end;
                                        }
                 }
-                path.m_name = (char *)path.d_dir->d_m_name->data;
+                path.m_name = cfrombstr(path.d_dir->d_m_name);
                        
                                if (addstack(path.u_name, path.d_dir, cidx) == -1) {
                                        result = AFPERR_MISC;