Пример #1
0
APR_DECLARE(apr_status_t) apr_filepath_get(char **rootpath, apr_int32_t flags,
                                           apr_pool_t *p)
{
    char path[APR_PATH_MAX];
    char *ptr;

    /* use getcwdpath to make sure that we get the volume name*/
    if (!getcwdpath(path, NULL, 0)) {
        if (errno == ERANGE)
            return APR_ENAMETOOLONG;
        else
            return errno;
    }
    /* Strip off the server name if there is one*/
    ptr = strpbrk(path, "\\/:");
    if (!ptr) {
        return APR_ENOENT;
    }
    if (*ptr == ':') {
        ptr = path;
    }
    *rootpath = apr_pstrdup(p, ptr);
    if (!(flags & APR_FILEPATH_NATIVE)) {
        for (ptr = *rootpath; *ptr; ++ptr) {
            if (*ptr == '\\')
                *ptr = '/';
        }
    }
    return APR_SUCCESS;
}
Пример #2
0
/*
 * Function: sys_set_ea
 *
 * Purpose: set a native EA
 *
 * Arguments:
 *
 *    vol          (r) current volume
 *    uname        (r) filename
 *    attruname    (r) EA name
 *    ibuf         (r) buffer with EA content
 *    attrsize     (r) length EA in ibuf
 *    oflag        (r) link and create flag
 *
 * Returns: AFP code: AFP_OK on success or appropiate AFP error code
 *
 * Effects:
 *
 */
int sys_set_ea(VFS_FUNC_ARGS_EA_SET)
{
    int attr_flag;
    int ret;

    attr_flag = 0;
    if ((oflag & O_CREAT) )
        attr_flag |= XATTR_CREATE;

    else if ((oflag & O_TRUNC) )
        attr_flag |= XATTR_REPLACE;

    if ((oflag & O_NOFOLLOW) ) {
        ret = sys_lsetxattr(uname, attruname,  ibuf, attrsize,attr_flag);
    }
    else {
        ret = sys_setxattr(uname, attruname,  ibuf, attrsize, attr_flag);
    }

    if (ret == -1) {
        switch(errno) {
        case OPEN_NOFOLLOW_ERRNO:
            /* its a symlink and client requested O_NOFOLLOW  */
            LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s\", ea:'%s'): symlink with kXAttrNoFollow",
                uname, attruname);
            return AFP_OK;
        case EEXIST:
            LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): EA already exists",
                getcwdpath(), uname, attruname);
            return AFPERR_EXIST;
        default:
            LOG(log_error, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s', size: %u, flags: %s|%s|%s): %s",
                getcwdpath(), uname, attruname, attrsize,
                oflag & O_CREAT ? "XATTR_CREATE" : "-",
                oflag & O_TRUNC ? "XATTR_REPLACE" : "-",
                oflag & O_NOFOLLOW ? "O_NOFOLLOW" : "-",
                strerror(errno));
            return AFPERR_MISC;
        }
    }

    return AFP_OK;
}
Пример #3
0
APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, 
                                   const char *fname, 
                                   apr_int32_t wanted, apr_pool_t *pool)
{
    struct stat info;
    int srv;
    NXPathCtx_t pathCtx = 0;

    getcwdpath(NULL, &pathCtx, CTX_ACTUAL_CWD);
#ifdef APR_HAS_PSA
	srv = getstat(pathCtx, (char*)fname, &info, ST_STAT_BITS|ST_NAME_BIT);
#else
    srv = cstat(pathCtx, (char*)fname, &info, ST_STAT_BITS|ST_NAME_BIT, pool);
#endif
    errno = srv;

    if (srv == 0) {
        finfo->pool = pool;
        finfo->fname = fname;
        fill_out_finfo(finfo, &info, wanted);
        if (wanted & APR_FINFO_LINK)
            wanted &= ~APR_FINFO_LINK;
        if (wanted & APR_FINFO_NAME) {
            finfo->name = apr_pstrdup(pool, info.st_name);
            finfo->valid |= APR_FINFO_NAME;
        }
        return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
    }
    else {
#if !defined(ENOENT) || !defined(ENOTDIR)
#error ENOENT || ENOTDIR not defined; please see the
#error comments at this line in the source for a workaround.
        /*
         * If ENOENT || ENOTDIR is not defined in one of the your OS's
         * include files, APR cannot report a good reason why the stat()
         * of the file failed; there are cases where it can fail even though
         * the file exists.  This opens holes in Apache, for example, because
         * it becomes possible for someone to get a directory listing of a 
         * directory even though there is an index (eg. index.html) file in 
         * it.  If you do not have a problem with this, delete the above 
         * #error lines and start the compile again.  If you need to do this,
         * please submit a bug report to http://www.apache.org/bug_report.html
         * letting us know that you needed to do this.  Please be sure to 
         * include the operating system you are using.
         */
        /* WARNING: All errors will be handled as not found
         */
#if !defined(ENOENT) 
        return APR_ENOENT;
#else
        /* WARNING: All errors but not found will be handled as not directory
         */
        if (errno != ENOENT)
            return APR_ENOENT;
        else
            return errno;
#endif
#else /* All was defined well, report the usual: */
        return errno;
#endif
    }
}
Пример #4
0
/*
 * Function: sys_set_ea
 *
 * Purpose: set a native EA
 *
 * Arguments:
 *
 *    vol          (r) current volume
 *    uname        (r) filename
 *    attruname    (r) EA name
 *    ibuf         (r) buffer with EA content
 *    attrsize     (r) length EA in ibuf
 *    oflag        (r) link and create flag
 *
 * Returns: AFP code: AFP_OK on success or appropiate AFP error code
 *
 * Effects:
 *
 */
