X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fcatsearch.c;h=f1f55ef96d7a3ed2cea6823d317f1abcb014d180;hb=b362b6f7b22b6e4e9e74760989f389149677917b;hp=5404118c753d33ac0ba1d096ba9b54ce7c12c29f;hpb=8208cf8bbc5fe3b91f68b67e1a052f82a1d9a89c;p=netatalk.git diff --git a/etc/afpd/catsearch.c b/etc/afpd/catsearch.c index 5404118c..f1f55ef9 100644 --- a/etc/afpd/catsearch.c +++ b/etc/afpd/catsearch.c @@ -29,6 +29,9 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ +#include +#include +#include #include #include #include @@ -47,13 +50,13 @@ #include #include #include +#include #include "desktop.h" #include "directory.h" #include "dircache.h" #include "file.h" #include "volume.h" -#include "globals.h" #include "filedir.h" #include "fork.h" @@ -108,57 +111,50 @@ struct scrit { * */ 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 */ + cnid_t ds_did; /* CNID of this directory */ + int ds_checked; /* Have we checked this directory ? */ }; #define DS_BSIZE 128 static int save_cidx = -1; /* Saved index of currently scanned directory. */ - static struct dsitem *dstack = NULL; /* Directory stack data... */ static int dssize = 0; /* Directory stack (allocated) size... */ static int dsidx = 0; /* First free item index... */ - static struct scrit c1, c2; /* search criteria */ +/* Clears directory stack. */ +static void clearstack(void) +{ + save_cidx = -1; + while (dsidx > 0) { + dsidx--; + } +} + /* Puts new item onto directory stack. */ static int addstack(char *uname, struct dir *dir, int pidx) { struct dsitem *ds; size_t l, u; + struct dsitem *tmpds = NULL; /* check if we have some space on stack... */ if (dsidx >= dssize) { dssize += DS_BSIZE; - dstack = realloc(dstack, dssize * sizeof(struct dsitem)); - if (dstack == NULL) + tmpds = realloc(dstack, dssize * sizeof(struct dsitem)); + if (tmpds == NULL) { + clearstack(); + free(dstack); return -1; + } + dstack = tmpds; } /* 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) { - l = dstack[pidx].path_len; - u = strlen(uname) +1; - if (!(ds->path = malloc(l + u + 1) )) - return -1; - 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->ds_did = dir->d_did; + ds->ds_checked = 0; return 0; } @@ -173,27 +169,15 @@ static int reducestack(void) } while (dsidx > 0) { - if (dstack[dsidx-1].checked) { + if (dstack[dsidx-1].ds_checked) { dsidx--; - dstack[dsidx].dir->d_flags &= ~DIRF_CACHELOCK; - free(dstack[dsidx].path); +// free(dstack[dsidx].path); } else return dsidx - 1; } return -1; } -/* Clears directory stack. */ -static void clearstack(void) -{ - save_cidx = -1; - while (dsidx > 0) { - dsidx--; - dstack[dsidx].dir->d_flags &= ~DIRF_CACHELOCK; - free(dstack[dsidx].path); - } -} - /* Looks up for an opened adouble structure, opens resource fork of selected file. * FIXME What about noadouble? */ @@ -209,7 +193,7 @@ static struct adouble *adl_lkup(struct vol *vol, struct path *path, struct adoub isdir = S_ISDIR(path->st.st_mode); - if (!isdir && (of = of_findname(path))) { + if (!isdir && (of = of_findname(vol, path))) { adp = of->of_ad; } else { ad_init(&ad, vol->v_adouble, vol->v_ad_options); @@ -506,6 +490,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 *currentdir; /* struct dir of current directory */ int cidx, r; struct dirent *entry; int result = AFP_OK; @@ -517,7 +502,8 @@ static int catsearch(struct vol *vol, int num_rounds = NUM_ROUNDS; int cwd = -1; int error; - + int unlen; + if (*pos != 0 && *pos != cur_pos) { result = AFPERR_CATCHNG; goto catsearch_end; @@ -551,18 +537,24 @@ static int catsearch(struct vol *vol, start_time = time(NULL); while ((cidx = reducestack()) != -1) { - error = lchdir(dstack[cidx].path); + if ((currentdir = dirlookup(vol, dstack[cidx].ds_did)) == NULL) { + result = AFPERR_MISC; + goto catsearch_end; + } + LOG(log_debug, logtype_afpd, "catsearch: current struct dir: \"%s\"", cfrombstr(currentdir->d_fullpath)); + + error = movecwd(vol, currentdir); if (!error && dirpos == NULL) dirpos = opendir("."); if (dirpos == NULL) - dirpos = opendir(dstack[cidx].path); + dirpos = opendir(bdata(currentdir->d_fullpath)); if (error || dirpos == NULL) { switch (errno) { case EACCES: - dstack[cidx].checked = 1; + dstack[cidx].ds_checked = 1; continue; case EMFILE: case ENFILE: @@ -576,16 +568,20 @@ static int catsearch(struct vol *vol, } /* switch (errno) */ goto catsearch_end; } + - while ((entry=readdir(dirpos)) != NULL) { + while ((entry = readdir(dirpos)) != NULL) { (*pos)++; if (!check_dirent(vol, entry->d_name)) continue; + LOG(log_debug, logtype_afpd, "catsearch(\"%s\"): dirent: \"%s\"", + cfrombstr(currentdir->d_fullpath), entry->d_name); + memset(&path, 0, sizeof(path)); path.u_name = entry->d_name; - if (of_stat(&path) != 0) { + if (of_stat(vol, &path) != 0) { switch (errno) { case EACCES: case ELOOP: @@ -600,16 +596,23 @@ static int catsearch(struct vol *vol, goto catsearch_end; } } - if (S_ISDIR(path.st.st_mode)) { + switch (S_IFMT & path.st.st_mode) { + case S_IFDIR: /* here we can short cut ie if in the same loop the parent dir wasn't in the cache 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); + unlen = strlen(path.u_name); + path.d_dir = dircache_search_by_name(vol, + currentdir, + 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, + currentdir, + &path, + unlen)) == NULL) { result = AFPERR_MISC; goto catsearch_end; } @@ -620,11 +623,14 @@ static int catsearch(struct vol *vol, result = AFPERR_MISC; goto catsearch_end; } + break; + case S_IFREG: + path.d_dir = currentdir; + break; + default: + continue; } - 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 */ @@ -654,7 +660,7 @@ static int catsearch(struct vol *vol, } /* while ((entry=readdir(dirpos)) != NULL) */ closedir(dirpos); dirpos = NULL; - dstack[cidx].checked = 1; + dstack[cidx].ds_checked = 1; } /* while (current_idx = reducestack()) != -1) */ /* We have finished traversing our tree. Return EOF here. */ @@ -768,7 +774,7 @@ static int catsearch_db(struct vol *vol, path.u_name = name; path.m_name = utompath(vol, name, cnid, utf8_encoding()); - if (of_stat(&path) != 0) { + if (of_stat(vol, &path) != 0) { switch (errno) { case EACCES: case ELOOP: @@ -1032,6 +1038,7 @@ static int catsearch_afp(AFPObj *obj _U_, char *ibuf, size_t ibuflen, /* Call search */ *rbuflen = 24; if ((c1.rbitmap & (1 << FILPBIT_PDINFO)) + && !(c1.rbitmap & (1<v_cnidscheme, "dbd") == 0) && (vol->v_flags & AFPVOL_SEARCHDB)) /* we've got a name and it's a dbd volume, so search CNID database */