]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/catsearch.c
First working IPC reconnect
[netatalk.git] / etc / afpd / catsearch.c
index e96621e84cefbea461df9d27b971c267cf734673..a488501e6b67e3c101660b844aa218bb460a1da5 100644 (file)
 #include <atalk/cnid_dbd_private.h>
 #include <atalk/util.h>
 #include <atalk/bstradd.h>
+#include <atalk/unicode.h>
+#include <atalk/globals.h>
 
 #include "desktop.h"
 #include "directory.h"
 #include "dircache.h"
 #include "file.h"
 #include "volume.h"
-#include "globals.h"
 #include "filedir.h"
 #include "fork.h"
 
@@ -107,7 +108,8 @@ struct scrit {
  *
  */
 struct dsitem {
-       struct dir *dir; /* Structure describing this directory */
+//     struct dir *dir; /* Structure describing this directory */
+//  cnid_t did;      /* CNID of this directory           */
        int pidx;        /* Parent's dsitem structure index. */
        int checked;     /* Have we checked this directory ? */
        int path_len;
@@ -140,8 +142,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->did = dir->d_did;
        ds->pidx = pidx;
        ds->checked = 0;
        if (pidx >= 0) {
@@ -174,7 +175,6 @@ 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;
@@ -188,7 +188,6 @@ static void clearstack(void)
        save_cidx = -1;
        while (dsidx > 0) {
                dsidx--;
-        dstack[dsidx].dir->d_flags &= ~DIRF_CACHELOCK;
                free(dstack[dsidx].path);
        }
 } 
@@ -505,6 +504,7 @@ static int catsearch(struct vol *vol,
 {
     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. */
+    struct dir *curdir;          /* struct dir of current directory */
        int cidx, r;
        struct dirent *entry;
        int result = AFP_OK;
@@ -575,8 +575,13 @@ static int catsearch(struct vol *vol,
                        } /* switch (errno) */
                        goto catsearch_end;
                }
+
+        if ((curdir = dirlookup_bypath(vol, dstack[cidx].path)) == NULL) {
+            result = AFPERR_MISC;
+            goto catsearch_end;
+        }
                
-               while ((entry=readdir(dirpos)) != NULL) {
+               while ((entry = readdir(dirpos)) != NULL) {
                        (*pos)++;
 
                        if (!check_dirent(vol, entry->d_name))
@@ -605,10 +610,16 @@ static int catsearch(struct vol *vol,
                                   ALL dirsearch_byname will fail.
                                */
                 int unlen = strlen(path.u_name);
-                path.d_dir = dircache_search_by_name(vol, dstack[cidx].dir, path.u_name, unlen, path.st.st_ctime);
+                path.d_dir = dircache_search_by_name(vol,
+                                                     curdir,
+                                                     path.u_name,
+                                                     unlen);
                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) ) ) {
+                   if ((path.d_dir = dir_add(vol,
+                                              curdir,
+                                              &path,
+                                              unlen)) == NULL) {
                                                result = AFPERR_MISC;
                                                goto catsearch_end;
                                        }
@@ -619,11 +630,10 @@ static int catsearch(struct vol *vol,
                                        result = AFPERR_MISC;
                                        goto catsearch_end;
                                } 
+            } else {
+               path.d_dir = curdir;
             }
-            else {
-               /* yes it sucks for directory d_dir is the directory, for file it's the parent directory*/
-               path.d_dir = dstack[cidx].dir;
-            }
+
                        ccr = crit_check(vol, &path);
 
                        /* bit 0 means that criteria has been met */
@@ -682,6 +692,7 @@ catsearch_end: /* Exiting catsearch: error condition */
  *
  * @param vol       (r)  volume we are searching on ...
  * @param dir       (rw) directory we are starting from ...
+ * @param uname     (r)  UNIX name of object to search
  * @param rmatches  (r)  maximum number of matches we can return
  * @param pos       (r)  position we've stopped recently
  * @param rbuf      (w)  output buffer
@@ -689,9 +700,9 @@ catsearch_end: /* Exiting catsearch: error condition */
  * @param rsize     (w)  length of data written to output buffer
  * @param ext       (r)  extended search flag
  */
-#define NUM_ROUNDS 200
 static int catsearch_db(struct vol *vol,
                         struct dir *dir,  
+                        const char *uname,
                         int rmatches,
                         uint32_t *pos,
                         char *rbuf,
@@ -700,11 +711,17 @@ static int catsearch_db(struct vol *vol,
                         int ext)
 {
     static char resbuf[DBD_MAX_SRCH_RSLTS * sizeof(cnid_t)];
-    static uint32_t cur_pos;    /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */
-    int num_matches, ccr ,r;
+    static uint32_t cur_pos;
+    static int num_matches;
+    int ccr ,r;
        int result = AFP_OK;
     struct path path;
        char *rrbuf = rbuf;
+    char buffer[MAXPATHLEN +2];
+    uint16_t flags = CONV_TOLOWER;
+
+    LOG(log_debug, logtype_afpd, "catsearch_db(req pos: %u): {pos: %u, name: %s}",
+        *pos, cur_pos, uname);
         
        if (*pos != 0 && *pos != cur_pos) {
                result = AFPERR_CATCHNG;
@@ -712,9 +729,24 @@ static int catsearch_db(struct vol *vol,
        }
 
     if (cur_pos == 0 || *pos == 0) {
+        if (convert_charset(vol->v_volcharset,
+                            vol->v_volcharset,
+                            vol->v_maccharset,
+                            uname,
+                            strlen(uname),
+                            buffer,
+                            MAXPATHLEN,
+                            &flags) == (size_t)-1) {
+            LOG(log_error, logtype_afpd, "catsearch_db: conversion error");
+            result = AFPERR_MISC;
+            goto catsearch_end;
+        }
+
+        LOG(log_debug, logtype_afpd, "catsearch_db: %s", buffer);
+
         if ((num_matches = cnid_find(vol->v_cdb,
-                                     c1.utf8name,
-                                     strlen(c1.utf8name),
+                                     buffer,
+                                     strlen(uname),
                                      resbuf,
                                      sizeof(resbuf))) == -1) {
             result = AFPERR_MISC;
@@ -732,22 +764,14 @@ static int catsearch_db(struct vol *vol,
         memcpy(&cnid, resbuf + cur_pos * sizeof(cnid_t), sizeof(cnid_t));
         did = cnid;
 
-        /* We need the parent CNID for files and must determine the type (file or dir) */
-        if ((name = cnid_resolve(vol->v_cdb, &did, resolvebuf, 12 + MAXPATHLEN + 1)) == NULL) {
-            result = AFPERR_NFILE;
-                       goto catsearch_end;
-        }
-
-        if ((dir = dirlookup(vol, did)) == NULL) {
-            LOG(log_error, logtype_afpd,"catsearch_db: missing DID: %u", ntohl(did));
-            result = AFPERR_NFILE;
-                       goto catsearch_end;
-        }
-        if (movecwd(vol, dir) < 0 ) {
-            LOG(log_error, logtype_afpd,"catsearch_db: movecwd: %s", dir->d_fullpath);
-            result = AFPERR_NFILE;
-                       goto catsearch_end;
-        }        
+        if ((name = cnid_resolve(vol->v_cdb, &did, resolvebuf, 12 + MAXPATHLEN + 1)) == NULL)
+            goto next;
+        LOG(log_debug, logtype_afpd, "catsearch_db: {pos: %u, name:%s, cnid: %u}",
+            cur_pos, name, ntohl(cnid));
+        if ((dir = dirlookup(vol, did)) == NULL)
+            goto next;
+        if (movecwd(vol, dir) < 0 )
+            goto next;
 
         memset(&path, 0, sizeof(path));
         path.u_name = name;
@@ -757,30 +781,28 @@ static int catsearch_db(struct vol *vol,
             switch (errno) {
             case EACCES:
             case ELOOP:
-            case ENOENT:
                 goto next;
+            case ENOENT:
+                
             default:
                 result = AFPERR_MISC;
                 goto catsearch_end;
             } 
         }
         /* For files path.d_dir is the parent dir, for dirs its the dir itself */
-        if (S_ISDIR(path.st.st_mode)) {
-            if ((dir = dirlookup(vol, cnid)) == NULL) {
-                LOG(log_error, logtype_afpd,"catsearch_db: missing DID: %u", ntohl(cnid));
-                result = AFPERR_NFILE;
-                goto catsearch_end;
-            }
-        }
+        if (S_ISDIR(path.st.st_mode))
+            if ((dir = dirlookup(vol, cnid)) == NULL)
+                goto next;
         path.d_dir = dir;
 
-        LOG(log_error, logtype_afpd,"catsearch_db: dir: %s, cwd: %s, name: %s", 
+        LOG(log_maxdebug, logtype_afpd,"catsearch_db: dir: %s, cwd: %s, name: %s", 
             cfrombstr(dir->d_fullpath), getcwdpath(), path.u_name);
 
-
         /* At last we can check the search criteria */
         ccr = crit_check(vol, &path);
         if ((ccr & 1)) {
+            LOG(log_debug, logtype_afpd,"catsearch_db: match: %s/%s",
+                getcwdpath(), path.u_name);
             /* bit 1 means that criteria has been met */
             r = rslt_add(vol, &path, &rrbuf, ext);
             if (r == 0) {
@@ -809,6 +831,7 @@ catsearch_pause:
 
 catsearch_end: /* Exiting catsearch: error condition */
        *rsize = rrbuf - rbuf;
+    LOG(log_debug, logtype_afpd, "catsearch_db(req pos: %u): {pos: %u}", *pos, cur_pos);
        return result;
 }
 
@@ -828,7 +851,8 @@ static int catsearch_afp(AFPObj *obj _U_, char *ibuf, size_t ibuflen,
     size_t     len;
     u_int16_t  namelen;
     u_int16_t  flags;
-    char       tmppath[256];
+    char           tmppath[256];
+    char        *uname;
 
     *rbuflen = 0;
 
@@ -999,11 +1023,13 @@ static int catsearch_afp(AFPObj *obj _U_, char *ibuf, size_t ibuflen,
                /* length */
                memcpy(&namelen, spec1, sizeof(namelen));
                namelen = ntohs (namelen);
-               if (namelen > 255)  /* Safeguard */
-                       namelen = 255;
+               if (namelen > UTF8FILELEN_EARLY)  /* Safeguard */
+                       namelen = UTF8FILELEN_EARLY;
 
                memcpy (c1.utf8name, spec1+2, namelen);
                c1.utf8name[namelen] = 0;
+        if ((uname = mtoupath(vol, c1.utf8name, 0, utf8_encoding())) == NULL)
+            return AFPERR_PARAM;
 
                /* convert charset */
                flags = CONV_PRECOMPOSE;
@@ -1014,9 +1040,11 @@ static int catsearch_afp(AFPObj *obj _U_, char *ibuf, size_t ibuflen,
     
     /* Call search */
     *rbuflen = 24;
-    if ((c1.rbitmap & (1 << FILPBIT_PDINFO)) && (strcmp(vol->v_cnidscheme, "dbd") == 0))
+    if ((c1.rbitmap & (1 << FILPBIT_PDINFO))
+        && (strcmp(vol->v_cnidscheme, "dbd") == 0)
+        && (vol->v_flags & AFPVOL_SEARCHDB))
         /* we've got a name and it's a dbd volume, so search CNID database */
-        ret = catsearch_db(vol, vol->v_root, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext);
+        ret = catsearch_db(vol, vol->v_root, uname, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext);
     else
         /* perform a slow filesystem tree search */
         ret = catsearch(vol, vol->v_root, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext);