static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_t *buflen) { struct path path; struct stat *st; struct adouble *adp; struct dir *dir; struct vol *vol; /* can only get the length of the opened fork */ if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN))) && (ofork->of_flags & AFPFORK_RSRC)) || ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN))) && (ofork->of_flags & AFPFORK_DATA))) { return( AFPERR_BITMAP ); } if ( ad_reso_fileno( ofork->of_ad ) == -1 ) { /* META ? */ adp = NULL; } else { adp = ofork->of_ad; } vol = ofork->of_vol; dir = dirlookup(vol, ofork->of_did); if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding()))) { return( AFPERR_MISC ); } path.m_name = of_name(ofork); path.id = 0; st = &path.st; if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) | (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) { if ( ad_data_fileno( ofork->of_ad ) <= 0 ) { /* 0 is for symlink */ if (movecwd(vol, dir) < 0) return( AFPERR_NOOBJ ); if ( lstat( path.u_name, st ) < 0 ) return( AFPERR_NOOBJ ); } else { if ( fstat( ad_data_fileno( ofork->of_ad ), st ) < 0 ) { return( AFPERR_BITMAP ); } } } return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp ); }
/*! * This function performs a CNID db search * * Uses globals c1, c2, the search criteria * * @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 * @param nrecs (w) number of matches * @param rsize (w) length of data written to output buffer * @param ext (r) extended search flag */ static int catsearch_db(struct vol *vol, struct dir *dir, const char *uname, int rmatches, uint32_t *pos, char *rbuf, uint32_t *nrecs, int *rsize, int ext) { static char resbuf[DBD_MAX_SRCH_RSLTS * sizeof(cnid_t)]; 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; goto catsearch_end; } 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, buffer, strlen(uname), resbuf, sizeof(resbuf))) == -1) { result = AFPERR_MISC; goto catsearch_end; } } while (cur_pos < num_matches) { char *name; cnid_t cnid, did; char resolvebuf[12 + MAXPATHLEN + 1]; struct dir *dir; /* Next CNID to process from buffer */ 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) 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; path.m_name = utompath(vol, name, cnid, utf8_encoding()); if (of_stat(vol, &path) != 0) { switch (errno) { case EACCES: case ELOOP: 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) goto next; path.d_dir = dir; 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) { result = AFPERR_MISC; goto catsearch_end; } *nrecs += r; /* Number of matches limit */ if (--rmatches == 0) goto catsearch_pause; /* Block size limit */ if (rrbuf - rbuf >= 448) goto catsearch_pause; } next: cur_pos++; } /* while */ /* finished */ result = AFPERR_EOF; cur_pos = 0; goto catsearch_end; catsearch_pause: *pos = cur_pos; 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; }
static int catsearch(struct vol *vol, struct dir *dir, int rmatches, uint32_t *pos, char *rbuf, uint32_t *nrecs, int *rsize, int ext) { 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; int ccr; struct path path; char *vpath = vol->v_path; char *rrbuf = rbuf; time_t start_time; int num_rounds = NUM_ROUNDS; int cwd = -1; int error; int unlen; if (*pos != 0 && *pos != cur_pos) { result = AFPERR_CATCHNG; goto catsearch_end; } /* FIXME: Category "offspring count ! */ /* 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 (addstack(vpath, dir, -1) == -1) { result = AFPERR_MISC; goto catsearch_end; } /* FIXME: Sometimes DID is given by client ! (correct this one above !) */ } /* Save current path */ if ((cwd = open(".", O_RDONLY)) < 0) { result = AFPERR_MISC; goto catsearch_end; } /* So we are beginning... */ start_time = time(NULL); while ((cidx = reducestack()) != -1) { 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(bdata(currentdir->d_fullpath)); if (error || dirpos == NULL) { switch (errno) { case EACCES: dstack[cidx].ds_checked = 1; continue; case EMFILE: case ENFILE: case ENOENT: result = AFPERR_NFILE; break; case ENOMEM: case ENOTDIR: default: result = AFPERR_MISC; } /* switch (errno) */ goto catsearch_end; } 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(vol, &path) != 0) { switch (errno) { case EACCES: case ELOOP: case ENOENT: continue; case ENOTDIR: case EFAULT: case ENOMEM: case ENAMETOOLONG: default: result = AFPERR_MISC; goto catsearch_end; } } 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. */ 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 ((path.d_dir = dir_add(vol, currentdir, &path, unlen)) == NULL) { result = AFPERR_MISC; goto catsearch_end; } } path.m_name = cfrombstr(path.d_dir->d_m_name); if (addstack(path.u_name, path.d_dir, cidx) == -1) { result = AFPERR_MISC; goto catsearch_end; } 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); if (r == 0) { result = AFPERR_MISC; goto catsearch_end; } *nrecs += r; /* Number of matches limit */ if (--rmatches == 0) goto catsearch_pause; /* Block size limit */ if (rrbuf - rbuf >= 448) goto catsearch_pause; } /* 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; dstack[cidx].ds_checked = 1; } /* while (current_idx = reducestack()) != -1) */ /* We have finished traversing our tree. Return EOF here. */ result = AFPERR_EOF; goto catsearch_end; catsearch_pause: cur_pos = *pos; save_cidx = cidx; catsearch_end: /* Exiting catsearch: error condition */ *rsize = rrbuf - rbuf; if (cwd != -1) { if ((fchdir(cwd)) != 0) { LOG(log_debug, logtype_afpd, "error chdiring back: %s", strerror(errno)); } close(cwd); } return result; } /* catsearch() */