ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size) { return lgetxattr(path, name, value, size); }
int run_attr_tests(char *testfile) { int ret = -1; char *res = NULL; struct stat buf; struct statfs sbuf; struct statvfs svbuf; assert(testfile); fprintf(stdout, "Testing chmod"); ret = chmod(testfile, 0); check_err(ret, "chmod", 2); fprintf(stdout, "Testing chown"); ret = chown(testfile, 0, 0); check_err(ret, "chown", 2); fprintf(stdout, "Testing link"); ret = link(testfile, testfile); check_err(ret, "link", 2); fprintf(stdout, "Testing rename"); ret = rename(testfile, testfile); check_err(ret, "rename", 2); fprintf(stdout, "Testing utimes"); ret = utimes(testfile, NULL); check_err(ret, "utimes", 2); fprintf(stdout, "Testing utime"); ret = utime(testfile, NULL); check_err(ret, "utime", 2); fprintf(stdout, "Testing unlink"); ret = unlink(testfile); check_err(ret, "unlink", 2); fprintf(stdout, "Testing symlink"); ret = symlink(testfile, testfile); check_err(ret, "symlink", 2); fprintf(stdout, "Testing readlink"); ret = readlink(testfile, testfile, 0); check_err(ret, "readlink", 2); fprintf(stdout, "Testing realpath"); ret = 0; res = realpath((const char *)testfile, testfile); if (!res) ret = -1; check_err(ret, "realpath", 2); fprintf(stdout, "Testing stat"); ret = stat(testfile, &buf); check_err(ret, "stat", 1); fprintf(stdout, "Testing lstat"); ret = lstat(testfile, &buf); check_err(ret, "lstat", 1); fprintf(stdout, "Testing statfs"); ret = statfs(testfile, &sbuf); check_err(ret, "statfs", 2); fprintf(stdout, "Testing statvfs"); ret = statvfs(testfile, &svbuf); check_err(ret, "statvfs", 1); fprintf(stdout, "Testing getxattr"); ret = getxattr(testfile, NULL, NULL, 0); check_err(ret, "getxattr", 2); fprintf(stdout, "Testing lgetxattr"); ret = lgetxattr(testfile, NULL, NULL, 0); check_err(ret, "lgetxattr", 1); fprintf(stdout, "Testing lchown"); ret = lchown(testfile, 0, 0); check_err(ret, "lchown", 2); return 0; }
static void write_xattr_entry(struct filesystem_entry *e) { struct jffs2_raw_xref ref; struct xattr_entry *xe; char xlist[XATTR_BUFFER_SIZE], xvalue[XATTR_BUFFER_SIZE]; char *xname, *prefix_str; int i, xprefix, prefix_len; int list_sz, offset, name_len, value_len; if (!enable_xattr) return; list_sz = llistxattr(e->hostname, xlist, XATTR_BUFFER_SIZE); if (list_sz < 0) { if (verbose) printf("llistxattr('%s') = %d : %s\n", e->hostname, errno, strerror(errno)); return; } for (offset = 0; offset < list_sz; offset += name_len) { xname = xlist + offset; name_len = strlen(xname) + 1; for (i = 0; (xprefix = xprefix_tbl[i].xprefix); i++) { prefix_str = xprefix_tbl[i].string; prefix_len = xprefix_tbl[i].length; if (prefix_str[prefix_len - 1] == '.') { if (!strncmp(xname, prefix_str, prefix_len - 1)) break; } else { if (!strcmp(xname, prefix_str)) break; } } if (!xprefix) { if (verbose) printf("%s: xattr '%s' is not supported.\n", e->hostname, xname); continue; } if ((enable_xattr & (1 << xprefix)) == 0) continue; value_len = lgetxattr(e->hostname, xname, xvalue, XATTR_BUFFER_SIZE); if (value_len < 0) { if (verbose) printf("lgetxattr('%s', '%s') = %d : %s\n", e->hostname, xname, errno, strerror(errno)); continue; } xe = find_xattr_entry(xprefix, xname + prefix_len, xvalue, value_len); if (!xe) { if (verbose) printf("%s : xattr '%s' was ignored.\n", e->hostname, xname); continue; } memset(&ref, 0, sizeof(ref)); ref.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ref.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); ref.totlen = cpu_to_je32(sizeof(ref)); ref.hdr_crc = cpu_to_je32(crc32(0, &ref, sizeof(struct jffs2_unknown_node) - 4)); ref.ino = cpu_to_je32(e->sb.st_ino); ref.xid = cpu_to_je32(xe->xid); ref.xseqno = cpu_to_je32(highest_xseqno += 2); ref.node_crc = cpu_to_je32(crc32(0, &ref, sizeof(ref) - 4)); pad_block_if_less_than(sizeof(ref)); full_write(out_fd, &ref, sizeof(ref)); padword(); } }
static int setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, const char *name, int fd) { ssize_t size; void *value = NULL; const char *accpath; accpath = archive_entry_sourcepath(entry); if (accpath == NULL) accpath = archive_entry_pathname(entry); #if HAVE_FGETXATTR if (fd >= 0) size = fgetxattr(fd, name, NULL, 0); else if (!a->follow_symlinks) size = lgetxattr(accpath, name, NULL, 0); else size = getxattr(accpath, name, NULL, 0); #elif HAVE_FGETEA if (fd >= 0) size = fgetea(fd, name, NULL, 0); else if (!a->follow_symlinks) size = lgetea(accpath, name, NULL, 0); else size = getea(accpath, name, NULL, 0); #endif if (size == -1) { archive_set_error(&a->archive, errno, "Couldn't query extended attribute"); return (ARCHIVE_WARN); } if (size > 0 && (value = malloc(size)) == NULL) { archive_set_error(&a->archive, errno, "Out of memory"); return (ARCHIVE_FATAL); } #if HAVE_FGETXATTR if (fd >= 0) size = fgetxattr(fd, name, value, size); else if (!a->follow_symlinks) size = lgetxattr(accpath, name, value, size); else size = getxattr(accpath, name, value, size); #elif HAVE_FGETEA if (fd >= 0) size = fgetea(fd, name, value, size); else if (!a->follow_symlinks) size = lgetea(accpath, name, value, size); else size = getea(accpath, name, value, size); #endif if (size == -1) { archive_set_error(&a->archive, errno, "Couldn't read extended attribute"); return (ARCHIVE_WARN); } archive_entry_xattr_add_entry(entry, name, value, size); free(value); return (ARCHIVE_OK); }
static int read_xattrs_from_system(char *filename, struct xattr_list **xattrs) { ssize_t size, vsize; char *xattr_names, *p; int i; struct xattr_list *xattr_list = NULL; #if 0 while(1) { size = llistxattr(filename, NULL, 0); if(size <= 0) { if(size < 0 && errno != ENOTSUP) ERROR("llistxattr for %s failed in read_attrs," " because %s\n", filename, strerror(errno)); return 0; } xattr_names = malloc(size); if(xattr_names == NULL) { ERROR("Out of memory in read_attrs\n"); return 0; } size = llistxattr(filename, xattr_names, size); if(size < 0) { free(xattr_names); if(errno == ERANGE) /* xattr list grew? Try again */ continue; else { ERROR("llistxattr for %s failed in read_attrs," " because %s\n", filename, strerror(errno)); return 0; } } break; } #else ERROR("llistxattr not available"); #endif for(i = 0, p = xattr_names; p < xattr_names + size; i++) { struct xattr_list *x = realloc(xattr_list, (i + 1) * sizeof(struct xattr_list)); if(x == NULL) { ERROR("Out of memory in read_attrs\n"); goto failed; } else xattr_list = x; xattr_list[i].type = get_prefix(&xattr_list[i], p); p += strlen(p) + 1; if(xattr_list[i].type == -1) { ERROR("Unrecognised xattr prefix %s\n", xattr_list[i].full_name); free(xattr_list[i].full_name); i--; continue; } #if 0 while(1) { vsize = lgetxattr(filename, xattr_list[i].full_name, NULL, 0); if(vsize < 0) { ERROR("lgetxattr failed for %s in read_attrs," " because %s\n", filename, strerror(errno)); free(xattr_list[i].full_name); goto failed; } xattr_list[i].value = malloc(vsize); if(xattr_list[i].value == NULL) { ERROR("Out of memory in read_attrs\n"); free(xattr_list[i].full_name); goto failed; } vsize = lgetxattr(filename, xattr_list[i].full_name, xattr_list[i].value, vsize); if(vsize < 0) { free(xattr_list[i].value); if(errno == ERANGE) /* xattr grew? Try again */ continue; else { ERROR("lgetxattr failed for %s in " "read_attrs, because %s\n", filename, strerror(errno)); free(xattr_list[i].full_name); goto failed; } } break; } #else ERROR("lgetxattr not supported"); #endif xattr_list[i].vsize = vsize; TRACE("read_xattrs_from_system: filename %s, xattr name %s," " vsize %d\n", filename, xattr_list[i].full_name, xattr_list[i].vsize); } free(xattr_names); *xattrs = xattr_list; return i; failed: while(--i >= 0) { free(xattr_list[i].full_name); free(xattr_list[i].value); } free(xattr_list); free(xattr_names); return 0; }
/* copy all extended attributes from op->operand to dest_path */ void DCOPY_copy_xattrs( mfu_flist flist, uint64_t idx, const char* dest_path) { #if DCOPY_USE_XATTRS /* get source file name */ const char* src_path = mfu_flist_file_get_name(flist, idx); /* start with a reasonable buffer, we'll allocate more as needed */ size_t list_bufsize = 1204; char* list = (char*) MFU_MALLOC(list_bufsize); /* get list, if list_size == ERANGE, try again */ ssize_t list_size; int got_list = 0; /* get current estimate for list size */ while(! got_list) { list_size = llistxattr(src_path, list, list_bufsize); if(list_size < 0) { if(errno == ERANGE) { /* buffer is too small, free our current buffer * and call it again with size==0 to get new size */ mfu_free(&list); list_bufsize = 0; } else if(errno == ENOTSUP) { /* this is common enough that we silently ignore it */ break; } else { /* this is a real error */ MFU_LOG(MFU_LOG_ERR, "Failed to get list of extended attributes on %s llistxattr() errno=%d %s", src_path, errno, strerror(errno) ); break; } } else { if(list_size > 0 && list_bufsize == 0) { /* called llistxattr with size==0 and got back positive * number indicating size of buffer we need to allocate */ list_bufsize = (size_t) list_size; list = (char*) MFU_MALLOC(list_bufsize); } else { /* got our list, it's size is in list_size, which may be 0 */ got_list = 1; } } } /* iterate over list and copy values to new object lgetxattr/lsetxattr */ if(got_list) { char* name = list; while(name < list + list_size) { /* start with a reasonable buffer, * allocate something bigger as needed */ size_t val_bufsize = 1024; void* val = (void*) MFU_MALLOC(val_bufsize); /* lookup value for name */ ssize_t val_size; int got_val = 0; while(! got_val) { val_size = lgetxattr(src_path, name, val, val_bufsize); if(val_size < 0) { if(errno == ERANGE) { /* buffer is too small, free our current buffer * and call it again with size==0 to get new size */ mfu_free(&val); val_bufsize = 0; } else if(errno == ENOATTR) { /* source object no longer has this attribute, * maybe deleted out from under us */ break; } else { /* this is a real error */ MFU_LOG(MFU_LOG_ERR, "Failed to get value for name=%s on %s llistxattr() errno=%d %s", name, src_path, errno, strerror(errno) ); break; } } else { if(val_size > 0 && val_bufsize == 0) { /* called lgetxattr with size==0 and got back positive * number indicating size of buffer we need to allocate */ val_bufsize = (size_t) val_size; val = (void*) MFU_MALLOC(val_bufsize); } else { /* got our value, it's size is in val_size, which may be 0 */ got_val = 1; } } } /* set attribute on destination object */ if(got_val) { int setrc = lsetxattr(dest_path, name, val, (size_t) val_size, 0); if(setrc != 0) { MFU_LOG(MFU_LOG_ERR, "Failed to set value for name=%s on %s llistxattr() errno=%d %s", name, dest_path, errno, strerror(errno) ); } } /* free value string */ mfu_free(&val); val_bufsize = 0; /* jump to next name */ size_t namelen = strlen(name) + 1; name += namelen; } } /* free space allocated for list */ mfu_free(&list); list_bufsize = 0; return; #endif /* DCOPY_USE_XATTR */ }