/* * 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; }
/* * 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; }
/* * 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; }
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); }