static int _posix_xattr_get_set_from_backend (posix_xattr_filler_t *filler, char *key) { ssize_t xattr_size = -1; int ret = 0; char *value = NULL; xattr_size = sys_lgetxattr (filler->real_path, key, NULL, 0); if (xattr_size > 0) { value = GF_CALLOC (1, xattr_size + 1, gf_posix_mt_char); if (!value) goto out; xattr_size = sys_lgetxattr (filler->real_path, key, value, xattr_size); if (xattr_size <= 0) { gf_log (filler->this->name, GF_LOG_WARNING, "getxattr failed. path: %s, key: %s", filler->real_path, key); GF_FREE (value); goto out; }
/* * Function: sys_get_easize * * Purpose: get size of a native EA * * Arguments: * * vol (r) current volume * rbuf (w) DSI reply buffer * rbuflen (rw) current length of data in reply buffer * uname (r) filename * oflag (r) link and create flag * attruname (r) name of attribute * * Returns: AFP code: AFP_OK on success or appropiate AFP error code * * Effects: * * Copies EA size into rbuf in network order. Increments *rbuflen +4. */ int sys_get_easize(VFS_FUNC_ARGS_EA_GETSIZE) { ssize_t ret; uint32_t attrsize; LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\"", uname, attruname); if ((oflag & O_NOFOLLOW) ) { ret = sys_lgetxattr(uname, attruname, rbuf +4, 0); } else { ret = sys_getxattr(uname, attruname, rbuf +4, 0); } if (ret == -1) { memset(rbuf, 0, 4); *rbuflen += 4; switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ LOG(log_debug, logtype_afpd, "sys_getextattr_size(%s): symlink with kXAttrNoFollow", uname); return AFPERR_MISC; case ENOATTR: case ENOENT: return AFPERR_MISC; default: LOG(log_debug, logtype_afpd, "sys_getextattr_size: error: %s", strerror(errno)); return AFPERR_MISC; } } if (ret > MAX_EA_SIZE) ret = MAX_EA_SIZE; /* Start building reply packet */ LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\", size: %u", uname, attruname, ret); /* length of attribute data */ attrsize = htonl((uint32_t)ret); memcpy(rbuf, &attrsize, 4); *rbuflen += 4; ret = AFP_OK; return ret; }
/* * Function: sys_get_eacontent * * Purpose: copy native EA into rbuf * * Arguments: * * vol (r) current volume * rbuf (w) DSI reply buffer * rbuflen (rw) current length of data in reply buffer * uname (r) filename * oflag (r) link and create flag * attruname (r) name of attribute * maxreply (r) maximum EA size as of current specs/real-life * * Returns: AFP code: AFP_OK on success or appropiate AFP error code * * Effects: * * Copies EA into rbuf. Increments *rbuflen accordingly. */ int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT) { ssize_t ret; uint32_t attrsize; /* Start building reply packet */ maxreply -= MAX_REPLY_EXTRA_BYTES; if (maxreply > MAX_EA_SIZE) maxreply = MAX_EA_SIZE; LOG(log_debug7, logtype_afpd, "sys_getextattr_content(%s): attribute: \"%s\", size: %u", uname, attruname, maxreply); if ((oflag & O_NOFOLLOW) ) { ret = sys_lgetxattr(uname, attruname, rbuf +4, maxreply); } else { ret = sys_getxattr(uname, attruname, rbuf +4, maxreply); } if (ret == -1) { memset(rbuf, 0, 4); *rbuflen += 4; switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): symlink with kXAttrNoFollow", uname); return AFPERR_MISC; case ENOATTR: return AFPERR_MISC; default: LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): error: %s", attruname, strerror(errno)); return AFPERR_MISC; } } /* remember where we must store length of attribute data in rbuf */ *rbuflen += 4 +ret; attrsize = htonl((uint32_t)ret); memcpy(rbuf, &attrsize, 4); return AFP_OK; }
static char * parse_and_validate_args (int argc, char *argv[]) { char *basedir = NULL; struct stat d = {0, }; int ret = -1; #ifndef __FreeBSD__ unsigned char volume_id[16]; #endif /* __FreeBSD__ */ char *slv_mnt = NULL; if (argc != 4) { err ("Usage: %s <DIR> <SLAVE-VOL-MOUNT> <CRAWL-THREAD-COUNT>\n", argv[0]); return NULL; } basedir = argv[1]; ret = sys_lstat (basedir, &d); if (ret) { err ("%s: %s\n", basedir, strerror (errno)); return NULL; } #ifndef __FreeBSD__ ret = sys_lgetxattr (basedir, "trusted.glusterfs.volume-id", volume_id, 16); if (ret != 16) { err ("%s:Not a valid brick path.\n", basedir); return NULL; } #endif /* __FreeBSD__ */ slv_mnt = argv[2]; ret = sys_lstat (slv_mnt, &d); if (ret) { err ("%s: %s\n", slv_mnt, strerror (errno)); return NULL; } slavemnt = argv[2]; workers = atoi(argv[3]); if (workers <= 0) workers = DEFAULT_WORKERS; return basedir; }
static int stat_xattr(const char *fname, STRUCT_STAT *fst) { int mode, rdev_major, rdev_minor, uid, gid, len; char buf[256]; if (am_root >= 0 || IS_DEVICE(fst->st_mode) || IS_SPECIAL(fst->st_mode)) return -1; len = sys_lgetxattr(fname, XSTAT_ATTR, buf, sizeof buf - 1); if (len >= (int)sizeof buf) { len = -1; errno = ERANGE; } if (len < 0) { if (errno == ENOTSUP || errno == ENOATTR) return -1; if (errno == EPERM && S_ISLNK(fst->st_mode)) { fst->st_uid = 0; fst->st_gid = 0; return 0; } fprintf(stderr, "failed to read xattr %s for %s: %s\n", XSTAT_ATTR, fname, strerror(errno)); return -1; } buf[len] = '\0'; if (sscanf(buf, "%o %d,%d %d:%d", &mode, &rdev_major, &rdev_minor, &uid, &gid) != 5) { fprintf(stderr, "Corrupt %s xattr attached to %s: \"%s\"\n", XSTAT_ATTR, fname, buf); exit(1); } #if _S_IFLNK != 0120000 if ((mode & (_S_IFMT)) == 0120000) mode = (mode & ~(_S_IFMT)) | _S_IFLNK; #endif fst->st_mode = mode; fst->st_rdev = MAKEDEV(rdev_major, rdev_minor); fst->st_uid = uid; fst->st_gid = gid; return 0; }
/* * Function: sys_get_easize * * Purpose: get size of a native EA * * Arguments: * * vol (r) current volume * rbuf (w) DSI reply buffer * rbuflen (rw) current length of data in reply buffer * uname (r) filename * oflag (r) link and create flag * attruname (r) name of attribute * * Returns: AFP code: AFP_OK on success or appropiate AFP error code * * Effects: * * Copies EA size into rbuf in network order. Increments *rbuflen +4. */ int sys_get_easize(VFS_FUNC_ARGS_EA_GETSIZE) { ssize_t ret; uint32_t attrsize; LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\"", uname, attruname); /* PBaranski fix */ if (fd != -1) { LOG(log_debug, logtype_afpd, "sys_get_easize(%s): file is already opened", uname); ret = sys_fgetxattr(fd, attruname, rbuf +4, 0); } else { if ((oflag & O_NOFOLLOW) ) { ret = sys_lgetxattr(uname, attruname, rbuf +4, 0); } else { ret = sys_getxattr(uname, attruname, rbuf +4, 0); } } /* PBaranski fix */ if (ret == -1) { memset(rbuf, 0, 4); *rbuflen += 4; switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ LOG(log_debug, logtype_afpd, "sys_getextattr_size(%s): symlink with kXAttrNoFollow", uname); return AFPERR_MISC; case ENOATTR: case ENOENT: if (vol->v_obj->afp_version >= 34) return AFPERR_NOITEM; return AFPERR_MISC; default: LOG(log_debug, logtype_afpd, "sys_getextattr_size: error: %s", strerror(errno)); return AFPERR_MISC; } } if (ret > MAX_EA_SIZE) ret = MAX_EA_SIZE; if (vol->v_flags & AFPVOL_EA_SAMBA) { /* What can we do about xattrs that are 1 byte large? */ if (ret < 2) { memset(rbuf, 0, 4); *rbuflen += 4; if (vol->v_obj->afp_version >= 34) { return AFPERR_NOITEM; } return AFPERR_MISC; } ret--; } /* Start building reply packet */ LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\", size: %u", uname, attruname, ret); /* length of attribute data */ attrsize = htonl((uint32_t)ret); memcpy(rbuf, &attrsize, 4); *rbuflen += 4; ret = AFP_OK; return ret; }
/* * Function: sys_get_eacontent * * Purpose: copy native EA into rbuf * * Arguments: * * vol (r) current volume * rbuf (w) DSI reply buffer * rbuflen (rw) current length of data in reply buffer * uname (r) filename * oflag (r) link and create flag * attruname (r) name of attribute * maxreply (r) maximum EA size as of current specs/real-life * fd (r) file descriptor * Returns: AFP code: AFP_OK on success or appropiate AFP error code * * Effects: * * Copies EA into rbuf. Increments *rbuflen accordingly. */ int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT) { ssize_t ret; uint32_t attrsize; /* Start building reply packet */ maxreply -= MAX_REPLY_EXTRA_BYTES; if (maxreply > MAX_EA_SIZE) maxreply = MAX_EA_SIZE; LOG(log_debug7, logtype_afpd, "sys_getextattr_content(%s): attribute: \"%s\", size: %u", uname, attruname, maxreply); if (vol->v_flags & AFPVOL_EA_SAMBA) { maxreply++; } /* PBaranski fix */ if (fd != -1) { LOG(log_debug, logtype_afpd, "sys_get_eacontent(%s): file is already opened", uname); ret = sys_fgetxattr(fd, attruname, rbuf +4, maxreply); } else { if ((oflag & O_NOFOLLOW) ) { ret = sys_lgetxattr(uname, attruname, rbuf +4, maxreply); } else { ret = sys_getxattr(uname, attruname, rbuf +4, maxreply); } } /* PBaranski fix */ if (ret == -1) { memset(rbuf, 0, 4); *rbuflen += 4; switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): symlink with kXAttrNoFollow", uname); return AFPERR_MISC; case ENOATTR: if (vol->v_obj->afp_version >= 34) return AFPERR_NOITEM; return AFPERR_MISC; default: LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): error: %s", attruname, strerror(errno)); return AFPERR_MISC; } } if (vol->v_flags & AFPVOL_EA_SAMBA) { /* What can we do about xattrs that are 1 byte large? */ if (ret < 2) { memset(rbuf, 0, 4); *rbuflen += 4; if (vol->v_obj->afp_version >= 34) { return AFPERR_NOITEM; } return AFPERR_MISC; } ret--; } /* remember where we must store length of attribute data in rbuf */ *rbuflen += 4 +ret; attrsize = htonl((uint32_t)ret); memcpy(rbuf, &attrsize, 4); return AFP_OK; }
ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) { return sys_lgetxattr(path, name, value, size); }
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; }