int sys_set_ea(VFS_FUNC_ARGS_EA_SET)
{
    int attr_flag;
    int ret;
    char *eabuf;

    /*
     * Buffer for a copy of the xattr plus one byte in case
     * AFPVOL_EA_SAMBA is used
     */
    eabuf = malloc(attrsize + 1);
    if (eabuf == NULL) {
        return AFPERR_MISC;
    }
    memcpy(eabuf, ibuf, attrsize);
    eabuf[attrsize] = 0;

    attr_flag = 0;
    if ((oflag & O_CREAT) ) 
        attr_flag |= XATTR_CREATE;
    else if ((oflag & O_TRUNC) ) 
        attr_flag |= XATTR_REPLACE;

    if (vol->v_flags & AFPVOL_EA_SAMBA) {
        attrsize++;
    }

    /* PBaranski fix */
    if ( fd != -1) {
	LOG(log_debug, logtype_afpd, "sys_set_ea(%s): file is already opened", uname);
	ret = sys_fsetxattr(fd, attruname, eabuf, attrsize, attr_flag);
    } else {
	if ((oflag & O_NOFOLLOW) ) {
   	    ret = sys_lsetxattr(uname, attruname, eabuf, attrsize,attr_flag);
	}
	else {
   	    ret = sys_setxattr(uname, attruname, eabuf, attrsize, attr_flag);
	}
    }
    /* PBaranski fix */

    if (ret == -1) {
        switch(errno) {
        case OPEN_NOFOLLOW_ERRNO:
            /* its a symlink and client requested O_NOFOLLOW  */
            LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s\", ea:'%s'): symlink with kXAttrNoFollow",
                uname, attruname);
            return AFP_OK;
        case EEXIST:
            LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): EA already exists",
                getcwdpath(), uname, attruname);
            return AFPERR_EXIST;
        case ENOATTR:
        case ENOENT:
            if ((attr_flag & XATTR_REPLACE) && (vol->v_obj->afp_version >= 34))
                return AFPERR_NOITEM;
            return AFPERR_MISC;
        default:
            LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s', size: %u, flags: %s|%s|%s): %s",
                getcwdpath(), uname, attruname, attrsize, 
                oflag & O_CREAT ? "XATTR_CREATE" : "-",
                oflag & O_TRUNC ? "XATTR_REPLACE" : "-",
                oflag & O_NOFOLLOW ? "O_NOFOLLOW" : "-",
                strerror(errno));
            return AFPERR_MISC;
        }
    }

    return AFP_OK;
}
Пример #5
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;
}
Пример #6
0
/*
 *
 * Dispatcher for all incoming file change events
 *
 * */
