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 ); }
int fce_register_file_modification( struct ofork *ofork ) { char *u_name = NULL; struct vol *vol; int ret = AFP_OK; if (ofork == NULL || ofork->of_vol == NULL) return AFPERR_PARAM; if (!(fce_ev_enabled & (1 << FCE_FILE_MODIFY))) return ret; vol = ofork->of_vol; if (NULL == (u_name = mtoupath(vol, of_name(ofork), ofork->of_did, utf8_encoding()))) { return AFPERR_MISC; } ret = register_fce( u_name, FALSE, FCE_FILE_MODIFY ); return ret; }
/* * build mac. path (backwards) by traversing the directory tree * * The old way: dir and path refer to an app, path is a mac format * pathname. makemacpath() builds something that looks like a cname, * but uses upaths instead of mac format paths. * * The new way: dir and path refer to an app, path is a mac format * pathname. makemacpath() builds a cname. (zero is a path separator * and it's not \0 terminated). * * See afp_getappl() for the backward compatiblity code. */ static char * makemacpath(const struct vol *vol, char *mpath, int mpathlen, struct dir *dir, char *path) { char *p; p = mpath + mpathlen; p -= strlen( path ); memcpy( p, path, strlen( path )); while ( dir->d_did != DIRDID_ROOT ) { p -= blength(dir->d_m_name) + 1; if (p < mpath) { /* FIXME: pathname too long */ return NULL; } memcpy(p, cfrombstr(dir->d_m_name), blength(dir->d_m_name) + 1); if ((dir = dirlookup(vol, dir->d_pdid)) == NULL) return NULL; } return( p ); #if 0 char buffer[12 + MAXPATHLEN + 1]; int buflen = 12 + MAXPATHLEN + 1; char *ret = mpath; char *path = name; char *uname = NULL; struct bstrList *pathlist = NULL; cnid_t cnid = dir->d_pdid; /* Create list for path elements, request 16 list elements for now*/ if ((pathlist = bstListCreateMin(16)) == NULL) { LOG(log_error, logtype_afpd, "makemacpath: OOM: %s", strerror(errno)); return NULL; } while ( cnid != DIRDID_ROOT ) { /* construct path, copy already found uname to path element list*/ if ((bstrListPush(pathlist, bfromcstr(path))) != BSTR_OK) { afp_errno = AFPERR_MISC; ret = NULL; goto exit; } /* next part */ if ((uname = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL ) { afp_errno = AFPERR_NOOBJ; ret = NULL; goto exit; } if ((path = utompath(vol, uname, cnid, utf8_encoding())) == NULL) { afp_errno = AFPERR_MISC; ret = NULL; goto exit; } } exit: if (pathlist) bstrListDestroy(pathlist); return(ret); #endif }
/*! * 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; }
/* uname - UNIX name * fname - our fname (translated to UNIX) * cidx - index in directory stack */ 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; /* 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<<DIRPBIT_LNAME))) { if ( (size_t)(-1) == (len = convert_string(vol->v_maccharset, CH_UCS2, path->m_name, -1, convbuf, 512)) ) goto crit_check_ret; if ((c1.rbitmap & (1<<CATPBIT_PARTIAL))) { if (strcasestr_w( (ucs2_t*) convbuf, (ucs2_t*) c1.lname) == NULL) goto crit_check_ret; } else if (strcasecmp_w((ucs2_t*) convbuf, (ucs2_t*) c1.lname) != 0) goto crit_check_ret; } if ((c1.rbitmap & (1<<FILPBIT_PDINFO))) { 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; } if (c1.rbitmap & (1<<CATPBIT_PARTIAL)) { if (strcasestr_w((ucs2_t *) convbuf, (ucs2_t*)c1.utf8name) == NULL) goto crit_check_ret; } else if (strcasecmp_w((ucs2_t *)convbuf, (ucs2_t*)c1.utf8name) != 0) goto crit_check_ret; } /* FIXME */ if ((unsigned)c2.mdate > 0x7fffffff) c2.mdate = 0x7fffffff; if ((unsigned)c2.cdate > 0x7fffffff) c2.cdate = 0x7fffffff; if ((unsigned)c2.bdate > 0x7fffffff) c2.bdate = 0x7fffffff; /* Check for modification date */ if ((c1.rbitmap & (1<<DIRPBIT_MDATE))) { if (path->st.st_mtime < c1.mdate || path->st.st_mtime > c2.mdate) goto crit_check_ret; } /* Check for creation date... */ if ((c1.rbitmap & (1<<DIRPBIT_CDATE))) { c_date = path->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<<DIRPBIT_BDATE))) { b_date = path->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<<DIRPBIT_ATTR)) && c2.attr != 0) { if ((adp = adl_lkup(vol, path, adp))) { ad_getattr(adp, &attr); if ((attr & c2.attr) != c1.attr) goto crit_check_ret; } else goto crit_check_ret; } /* Check file type ID */ if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.f_type != 0) { finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk); if (finfo->f_type != c1.finfo.f_type) goto crit_check_ret; } /* Check creator ID */ if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.creator != 0) { if (!finfo) { finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk); } if (finfo->creator != c1.finfo.creator) goto crit_check_ret; } /* Check finder info attributes */ if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.attrs != 0) { if (!finfo) { finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk); } if ((finfo->attrs & c2.finfo.attrs) != c1.finfo.attrs) goto crit_check_ret; } /* Check label */ if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.label != 0) { if (!finfo) { finfo = unpack_finderinfo(vol, path, &adp, &finderinfo,islnk); } if ((finfo->label & c2.finfo.label) != c1.finfo.label) goto crit_check_ret; } /* FIXME: Attributes check ! */ /* All criteria are met. */ result |= 1; crit_check_ret: if (adp != NULL) ad_close_metadata(adp); return result; }
/* ------------------------------------------------------- */ static char * private_demangle(const struct vol *vol, char *mfilename, cnid_t did, cnid_t *osx) { char *t; char *u_name; uint32_t id, file_id; static char buffer[12 + MAXPATHLEN + 1]; int len = 12 + MAXPATHLEN + 1; struct dir *dir; size_t prefix; id = file_id = 0; t = strchr(mfilename, MANGLE_CHAR); if (t == NULL) { return mfilename; } prefix = t - mfilename; /* FIXME * is prefix == 0 a valid mangled filename ? */ /* may be a mangled filename */ t++; if (*t == '0') { /* can't start with a 0 */ return mfilename; } while(isuxdigit(*t)) { id = (id *16) + hextoint(*t); t++; } if ((*t != 0 && *t != '.') || strlen(t) > MAX_EXT_LENGTH || id < 17) { return mfilename; } file_id = id = htonl(id); if (osx) { *osx = id; } /* is it a dir?, there's a conflict with pre OSX 'trash #2' */ if ((dir = dirlookup(vol, id))) { if (dir->d_pdid != did) { /* not in the same folder, there's a race with outdate cache * but we have to live with it, hopefully client will recover */ return mfilename; } if (!osx) { /* it's not from cname so mfilename and dir must be the same */ if (strcmp(cfrombstr(dir->d_m_name), mfilename) == 0) { return cfrombstr(dir->d_u_name); } } else { return demangle_checks(vol, cfrombstr(dir->d_u_name), mfilename, prefix, t); } } else if (NULL != (u_name = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) { if (id != did) { return mfilename; } if (!osx) { /* convert back to mac name and check it's the same */ t = utompath(vol, u_name, file_id, utf8_encoding(vol->v_obj)); if (!strcmp(t, mfilename)) { return u_name; } } else { return demangle_checks (vol, u_name, mfilename, prefix, t); } } return mfilename; }