#include "config.h"
#endif /* HAVE_CONFIG_H */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <atalk/bstradd.h>
#include <atalk/unicode.h>
#include <atalk/globals.h>
+#include <atalk/netatalk_conf.h>
#include "desktop.h"
#include "directory.h"
*
*/
struct dsitem {
-// 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;
- 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->did = dir->d_did;
- 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;
}
}
while (dsidx > 0) {
- if (dstack[dsidx-1].checked) {
+ if (dstack[dsidx-1].ds_checked) {
dsidx--;
- 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--;
- free(dstack[dsidx].path);
- }
-}
-
/* Looks up for an opened adouble structure, opens resource fork of selected file.
* FIXME What about noadouble?
*/
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);
+ ad_init(&ad, vol);
adp = &ad;
}
* An other option would be to call get_id in utompath but
* we need to pass parent dir
*/
- if (!(path->m_name = utompath(vol, path->u_name, 0 , utf8_encoding()) )) {
+ if (!(path->m_name = utompath(vol, path->u_name, 0 , utf8_encoding(vol->v_obj)) )) {
/*retry with the right id */
cnid_t id;
}
/* save the id for getfilparm */
path->id = id;
- if (!(path->m_name = utompath(vol, path->u_name, id , utf8_encoding()))) {
+ if (!(path->m_name = utompath(vol, path->u_name, id , utf8_encoding(vol->v_obj)))) {
return 0;
}
}
}
/* ------------------------------ */
-static int rslt_add ( struct vol *vol, struct path *path, char **buf, int ext)
+static int rslt_add (const AFPObj *obj, struct vol *vol, struct path *path, char **buf, int ext)
{
char *p = *buf;
}
if ( isdir ) {
- ret = getdirparams(vol, c1.dbitmap, path, path->d_dir, p , &tbuf );
+ ret = getdirparams(obj, vol, c1.dbitmap, path, path->d_dir, p , &tbuf );
}
else {
/* FIXME slow if we need the file ID, we already know it, done ? */
- ret = getfilparams ( vol, c1.fbitmap, path, path->d_dir, p, &tbuf);
+ ret = getfilparams (obj, vol, c1.fbitmap, path, path->d_dir, p, &tbuf, 0);
}
if ( ret != AFP_OK )
* @param ext (r) extended search flag
*/
#define NUM_ROUNDS 200
-static int catsearch(struct vol *vol,
+static int catsearch(const AFPObj *obj,
+ struct vol *vol,
struct dir *dir,
int rmatches,
uint32_t *pos,
int num_rounds = NUM_ROUNDS;
int cwd = -1;
int error;
-
+ int unlen;
+
if (*pos != 0 && *pos != cur_pos) {
result = AFPERR_CATCHNG;
goto catsearch_end;
start_time = time(NULL);
while ((cidx = reducestack()) != -1) {
- LOG(log_debug, logtype_afpd, "catsearch: dir: \"%s\"", 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 = lchdir(dstack[cidx].path);
+ error = movecwd(vol, currentdir);
if (!error && dirpos == NULL)
dirpos = opendir(".");
if (dirpos == NULL)
- dirpos = opendir(dstack[cidx].path);
+ dirpos = opendir(cfrombstr(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:
goto catsearch_end;
}
- if ((currentdir = dirlookup_bypath(vol, dstack[cidx].path)) == NULL) {
- result = AFPERR_MISC;
- goto catsearch_end;
- }
- LOG(log_debug, logtype_afpd, "catsearch: current struct dir: \"%s\"", cfrombstr(currentdir->d_fullpath));
while ((entry = readdir(dirpos)) != NULL) {
(*pos)++;
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:
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);
+ unlen = strlen(path.u_name);
path.d_dir = dircache_search_by_name(vol,
currentdir,
path.u_name,
result = AFPERR_MISC;
goto catsearch_end;
}
- } else {
+ break;
+ case S_IFREG:
path.d_dir = currentdir;
+ break;
+ default:
+ continue;
}
ccr = crit_check(vol, &path);
/* bit 0 means that criteria has been met */
if ((ccr & 1)) {
- r = rslt_add ( vol, &path, &rrbuf, ext);
+ r = rslt_add (obj, vol, &path, &rrbuf, ext);
if (r == 0) {
result = AFPERR_MISC;
} /* 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. */
* @param rsize (w) length of data written to output buffer
* @param ext (r) extended search flag
*/
-static int catsearch_db(struct vol *vol,
+static int catsearch_db(const AFPObj *obj,
+ struct vol *vol,
struct dir *dir,
const char *uname,
int rmatches,
LOG(log_debug, logtype_afpd, "catsearch_db: %s", buffer);
- if ((num_matches = cnid_find(vol->v_cdb,
- buffer,
- strlen(uname),
- resbuf,
- sizeof(resbuf))) == -1) {
+ AFP_CNID_START("cnid_find");
+ num_matches = cnid_find(vol->v_cdb,
+ buffer,
+ strlen(uname),
+ resbuf,
+ sizeof(resbuf));
+ AFP_CNID_DONE();
+ if (num_matches == -1) {
result = AFPERR_MISC;
goto catsearch_end;
}
memcpy(&cnid, resbuf + cur_pos * sizeof(cnid_t), sizeof(cnid_t));
did = cnid;
- if ((name = cnid_resolve(vol->v_cdb, &did, resolvebuf, 12 + MAXPATHLEN + 1)) == NULL)
+ AFP_CNID_START("cnid_resolve");
+ name = cnid_resolve(vol->v_cdb, &did, resolvebuf, 12 + MAXPATHLEN + 1);
+ AFP_CNID_DONE();
+ if (name == 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)
memset(&path, 0, sizeof(path));
path.u_name = name;
- path.m_name = utompath(vol, name, cnid, utf8_encoding());
+ path.m_name = utompath(vol, name, cnid, utf8_encoding(vol->v_obj));
- if (of_stat(&path) != 0) {
+ if (of_stat(vol, &path) != 0) {
switch (errno) {
case EACCES:
case ELOOP:
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);
+ r = rslt_add(obj, vol, &path, &rrbuf, ext);
if (r == 0) {
result = AFPERR_MISC;
goto catsearch_end;
memcpy (c1.utf8name, spec1+2, namelen);
c1.utf8name[namelen] = 0;
- if ((uname = mtoupath(vol, c1.utf8name, 0, utf8_encoding())) == NULL)
+ if ((uname = mtoupath(vol, c1.utf8name, 0, utf8_encoding(obj))) == NULL)
return AFPERR_PARAM;
/* convert charset */
/* Call search */
*rbuflen = 24;
if ((c1.rbitmap & (1 << FILPBIT_PDINFO))
+ && !(c1.rbitmap & (1<<CATPBIT_PARTIAL))
&& (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, uname, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext);
+ ret = catsearch_db(obj, 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);
+ ret = catsearch(obj, vol, vol->v_root, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext);
memcpy(rbuf, catpos, sizeof(catpos));
rbuf += sizeof(catpos);