/* * 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_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_lsetxattr(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_lsetxattr(path, name, value, size, flags); }
int main(int argc, char **argv) { int ret = 0; struct stat st; char *dname = NULL; char *bname = NULL; ssize_t ret_size = 0; uuid_t pgfid_raw = { 0, }; char pgfid[36] = ""; char xxh64[GF_XXH64_DIGEST_LENGTH * 2 + 1] = { 0, }; char pgfid_bname[1024] = { 0, }; char *key = NULL; char *val = NULL; size_t key_size = 0; size_t val_size = 0; const char *file_path = NULL; char *file_path1 = NULL; char *file_path2 = NULL; if (argc != 2) { fprintf(stderr, "Usage: setgfid2path <file-path>\n"); return -1; } ret = sys_lstat(argv[1], &st); if (ret != 0) { fprintf(stderr, "Invalid File Path\n"); return -1; } if (st.st_nlink >= MAX_GFID2PATH_LINK_SUP) { fprintf(stderr, "Number of Hardlink support exceeded. " "max=%d\n", MAX_GFID2PATH_LINK_SUP); return -1; } file_path = argv[1]; file_path1 = strdup(file_path); file_path2 = strdup(file_path); dname = dirname(file_path1); bname = basename(file_path2); /* Get GFID of Parent directory */ ret_size = sys_lgetxattr(dname, GFID_XATTR_KEY, pgfid_raw, GFID_SIZE); if (ret_size != GFID_SIZE) { fprintf(stderr, "Failed to get GFID of parent directory. dir=%s\n", dname); ret = -1; goto out; } /* Convert to UUID format */ if (uuid_utoa_r(pgfid_raw, pgfid) == NULL) { fprintf(stderr, "Failed to format GFID of parent directory. " "dir=%s GFID=%s\n", dname, pgfid_raw); ret = -1; goto out; } /* Find xxhash for PGFID/BaseName */ snprintf(pgfid_bname, sizeof(pgfid_bname), "%s/%s", pgfid, bname); gf_xxh64_wrapper((unsigned char *)pgfid_bname, strlen(pgfid_bname), GF_XXHSUM64_DEFAULT_SEED, xxh64); key_size = SLEN(GFID2PATH_XATTR_KEY_PREFIX) + GF_XXH64_DIGEST_LENGTH * 2 + 1; key = alloca(key_size); snprintf(key, key_size, GFID2PATH_XATTR_KEY_PREFIX "%s", xxh64); val_size = UUID_CANONICAL_FORM_LEN + NAME_MAX + 2; val = alloca(val_size); snprintf(val, val_size, "%s/%s", pgfid, bname); /* Set the Xattr, ignore if same key xattr already exists */ ret = sys_lsetxattr(file_path, key, val, strlen(val), XATTR_CREATE); if (ret == -1) { if (errno == EEXIST) { printf("Xattr already exists, ignoring..\n"); ret = 0; goto out; } fprintf(stderr, "Failed to set gfid2path xattr. errno=%d\n error=%s", errno, strerror(errno)); ret = -1; goto out; } printf("Success. file=%s key=%s value=%s\n", file_path, key, val); out: if (file_path1 != NULL) free(file_path1); if (file_path2 != NULL) free(file_path2); return ret; }