Beispiel #1
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;
}
Beispiel #2
0
/*
 * Function: sys_ea_copyfile
 *
 * Purpose: copy EAs
 *
 * Arguments:
 *
 *    vol          (r) current volume
 *    sdf          (r) source file descriptor
 *    src          (r) source path
 *    dst          (r) destination path
 *
 * Return AFP code AFP_OK on success or appropriate AFP error code
 *
 * Effects:
 *
 * Copies EAs from source file to dest file.
 */
int sys_ea_copyfile(VFS_FUNC_ARGS_COPYFILE)
{
  	int ret = 0;
    int cwd = -1;
	ssize_t size;
	char *names = NULL, *end_names, *name, *value = NULL;
	unsigned int setxattr_ENOTSUP = 0;

    if (sfd != -1) {
        if ((cwd = open(".", O_RDONLY)) == -1) {
            LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant open cwd: %s",
                strerror(errno));
            ret = -1;
            goto getout;
        }
    }

    if (sfd != -1) {
        if (fchdir(sfd) == -1) {
            LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to sfd: %s",
                strerror(errno));
            ret = -1;
            goto getout;
        }
    }

	size = sys_listxattr(src, NULL, 0);
	if (size < 0) {
		if (errno != ENOSYS && errno != ENOTSUP) {
			ret = -1;
		}
		goto getout;
	}
	names = malloc(size+1);
	if (names == NULL) {
		ret = -1;
		goto getout;
	}
	size = sys_listxattr(src, names, size);
	if (size < 0) {
		ret = -1;
		goto getout;
	} else {
		names[size] = '\0';
		end_names = names + size;
	}

    if (sfd != -1) {
        if (fchdir(cwd) == -1) {
            LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to cwd: %s",
                strerror(errno));
            ret = -1;
            goto getout;
        }
    }

	for (name = names; name != end_names; name = strchr(name, '\0') + 1) {
		void *old_value;

		/* check if this attribute shall be preserved */
		if (!*name)
			continue;

        if (STRCMP(name, ==, AD_EA_META))
            continue;

        if (sfd != -1) {
            if (fchdir(sfd) == -1) {
                LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to sfd: %s",
                    strerror(errno));
                ret = -1;
                goto getout;
            }
        }

		size = sys_getxattr (src, name, NULL, 0);
		if (size < 0) {
			ret = -1;
			continue;
		}
		value = realloc(old_value = value, size);
		if (size != 0 && value == NULL) {
			free(old_value);
			ret = -1;
		}
		size = sys_getxattr(src, name, value, size);
		if (size < 0) {
			ret = -1;
			continue;
		}

        if (sfd != -1) {
            if (fchdir(cwd) == -1) {
                LOG(log_error, logtype_afpd, "sys_ea_copyfile: cant chdir to cwd: %s",
                    strerror(errno));
                ret = -1;
                goto getout;
            }
        }

		if (sys_setxattr(dst, name, value, size, 0) != 0) {
			if (errno == ENOTSUP)
				setxattr_ENOTSUP++;
			else {
				if (errno == ENOSYS) {
					ret = -1;
					/* no hope of getting any further */
					break;
				} else {
					ret = -1;
				}
			}
		}
	}
	if (setxattr_ENOTSUP) {
		errno = ENOTSUP;
		ret = -1;
	}

getout:
    if (cwd != -1)
        close(cwd);
        
	free(value);
	free(names);

    if (ret == -1) {
        switch(errno) {
        case ENOENT:
            /* no attribute */
            break;
        case EACCES:
            LOG(log_debug, logtype_afpd, "sys_ea_copyfile(%s, %s): error: %s", src, dst, strerror(errno));
            return AFPERR_ACCESS;
        default:
            LOG(log_error, logtype_afpd, "sys_ea_copyfile(%s, %s): error: %s", src, dst, strerror(errno));
            return AFPERR_MISC;
        }
    }

    return AFP_OK;
}
Beispiel #3
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;
}
Beispiel #4
0
int vfswrap_setxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
{
	return sys_setxattr(path, name, value, size, flags);
}