Ejemplo n.º 1
0
/*!
 * 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;
}
Ejemplo n.º 2
0
Archivo: appl.c Proyecto: hajuuk/R7000
/*
 * 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
}
Ejemplo n.º 3
0
/* -------------------------------------------------------
*/
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;
}