static int register_fce(const char *u_name, int is_dir, int mode)
{
    if (udp_sockets == 0)
        /* No listeners configured */
        return AFP_OK;

    if (u_name == NULL)
        return AFPERR_PARAM;

    static int first_event = FCE_TRUE;

	/* do some initialization on the fly the first time */
	if (first_event) {
		fce_initialize_history();
	}

	/* handle files which should not cause events (.DS_Store atc. ) */
	for (int i = 0; skip_files[i] != NULL; i++)
	{
		if (!strcmp( u_name, skip_files[i]))
			return AFP_OK;
	}


	char full_path_buffer[MAXPATHLEN + 1] = {""};
	const char *cwd = getcwdpath();

    if (mode == FCE_TM_SIZE) {
        strlcpy(full_path_buffer, u_name, MAXPATHLEN);
    } else if (!is_dir || mode == FCE_DIR_DELETE) {
		if (strlen( cwd ) + strlen( u_name) + 1 >= MAXPATHLEN) {
			LOG(log_error, logtype_afpd, "FCE file name too long: %s/%s", cwd, u_name );
			return AFPERR_PARAM;
		}
		sprintf( full_path_buffer, "%s/%s", cwd, u_name );
	} else {
		if (strlen( cwd ) >= MAXPATHLEN) {
			LOG(log_error, logtype_afpd, "FCE directory name too long: %s", cwd);
			return AFPERR_PARAM;
		}
		strcpy( full_path_buffer, cwd);
	}

	/* Can we ignore this event based on type or history? */
	if (!(mode & FCE_TM_SIZE) && fce_handle_coalescation( full_path_buffer, is_dir, mode ))
	{
		LOG(log_debug9, logtype_afpd, "Coalesced fc event <%d> for <%s>", mode, full_path_buffer );
		return AFP_OK;
	}

	LOG(log_debug9, logtype_afpd, "Detected fc event <%d> for <%s>", mode, full_path_buffer );


    /* we do initilization on the fly, no blocking calls in here 
     * (except when using FQDN in broken DNS environment)
     */
    if (first_event == FCE_TRUE)
    {
        fce_init_udp();
        
        /* Notify listeners the we start from the beginning */
        send_fce_event( "", FCE_CONN_START );
        
        first_event = FCE_FALSE;
    }

	/* Handle UDP transport */
    send_fce_event( full_path_buffer, mode );

    return AFP_OK;
}
Пример #7
0
/*
 *
 * Dispatcher for all incoming file change events
 *
 * */
static int register_fce(const char *u_name, int is_dir, int mode)
{
    static int first_event = FCE_TRUE;

    if (udp_sockets == 0)
        /* No listeners configured */
        return AFP_OK;

    if (u_name == NULL)
        return AFPERR_PARAM;

	/* do some initialization on the fly the first time */
	if (first_event) {
		fce_initialize_history();
        first_event = FCE_FALSE;
	}

	/* handle files which should not cause events (.DS_Store atc. ) */
	for (int i = 0; skip_files[i] != NULL; i++)
	{
		if (!strcmp( u_name, skip_files[i]))
			return AFP_OK;
	}


	char full_path_buffer[MAXPATHLEN + 1] = {""};
	const char *cwd = getcwdpath();

    if (mode == FCE_TM_SIZE) {
        strlcpy(full_path_buffer, u_name, MAXPATHLEN);
    } else if (!is_dir || mode == FCE_DIR_DELETE) {
		if (strlen( cwd ) + strlen( u_name) + 1 >= MAXPATHLEN) {
			LOG(log_error, logtype_afpd, "FCE file name too long: %s/%s", cwd, u_name );
			return AFPERR_PARAM;
		}
		sprintf( full_path_buffer, "%s/%s", cwd, u_name );
	} else {
		if (strlen( cwd ) >= MAXPATHLEN) {
			LOG(log_error, logtype_afpd, "FCE directory name too long: %s", cwd);
			return AFPERR_PARAM;
		}
		strcpy( full_path_buffer, cwd);
	}

	/* Can we ignore this event based on type or history? */
	if (!(mode & FCE_TM_SIZE) && fce_handle_coalescation( full_path_buffer, is_dir, mode ))
	{
		LOG(log_debug9, logtype_afpd, "Coalesced fc event <%d> for <%s>", mode, full_path_buffer );
		return AFP_OK;
	}

	LOG(log_debug9, logtype_afpd, "Detected fc event <%d> for <%s>", mode, full_path_buffer );

    if (mode & FCE_FILE_MODIFY) {
        save_close_event(full_path_buffer);
        return AFP_OK;
    }

    send_fce_event( full_path_buffer, mode );

    return AFP_OK;
}