X-Git-Url: https://arthur.barton.de/gitweb/?a=blobdiff_plain;f=etc%2Fafpd%2Fcatsearch.c;h=46192e35465bf9de01e3030fac1c045893ef37b8;hb=2bf71d3ccf20c072bc67a9d075b6ac8b0798021e;hp=490ddb9145f737d1f05df7c13c3b1efe9f37caf7;hpb=232d9560a0841237dc4efceb1e203a162c2ed693;p=netatalk.git diff --git a/etc/afpd/catsearch.c b/etc/afpd/catsearch.c index 490ddb91..46192e35 100644 --- a/etc/afpd/catsearch.c +++ b/etc/afpd/catsearch.c @@ -1,4 +1,5 @@ /* + * Netatalk 2002 (c) * Copyright (C) 1990, 1993 Regents of The University of Michigan * All Rights Reserved. See COPYRIGHT */ @@ -25,10 +26,10 @@ #include #include -#include #include -#include -#include +#include +#include +#include #if STDC_HEADERS #include @@ -39,17 +40,15 @@ #endif /* ! HAVE_MEMCPY */ #endif -#include -#include #include #include -#include #include #include +#include #ifdef CNID_DB #include -#endif /* DID_MTAB */ +#endif /* CNID_DB */ #include "desktop.h" #include "directory.h" #include "file.h" @@ -58,20 +57,17 @@ #include "filedir.h" #include "fork.h" -#ifdef DID_MTAB -#include "parse-mtab.h" -#endif /* DID_MTAB */ - -#ifdef WITH_CATSEARCH struct finderinfo { u_int32_t f_type; u_int32_t creator; - u_int8_t attrs; /* File attributes (8 bits)*/ - u_int8_t label; /* Label (8 bits)*/ + u_int16_t attrs; /* File attributes (high 8 bits)*/ + u_int16_t label; /* Label (low 8 bits )*/ char reserved[22]; /* Unknown (at least for now...) */ }; +typedef char packed_finder[ADEDLEN_FINDERI]; + /* Known attributes: * 0x04 - has a custom icon * 0x20 - name/icon is locked @@ -97,9 +93,10 @@ struct scrit { time_t mdate; /* Last modification date */ time_t bdate; /* Last backup date */ u_int32_t pdid; /* Parent DID */ - u_int16_t offcnt; /* Offspring count */ + u_int16_t offcnt; /* Offspring count */ struct finderinfo finfo; /* Finder info */ - char lname[32]; /* Long name */ + char lname[64]; /* Long name */ + char utf8name[514]; /* UTF8 or UCS2 name */ /* for convert_charset dest_len parameter +2 */ }; /* @@ -111,16 +108,16 @@ struct scrit { * */ struct dsitem { - char *lname; /* Long name */ struct dir *dir; /* Structure describing this directory */ int pidx; /* Parent's dsitem structure index. */ int checked; /* Have we checked this directory ? */ - char *path; /* UNIX path to this directory */ + int path_len; + char *path; /* absolute UNIX path to this directory */ }; #define DS_BSIZE 128 -static int cur_pos = 0; /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */ +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. */ @@ -131,9 +128,10 @@ static int dsidx = 0; /* First free item index... */ static struct scrit c1, c2; /* search criteria */ /* Puts new item onto directory stack. */ -static int addstack(char *lname, struct dir *dir, int pidx) +static int addstack(char *uname, struct dir *dir, int pidx) { struct dsitem *ds; + size_t l, u; /* check if we have some space on stack... */ if (dsidx >= dssize) { @@ -145,23 +143,28 @@ static int addstack(char *lname, struct dir *dir, int pidx) /* Put new element. Allocate and copy lname and path. */ ds = dstack + dsidx++; - ds->lname = strdup(lname); ds->dir = dir; ds->pidx = pidx; + ds->checked = 0; if (pidx >= 0) { - ds->path = malloc(strlen(dstack[pidx].path) + strlen(ds->lname) + 2); - strcpy(ds->path, dstack[pidx].path); - strcat(ds->path, "/"); - strcat(ds->path, ds->lname); + 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->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) { @@ -173,90 +176,78 @@ static int reducestack() while (dsidx > 0) { if (dstack[dsidx-1].checked) { dsidx--; - free(dstack[dsidx].lname); free(dstack[dsidx].path); - /* Check if we need to free (or release) dir structures */ } else return dsidx - 1; - } // while + } return -1; -} /* reducestack() */ +} /* Clears directory stack. */ -static void clearstack() +static void clearstack(void) { save_cidx = -1; while (dsidx > 0) { dsidx--; - free(dstack[dsidx].lname); free(dstack[dsidx].path); - /* Check if we need to free (or release) dir structures */ } -} /* clearstack() */ - -/* Fills in dir field of dstack[cidx]. Must fill parent dirs' fields if needed... */ -static int resolve_dir(struct vol *vol, int cidx) -{ - struct dir *dir, *curdir; - struct stat statbuf; - - if (dstack[cidx].dir != NULL) - return 1; - - if (dstack[cidx].pidx < 0) - return 0; - - if (dstack[dstack[cidx].pidx].dir == NULL && resolve_dir(vol, dstack[cidx].pidx) == 0) - return 0; - - curdir = dstack[dstack[cidx].pidx].dir; - dir = curdir->d_child; - while (dir) { - if (strcmp(dir->d_name, dstack[cidx].lname) == 0) - break; - dir = (dir == curdir->d_child->d_prev) ? NULL : dir->d_next; - } /* while */ - - if (!dir) - if (stat(dstack[cidx].path, &statbuf)==-1) { - syslog(LOG_DEBUG, "resolve_dir: stat %s: %s", dstack[cidx].path, strerror(errno)); - return 0; - } - - if (!dir && ((dir = adddir(vol, curdir, dstack[cidx].lname, strlen(dstack[cidx].lname), - dstack[cidx].path, strlen(dstack[cidx].path), &statbuf)) == NULL)) - return 0; - dstack[cidx].dir = dir; +} - return 1; -} /* resolve_dir */ - -/* Looks up for an opened adouble structure, opens resource fork of selected file. */ -static struct adouble *adl_lkup(struct vol *vol, char *upath, int cidx) +/* Looks up for an opened adouble structure, opens resource fork of selected file. + * FIXME What about noadouble? +*/ +static struct adouble *adl_lkup(struct vol *vol, struct path *path, struct adouble *adp) { static struct adouble ad; - struct adouble *adp; - char *mpath = utompath(vol, upath); + struct ofork *of; - -/* - //if (dstack[cidx].dir == NULL && !resolve_dir(vol, cidx)) - // return NULL; - - //if ((of = of_findname(vol, dstack[cidx].dir, mpath))) { - // adp = of->of_ad; - //} else { - */ - memset(&ad, 0, sizeof(ad)); + int isdir; + + if (adp) + return adp; + + isdir = S_ISDIR(path->st.st_mode); + + if (!isdir && (of = of_findname(path))) { + adp = of->of_ad; + } else { + ad_init(&ad, vol->v_adouble, vol->v_ad_options); adp = &ad; - /* } */ + } - if ( ad_open( upath, ADFLAGS_HF, O_RDONLY, 0, adp) < 0 ) { - return NULL; - } + if ( ad_metadata( path->u_name, ((isdir) ? ADFLAGS_DIR : 0), adp) < 0 ) { + adp = NULL; /* FIXME without resource fork adl_lkup will be call again */ + } + return adp; } +/* -------------------- */ +static struct finderinfo *unpack_buffer(struct finderinfo *finfo, char *buffer) +{ + memcpy(&finfo->f_type, buffer +FINDERINFO_FRTYPEOFF, sizeof(finfo->f_type)); + memcpy(&finfo->creator, buffer +FINDERINFO_FRCREATOFF, sizeof(finfo->creator)); + memcpy(&finfo->attrs, buffer +FINDERINFO_FRFLAGOFF, sizeof(finfo->attrs)); + memcpy(&finfo->label, buffer +FINDERINFO_FRFLAGOFF, sizeof(finfo->label)); + finfo->attrs &= 0xff00; /* high 8 bits */ + finfo->label &= 0xff; /* low 8 bits */ + + return finfo; +} + +/* -------------------- */ +static struct finderinfo * +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,islnk); + return unpack_buffer(finfo, ptr); +} + +/* -------------------- */ #define CATPBIT_PARTIAL 31 /* Criteria checker. This function returns a 2-bit value. */ /* bit 0 means if checked file meets given criteria. */ @@ -265,34 +256,81 @@ static struct adouble *adl_lkup(struct vol *vol, char *upath, int cidx) * fname - our fname (translated to UNIX) * cidx - index in directory stack */ -static int crit_check(struct vol *vol, char *uname, char *fname, int cidx) { - int r = 0; - struct stat sbuf; - u_int16_t attr; - struct finderinfo *finfo = NULL; +static int crit_check(struct vol *vol, struct path *path) { + int result = 0; + u_int16_t attr, flags = CONV_PRECOMPOSE; + struct finderinfo *finfo = NULL, finderinfo; struct adouble *adp = NULL; time_t c_date, b_date; + 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) + return 0; + } + else { + if (!c1.fbitmap) + return 0; - if (stat(uname, &sbuf) < 0) - return 0; - - if (S_ISDIR(sbuf.st_mode)) - r = 2; - + /* compute the Mac name + * first try without id (it's slow to find it) + * 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()) )) { + /*retry with the right id */ + + cnid_t id; + + adp = adl_lkup(vol, path, adp); + id = get_id(vol, adp, &path->st, path->d_dir->d_did, path->u_name, strlen(path->u_name)); + if (!id) { + /* FIXME */ + return 0; + } + /* save the id for getfilparm */ + path->id = id; + if (!(path->m_name = utompath(vol, path->u_name, id , utf8_encoding()))) { + return 0; + } + } + } + /* Kind of optimization: * -- first check things we've already have - filename * -- last check things we get from ad_open() + * FIXME strmcp strstr (icase) */ /* Check for filename */ - if (c1.rbitmap & (1<v_maccharset, CH_UCS2, path->m_name, -1, convbuf, 512)) ) + goto crit_check_ret; + + if ((c1.rbitmap & (1<m_name, strlen(path->m_name), convbuf, 512, &flags))) { + goto crit_check_ret; + } + if (c1.rbitmap & (1< 0x7fffffff) c2.bdate = 0x7fffffff; - /* Check for modification date FIXME: should we look at adouble structure ? */ - if ((c1.rbitmap & (1< c2.mdate) + /* Check for modification date */ + if ((c1.rbitmap & (1<st.st_mtime < c1.mdate || path->st.st_mtime > c2.mdate) goto crit_check_ret; - + } + /* Check for creation date... */ - if (c1.rbitmap & (1<= 0) - c_date = AD_DATE_TO_UNIX(c_date); - else c_date = sbuf.st_mtime; - } else c_date = sbuf.st_mtime; + if ((c1.rbitmap & (1<st.st_mtime; + adp = adl_lkup(vol, path, adp); + if (adp && ad_getdate(adp, AD_DATE_CREATE, &ac_date) >= 0) + c_date = AD_DATE_TO_UNIX(ac_date); + if (c_date < c1.cdate || c_date > c2.cdate) goto crit_check_ret; } /* Check for backup date... */ - if (c1.rbitmap & (1<= 0) - b_date = AD_DATE_TO_UNIX(b_date); - else b_date = sbuf.st_mtime; - } else b_date = sbuf.st_mtime; + if ((c1.rbitmap & (1<st.st_mtime; + adp = adl_lkup(vol, path, adp); + if (adp && ad_getdate(adp, AD_DATE_BACKUP, &ab_date) >= 0) + b_date = AD_DATE_TO_UNIX(ab_date); + if (b_date < c1.bdate || b_date > c2.bdate) goto crit_check_ret; } /* Check attributes */ - if ((c1.rbitmap & (1<f_type != c1.finfo.f_type) - goto crit_check_ret; - } else goto crit_check_ret; - - /* Check creator ID */ - if ((c1.rbitmap & (1<creator != c1.finfo.creator) - goto crit_check_ret; - } else goto crit_check_ret; + if ((c1.rbitmap & (1<f_type != c1.finfo.f_type) + goto crit_check_ret; + } + /* Check creator ID */ + if ((c1.rbitmap & (1<creator != c1.finfo.creator) + goto crit_check_ret; + } + /* Check finder info attributes */ - if ((c1.rbitmap & (1<attrs & c2.finfo.attrs) != c1.finfo.attrs) - goto crit_check_ret; - } else goto crit_check_ret; + if ((c1.rbitmap & (1<label & c2.finfo.label) != c1.finfo.label) - goto crit_check_ret; - } else goto crit_check_ret; + if ((finfo->attrs & c2.finfo.attrs) != c1.finfo.attrs) + goto crit_check_ret; + } + /* Check label */ + if ((c1.rbitmap & (1<label & c2.finfo.label) != c1.finfo.label) + goto crit_check_ret; + } /* FIXME: Attributes check ! */ /* All criteria are met. */ - r |= 1; + result |= 1; crit_check_ret: if (adp != NULL) - ad_close(adp, ADFLAGS_HF); - return r; + ad_close_metadata(adp); + return result; } - -/* Adds an item to resultset. */ -static int rslt_add(struct vol *vol, struct stat *statbuf, char *fname, short cidx, int isdir, char **rbuf) +/* ------------------------------ */ +static int rslt_add ( struct vol *vol, struct path *path, char **buf, int ext) { - char *p = *rbuf; - int l = fname != NULL ? strlen(fname) : 0; - u_int32_t did; - char p0; - - p0 = p[0] = cidx != -1 ? l + 7 : l + 5; - if (p0 & 1) p[0]++; - p[1] = isdir ? 128 : 0; - p += 2; - if (cidx != -1) { - if (dstack[cidx].dir == NULL && resolve_dir(vol, cidx) == 0) - return 0; - did = dstack[cidx].dir->d_did; - memcpy(p, &did, sizeof(did)); - p += sizeof(did); + + char *p = *buf; + int ret; + size_t tbuf =0; + u_int16_t resultsize; + int isdir = S_ISDIR(path->st.st_mode); + + /* Skip resultsize */ + if (ext) { + p += sizeof(resultsize); } + else { + p++; + } + *p++ = isdir ? FILDIRBIT_ISDIR : FILDIRBIT_ISFILE; /* IsDir ? */ - /* Fill offset of returned file name */ - if (fname != NULL) { - *p++ = 0; - *p++ = (int)(p - *rbuf) + 1; - p[0] = l; - strcpy(p+1, fname); - p += l + 1; + if (ext) { + *p++ = 0; /* Pad */ + } + + if ( isdir ) { + ret = getdirparams(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); } - if (p0 & 1) - *p++ = 0; + if ( ret != AFP_OK ) + return 0; - *rbuf = p; - /* *rbuf[0] = (int)(p-*rbuf); */ - return 1; -} /* rslt_add */ + /* Make sure entry length is even */ + if ((tbuf & 1)) { + *p++ = 0; + tbuf++; + } + if (ext) { + resultsize = htons(tbuf); + memcpy ( *buf, &resultsize, sizeof(resultsize) ); + *buf += tbuf + 4; + } + else { + **buf = tbuf; + *buf += tbuf + 2; + } + + return 1; +} + #define VETO_STR \ "./../.AppleDouble/.AppleDB/Network Trash Folder/TheVolumeSettingsFolder/TheFindByContentFolder/.AppleDesktop/.Parent/" @@ -430,57 +487,60 @@ static int rslt_add(struct vol *vol, struct stat *statbuf, char *fname, short ci * pos - position we've stopped recently * rbuf - output buffer * rbuflen - output buffer length -*/ + */ +#define NUM_ROUNDS 200 static int catsearch(struct vol *vol, struct dir *dir, - int rmatches, int *pos, char *rbuf, u_int32_t *nrecs, int *rsize) + int rmatches, u_int32_t *pos, char *rbuf, u_int32_t *nrecs, int *rsize, int ext) { - int cidx, r, i; - char *fname = NULL; + int cidx, r; struct dirent *entry; - struct stat statbuf; int result = AFP_OK; int ccr; - char *orig_dir = NULL; - int orig_dir_len = 128; - char *path = vol->v_path; + struct path path; + char *vpath = vol->v_path; char *rrbuf = rbuf; - - if (*pos != 0 && *pos != cur_pos) - return AFPERR_CATCHNG; + time_t start_time; + int num_rounds = NUM_ROUNDS; + int cached; + int cwd = -1; + + if (*pos != 0 && *pos != cur_pos) { + result = AFPERR_CATCHNG; + goto catsearch_end; + } /* 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) { clearstack(); if (dirpos != NULL) { closedir(dirpos); dirpos = NULL; - } /* if (dirpos != NULL) */ + } - if (addstack("", dir, -1) == -1) { + if (addstack(vpath, dir, -1) == -1) { result = AFPERR_MISC; goto catsearch_end; } - dstack[0].path = strdup(path); - /* FIXME: Sometimes DID is given by klient ! (correct this one above !) */ + /* 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) { - if (dirpos == NULL) - dirpos = opendir(dstack[cidx].path); + cached = 1; + if (dirpos == NULL) { + dirpos = opendir(dstack[cidx].path); + cached = (dstack[cidx].dir->d_child != NULL); + } if (dirpos == NULL) { switch (errno) { case EACCES: @@ -498,12 +558,19 @@ 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)++; - if (veto_file(VETO_STR, entry->d_name)) - continue; - if (stat(entry->d_name, &statbuf) != 0) { + + if (!check_dirent(vol, entry->d_name)) + continue; + + memset(&path, 0, sizeof(path)); + path.u_name = entry->d_name; + if (of_stat(&path) != 0) { switch (errno) { case EACCES: case ELOOP: @@ -516,22 +583,41 @@ static int catsearch(struct vol *vol, struct dir *dir, default: result = AFPERR_MISC; goto catsearch_end; - } /* switch (errno) */ - } /* if (stat(entry->d_name, &statbuf) != 0) */ - fname = utompath(vol, entry->d_name); - for (i = 0; fname[i] != 0; i++) - fname[i] = tolower(fname[i]); - if (strlen(fname) > MACFILELEN) - continue; - ccr = crit_check(vol, entry->d_name, fname, cidx); - /* bit 0 means that criteria has ben met */ - if (ccr & 1) { - r = rslt_add(vol, &statbuf, - (c1.fbitmap&(1<d_name) : NULL, - (c1.fbitmap&(1<d_m_name; + + if (addstack(path.u_name, path.d_dir, cidx) == -1) { + result = AFPERR_MISC; + goto catsearch_end; + } + } + 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 */ + if ((ccr & 1)) { + r = rslt_add ( vol, &path, &rrbuf, ext); + if (r == 0) { result = AFPERR_MISC; goto catsearch_end; @@ -539,22 +625,22 @@ static int catsearch(struct vol *vol, struct dir *dir, *nrecs += r; /* Number of matches limit */ if (--rmatches == 0) - goto catsearch_pause; /* FIXME: timelimit checks ! */ + goto catsearch_pause; /* Block size limit */ if (rrbuf - rbuf >= 448) goto catsearch_pause; - - } - /* bit 1 means that we have to descend into this directory. */ - if (ccr & 2) { - if (S_ISDIR(statbuf.st_mode)) - if (addstack(entry->d_name, NULL, cidx) == -1) { - result = AFPERR_MISC; - goto catsearch_end; - } /* if (addstack... */ + } + /* MacOS 9 doesn't like servers executing commands longer than few seconds */ + if (--num_rounds <= 0) { + if (start_time != time(NULL)) { + result=AFP_OK; + goto catsearch_pause; + } + num_rounds = NUM_ROUNDS; } } /* while ((entry=readdir(dirpos)) != NULL) */ - closedir(dirpos);dirpos = NULL; + closedir(dirpos); + dirpos = NULL; dstack[cidx].checked = 1; } /* while (current_idx = reducestack()) != -1) */ @@ -568,28 +654,39 @@ 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 afp_catsearch(AFPObj *obj, char *ibuf, int ibuflen, - char *rbuf, int *rbuflen) +/* -------------------------- */ +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; + u_int16_t spec_len; u_int32_t rmatches, reserved; u_int32_t catpos[4]; u_int32_t pdid = 0; - char *lname = NULL; - struct dir *dir; - int ret, rsize, i = 0; + int ret, rsize; u_int32_t nrecs = 0; - static int nrr = 1; - char *spec1, *spec2, *bspec1, *bspec2; + unsigned char *spec1, *spec2, *bspec1, *bspec2; + size_t len; + u_int16_t namelen; + u_int16_t flags; + char tmppath[256]; + + *rbuflen = 0; + + /* min header size */ + if (ibuflen < 32) { + return AFPERR_PARAM; + } memset(&c1, 0, sizeof(c1)); memset(&c2, 0, sizeof(c2)); @@ -598,10 +695,10 @@ int afp_catsearch(AFPObj *obj, char *ibuf, int ibuflen, memcpy(&vid, ibuf, sizeof(vid)); ibuf += sizeof(vid); - *rbuflen = 0; - if ((vol = getvolbyvid(vid)) == NULL) + if ((vol = getvolbyvid(vid)) == NULL) { return AFPERR_PARAM; - + } + memcpy(&rmatches, ibuf, sizeof(rmatches)); rmatches = ntohl(rmatches); ibuf += sizeof(rmatches); @@ -617,7 +714,7 @@ int afp_catsearch(AFPObj *obj, char *ibuf, int ibuflen, ibuf += sizeof(c1.fbitmap); memcpy(&c1.dbitmap, ibuf, sizeof(c1.dbitmap)); - c1.dbitmap = c2.dbitmap = ntohl(c1.dbitmap); + c1.dbitmap = c2.dbitmap = ntohs(c1.dbitmap); ibuf += sizeof(c1.dbitmap); memcpy(&c1.rbitmap, ibuf, sizeof(c1.rbitmap)); @@ -625,25 +722,35 @@ int afp_catsearch(AFPObj *obj, char *ibuf, int ibuflen, ibuf += sizeof(c1.rbitmap); if (! (c1.fbitmap || c1.dbitmap)) { - *rbuflen = 0; return AFPERR_BITMAP; } + if ( ext) { + memcpy(&spec_len, ibuf, sizeof(spec_len)); + spec_len = ntohs(spec_len); + } + else { + /* with catsearch only name and parent id are allowed */ + c1.fbitmap &= (1<v_maccharset, CH_UCS2, tmppath, -1, c1.lname, sizeof(c1.lname)); + if (len == (size_t)(-1)) + return AFPERR_PARAM; + +#if 0 + /* FIXME: do we need it ? It's always null ! */ + memcpy(c2.lname, bspec2 + spec2[1] + 1, (bspec2 + spec2[1])[0]); + c2.lname[(bspec2 + spec2[1])[0]]= 0; +#endif } + /* UTF8 Name */ + if (c1.rbitmap & (1 << FILPBIT_PDINFO)) { + + /* offset */ + memcpy(&namelen, spec1, sizeof(namelen)); + namelen = ntohs (namelen); + + spec1 = bspec1+namelen+4; /* Skip Unicode Hint */ + /* length */ + memcpy(&namelen, spec1, sizeof(namelen)); + namelen = ntohs (namelen); + if (namelen > 255) /* Safeguard */ + namelen = 255; + memcpy (c1.utf8name, spec1+2, namelen); + c1.utf8name[(namelen+1)] =0; + + /* convert charset */ + flags = CONV_PRECOMPOSE; + 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; + } + /* Call search */ *rbuflen = 24; - ret = catsearch(vol, vol->v_dir, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize); + ret = catsearch(vol, vol->v_dir, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext); memcpy(rbuf, catpos, sizeof(catpos)); rbuf += sizeof(catpos); + c1.fbitmap = htons(c1.fbitmap); memcpy(rbuf, &c1.fbitmap, sizeof(c1.fbitmap)); rbuf += sizeof(c1.fbitmap); + c1.dbitmap = htons(c1.dbitmap); memcpy(rbuf, &c1.dbitmap, sizeof(c1.dbitmap)); - rbuf += sizeof(c2.dbitmap); + rbuf += sizeof(c1.dbitmap); + nrecs = htonl(nrecs); memcpy(rbuf, &nrecs, sizeof(nrecs)); rbuf += sizeof(nrecs); *rbuflen += rsize; return ret; -} /* afp_catsearch */ +} /* catsearch_afp */ + +/* -------------------------- */ +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, size_t ibuflen, + char *rbuf, size_t *rbuflen) +{ + return catsearch_afp( obj, ibuf, ibuflen, rbuf, rbuflen, 1); +} /* FIXME: we need a clean separation between afp stubs and 'real' implementation */ /* (so, all buffer packing/unpacking should be done in stub, everything else should be done in other functions) */ - -#endif -/* WITH_CATSEARCH */