]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/catsearch.c
Merge symlink branch
[netatalk.git] / etc / afpd / catsearch.c
index 73dd30a8f0f8ae24e2e955cbd9a015c7d08426c2..46192e35465bf9de01e3030fac1c045893ef37b8 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <dirent.h>
 #include <errno.h>
 #include <ctype.h>
 #include <string.h>
@@ -97,7 +96,7 @@ struct scrit {
     u_int16_t offcnt;           /* Offspring count */
        struct finderinfo finfo;    /* Finder info */
        char lname[64];             /* Long name */ 
-       char utf8name[512];         /* UTF8 name */
+       char utf8name[514];         /* UTF8 or UCS2 name */ /* for convert_charset dest_len parameter +2 */
 };
 
 /*
@@ -112,6 +111,7 @@ struct dsitem {
        struct dir *dir; /* Structure describing this directory */
        int pidx;        /* Parent's dsitem structure index. */
        int checked;     /* Have we checked this directory ? */
+       int path_len;
        char *path;      /* absolute UNIX path to this directory */
 };
  
@@ -131,7 +131,7 @@ static struct scrit c1, c2;          /* search criteria */
 static int addstack(char *uname, struct dir *dir, int pidx)
 {
        struct dsitem *ds;
-       int           l;
+       size_t         l, u;
 
        /* check if we have some space on stack... */
        if (dsidx >= dssize) {
@@ -145,22 +145,26 @@ static int addstack(char *uname, struct dir *dir, int pidx)
        ds = dstack + dsidx++;
        ds->dir = dir;
        ds->pidx = pidx;
+       ds->checked = 0;
        if (pidx >= 0) {
-           l = strlen(dstack[pidx].path);
-           if (!(ds->path = malloc(l + strlen(uname) + 2) ))
+           l = dstack[pidx].path_len;
+           u = strlen(uname) +1;
+           if (!(ds->path = malloc(l + u + 1) ))
                        return -1;
-               strcpy(ds->path, dstack[pidx].path);
-               strcat(ds->path, "/");
-               strcat(ds->path, uname);
+               memcpy(ds->path, dstack[pidx].path, l);
+               ds->path[l] = '/';
+               memcpy(&ds->path[l+1], uname, u);
+               ds->path_len = l +u;
+       }
+       else {
+           ds->path = strdup(uname);
+               ds->path_len = strlen(uname);
        }
-
-       ds->checked = 0;
-
        return 0;
 }
 
 /* Removes checked items from top of directory stack. Returns index of the first unchecked elements or -1. */
-static int reducestack()
+static int reducestack(void)
 {
        int r;
        if (save_cidx != -1) {
@@ -180,7 +184,7 @@ static int reducestack()
 } 
 
 /* Clears directory stack. */
-static void clearstack() 
+static void clearstack(void
 {
        save_cidx = -1;
        while (dsidx > 0) {
@@ -211,7 +215,7 @@ static struct adouble *adl_lkup(struct vol *vol, struct path *path, struct adoub
                adp = &ad;
        } 
 
-    if ( ad_metadata( path->u_name, ((isdir)?ADFLAGS_DIR:0), adp) < 0 ) {
+    if ( ad_metadata( path->u_name, ((isdir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
         adp = NULL; /* FIXME without resource fork adl_lkup will be call again */
     }
     
@@ -233,12 +237,13 @@ static struct finderinfo *unpack_buffer(struct finderinfo *finfo, char *buffer)
 
 /* -------------------- */
 static struct finderinfo *
-unpack_finderinfo(char *upath, 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;
        
-       ptr = get_finderinfo(upath, adp, &buf);
+    *adp = adl_lkup(vol, path, *adp);
+       ptr = get_finderinfo(vol, path->u_name, *adp, &buf,islnk);
        return unpack_buffer(finfo, ptr);
 }
 
@@ -258,8 +263,10 @@ static int crit_check(struct vol *vol, struct path *path) {
        struct adouble *adp = NULL;
        time_t c_date, b_date;
        u_int32_t ac_date, ab_date;
-       static char convbuf[512];
+       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)
@@ -301,9 +308,9 @@ static int crit_check(struct vol *vol, struct path *path) {
 
        /* Check for filename */
        if ((c1.rbitmap & (1<<DIRPBIT_LNAME))) { 
-               if ( (size_t)(-1) == (len = convert_string(vol->v_maccharset, CH_UCS2, path->m_name, strlen(path->m_name), convbuf, 512)) )
+               if ( (size_t)(-1) == (len = convert_string(vol->v_maccharset, CH_UCS2, path->m_name, -1, convbuf, 512)) )
                        goto crit_check_ret;
-               convbuf[len] = 0; 
+
                if ((c1.rbitmap & (1<<CATPBIT_PARTIAL))) {
                        if (strcasestr_w( (ucs2_t*) convbuf, (ucs2_t*) c1.lname) == NULL)
                                goto crit_check_ret;
@@ -316,7 +323,7 @@ static int crit_check(struct vol *vol, struct path *path) {
                if ( (size_t)(-1) == (len = convert_charset( CH_UTF8_MAC, CH_UCS2, CH_UTF8, path->m_name, strlen(path->m_name), convbuf, 512, &flags))) {
                        goto crit_check_ret;
                }
-               convbuf[len] = 0; 
+
                if (c1.rbitmap & (1<<CATPBIT_PARTIAL)) {
                        if (strcasestr_w((ucs2_t *) convbuf, (ucs2_t*)c1.utf8name) == NULL)
                                goto crit_check_ret;
@@ -374,8 +381,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) {
-               adp = adl_lkup(vol, path, adp);
-           finfo = unpack_finderinfo(path->u_name, adp, &finderinfo);
+           finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                if (finfo->f_type != c1.finfo.f_type)
                        goto crit_check_ret;
        }
@@ -383,8 +389,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) {
-               adp = adl_lkup(vol, path, adp);
-                       finfo = unpack_finderinfo(path->u_name, adp, &finderinfo);
+                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                }
                if (finfo->creator != c1.finfo.creator)
                        goto crit_check_ret;
@@ -393,8 +398,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) {
-               adp = adl_lkup(vol, path, adp);
-                       finfo = unpack_finderinfo(path->u_name, adp, &finderinfo);
+                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                }
 
                if ((finfo->attrs & c2.finfo.attrs) != c1.finfo.attrs)
@@ -404,8 +408,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) {
-               adp = adl_lkup(vol, path, adp);
-                       finfo = unpack_finderinfo(path->u_name, adp, &finderinfo);
+                       finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk);
                }
                if ((finfo->label & c2.finfo.label) != c1.finfo.label)
                        goto crit_check_ret;
@@ -416,7 +419,7 @@ static int crit_check(struct vol *vol, struct path *path) {
        result |= 1;
 crit_check_ret:
        if (adp != NULL)
-               ad_close(adp, ADFLAGS_HF);
+               ad_close_metadata(adp);
        return result;
 }  
 
@@ -425,7 +428,8 @@ static int rslt_add ( struct vol *vol, struct path *path, char **buf, int ext)
 {
 
        char            *p = *buf;
-       int             ret, tbuf =0;
+       int             ret;
+       size_t          tbuf =0;
        u_int16_t       resultsize;
        int             isdir = S_ISDIR(path->st.st_mode); 
 
@@ -484,7 +488,7 @@ static int rslt_add ( struct vol *vol, struct path *path, char **buf, int ext)
  * rbuf - output buffer
  * rbuflen - output buffer length
  */
-#define NUM_ROUNDS 100
+#define NUM_ROUNDS 200
 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)
 {
@@ -493,13 +497,12 @@ static int catsearch(struct vol *vol, struct dir *dir,
        int result = AFP_OK;
        int ccr;
     struct path path;
-       char *orig_dir = NULL;
-       int orig_dir_len = 128;
        char *vpath = vol->v_path;
        char *rrbuf = rbuf;
     time_t start_time;
     int num_rounds = NUM_ROUNDS;
     int cached;
+    int cwd = -1;
         
        if (*pos != 0 && *pos != cur_pos) {
                result = AFPERR_CATCHNG;
@@ -519,24 +522,18 @@ static int catsearch(struct vol *vol, struct dir *dir,
                        dirpos = NULL;
                } 
                
-               if (addstack("", dir, -1) == -1) {
+               if (addstack(vpath, dir, -1) == -1) {
                        result = AFPERR_MISC;
                        goto catsearch_end;
                }
-               dstack[0].path = strdup(vpath);
                /* FIXME: Sometimes DID is given by client ! (correct this one above !) */
        }
 
        /* Save current path */
-       orig_dir = (char*)malloc(orig_dir_len);
-       while (getcwd(orig_dir, orig_dir_len-1)==NULL) {
-               if (errno != ERANGE) {
-                       result = AFPERR_MISC;
-                       goto catsearch_end;
-               }
-               orig_dir_len += 128; 
-               orig_dir = realloc(orig_dir, orig_dir_len);
-       } /* while() */
+    if ((cwd = open(".", O_RDONLY)) < 0) {
+        result = AFPERR_MISC;
+        goto catsearch_end;
+    }
        
        while ((cidx = reducestack()) != -1) {
                cached = 1;
@@ -657,16 +654,18 @@ catsearch_pause:
 
 catsearch_end: /* Exiting catsearch: error condition */
        *rsize = rrbuf - rbuf;
-       if (orig_dir != NULL) {
-               chdir(orig_dir);
-               free(orig_dir);
-       }
+    if (cwd != -1) {
+        if ((fchdir(cwd)) != 0) {
+            LOG(log_debug, logtype_afpd, "error chdiring back: %s", strerror(errno));        
+        }
+        close(cwd);
+    }
        return result;
 } /* catsearch() */
 
 /* -------------------------- */
-int catsearch_afp(AFPObj *obj _U_, char *ibuf, int ibuflen,
-                  char *rbuf, int *rbuflen, int ext)
+static int catsearch_afp(AFPObj *obj _U_, char *ibuf, size_t ibuflen,
+                  char *rbuf, size_t *rbuflen, int ext)
 {
     struct vol *vol;
     u_int16_t   vid;
@@ -738,8 +737,8 @@ int catsearch_afp(AFPObj *obj _U_, char *ibuf, int ibuflen,
     }
 
     /* Parse file specifications */
-    spec1 = ibuf;
-    spec2 = ibuf + spec_len + 2;
+    spec1 = (unsigned char*)ibuf;
+    spec2 = (unsigned char*)ibuf + spec_len + 2;
 
     spec1 += 2; 
     spec2 += 2; 
@@ -829,10 +828,9 @@ int catsearch_afp(AFPObj *obj _U_, char *ibuf, int ibuflen,
         /* Get the long filename */    
                memcpy(tmppath, bspec1 + spec1[1] + 1, (bspec1 + spec1[1])[0]);
                tmppath[(bspec1 + spec1[1])[0]]= 0;
-               len = convert_string ( vol->v_maccharset, CH_UCS2, tmppath, strlen(tmppath), c1.lname, 64);
+               len = convert_string ( vol->v_maccharset, CH_UCS2, tmppath, -1, c1.lname, sizeof(c1.lname));
         if (len == (size_t)(-1))
             return AFPERR_PARAM;
-               c1.lname[len] = 0;
 
 #if 0  
                /* FIXME: do we need it ? It's always null ! */
@@ -863,7 +861,6 @@ int catsearch_afp(AFPObj *obj _U_, char *ibuf, int ibuflen,
                len = convert_charset(CH_UTF8_MAC, CH_UCS2, CH_UTF8, c1.utf8name, namelen, c1.utf8name, 512, &flags);
         if (len == (size_t)(-1))
             return AFPERR_PARAM;
-               c1.utf8name[len]=0;
     }
     
     /* Call search */
@@ -889,15 +886,15 @@ int catsearch_afp(AFPObj *obj _U_, char *ibuf, int ibuflen,
 } /* catsearch_afp */
 
 /* -------------------------- */
-int afp_catsearch (AFPObj *obj, char *ibuf, int ibuflen,
-                  char *rbuf, int *rbuflen)
+int afp_catsearch (AFPObj *obj, char *ibuf, size_t ibuflen,
+                  char *rbuf, size_t *rbuflen)
 {
        return catsearch_afp( obj, ibuf, ibuflen, rbuf, rbuflen, 0);
 }
 
 
-int afp_catsearch_ext (AFPObj *obj, char *ibuf, int ibuflen,
-                  char *rbuf, int *rbuflen)
+int afp_catsearch_ext (AFPObj *obj, char *ibuf, size_t ibuflen,
+                  char *rbuf, size_t *rbuflen)
 {
        return catsearch_afp( obj, ibuf, ibuflen, rbuf, rbuflen, 1);
 }