static void setup(void) { SAFE_TOUCH("testfile", 0644, NULL); SAFE_SYMLINK("testfile", "symlink"); set_xattr("testfile", SECURITY_KEY1); set_xattr("symlink", SECURITY_KEY2); }
static void test_xattr(struct xattrdata x) { size_t rlen=0; char metasymbol=META_XATTR; char *retrieved=NULL; const char *path=NULL; const char *myfile=BASE "/myfile"; char expected[256]; fail_unless(recursive_delete(BASE)==0); build_file(myfile, NULL); if(x.do_dir) path=BASE; else path=myfile; #if defined(HAVE_FREEBSD_OS) || \ defined(HAVE_NETBSD_OS) metasymbol=META_XATTR_BSD; #endif #if defined(HAVE_LINUX_OS) || \ defined(HAVE_DARWIN_OS) metasymbol=META_XATTR; #endif snprintf(expected, sizeof(expected), "%s", x.expected_read); expected[0]=metasymbol; fail_unless(has_xattr(path)==0); fail_unless(!set_xattr( NULL, // asfd path, x.write, strlen(x.write), metasymbol, NULL // cntr )); fail_unless(!get_xattr( NULL, // asfd path, &retrieved, &rlen, NULL // cntr )); fail_unless(rlen==strlen(expected)); assert_xattr(expected, retrieved, rlen); free_w(&retrieved); tear_down(); }
int set_extrameta(const char *path, char cmd, struct stat *statp, const char *extrameta, size_t metalen, struct cntr *cntr) { size_t l=0; char cmdtmp='\0'; unsigned int s=0; const char *metadata=NULL; int errors=0; metadata=extrameta; l=metalen; while(l>0) { char *m=NULL; if((sscanf(metadata, "%c%08X", &cmdtmp, &s))!=2) { logw(cntr, "sscanf of metadata failed for %s: %s\n", path, metadata); return -1; } metadata+=9; l-=9; if(!(m=(char *)malloc(s+1))) { logp("out of memory\n"); return -1; } memcpy(m, metadata, s); m[s]='\0'; metadata+=s; l-=s; switch(cmdtmp) { #if defined(HAVE_LINUX_OS) || \ defined(HAVE_FREEBSD_OS) || \ defined(HAVE_OPENBSD_OS) || \ defined(HAVE_NETBSD_OS) #ifdef HAVE_ACL case META_ACCESS_ACL: if(set_acl(path, statp, m, s, cmdtmp, cntr)) errors++; break; case META_DEFAULT_ACL: if(set_acl(path, statp, m, s, cmdtmp, cntr)) errors++; break; #endif #endif #if defined(HAVE_LINUX_OS) #ifdef HAVE_XATTR case META_XATTR: if(set_xattr(path, statp, m, s, cmdtmp, cntr)) errors++; break; #endif #endif #if defined(HAVE_FREEBSD_OS) || \ defined(HAVE_OPENBSD_OS) || \ defined(HAVE_NETBSD_OS) #ifdef HAVE_XATTR case META_XATTR_BSD: if(set_xattr(path, statp, m, s, cmdtmp, cntr)) errors++; break; #endif #endif default: logp("unknown metadata: %c\n", cmdtmp); logw(cntr, "unknown metadata: %c\n", cmdtmp); errors++; break; } free(m); } return errors; }
int main(int argc, char *argv[]) { unsigned abits = DATA_BTREE_BIT|CTIME_SIZE_BIT|MODE_OWNER_BIT|LINK_COUNT_BIT|MTIME_BIT; struct dev *dev = &(struct dev){ .bits = 8, .fd = open(argv[1], O_CREAT|O_RDWR, S_IRUSR|S_IWUSR) }; assert(!ftruncate(dev->fd, 1 << 24)); init_buffers(dev, 1 << 20, 0); struct sb *sb = rapid_sb(dev, .version = 0, .atomref_base = 1 << 10, .unatom_base = 1 << 11, .atomgen = 1); struct inode *inode = rapid_open_inode(sb, NULL, S_IFDIR | 0x666, .present = abits, .i_uid = 0x12121212, .i_gid = 0x34343434, .i_ctime = spectime(0xdec0debeadULL), .i_mtime = spectime(0xbadfaced00dULL)); inode->btree = (struct btree){ .root = { .block = 0xcaba1f00dULL, .depth = 3 } }; sb->atable = inode; for (int i = 0; i < 2; i++) { struct buffer_head *buffer = blockget(mapping(inode), tux_sb(inode->i_sb)->atomref_base + i); memset(bufdata(buffer), 0, sb->blocksize); blockput_dirty(buffer); } if (1) { warn("---- test positive and negative refcount carry ----"); use_atom(inode, 6, 1 << 15); use_atom(inode, 6, (1 << 15)); use_atom(inode, 6, -(1 << 15)); use_atom(inode, 6, -(1 << 15)); } warn("---- test atom table ----"); printf("atom = %Lx\n", (L)make_atom(inode, "foo", 3)); printf("atom = %Lx\n", (L)make_atom(inode, "foo", 3)); printf("atom = %Lx\n", (L)make_atom(inode, "bar", 3)); printf("atom = %Lx\n", (L)make_atom(inode, "foo", 3)); printf("atom = %Lx\n", (L)make_atom(inode, "bar", 3)); warn("---- test inode xattr cache ----"); int err; err = xcache_update(inode, 0x666, "hello", 5, 0); if (err) printf("err %d\n", err); err = xcache_update(inode, 0x777, "world!", 6, 0); if (err) printf("err %d\n", err); xcache_dump(inode); struct xattr *xattr = xcache_lookup(tux_inode(inode)->xcache, 0x777); if (!IS_ERR(xattr)) printf("atom %x => %.*s\n", xattr->atom, xattr->size, xattr->body); err = xcache_update(inode, 0x111, "class", 5, 0); if (err) printf("err %d\n", err); err = xcache_update(inode, 0x666, NULL, 0, 0); if (err) printf("err %d\n", err); err = xcache_update(inode, 0x222, "boooyah", 7, 0); if (err) printf("err %d\n", err); xcache_dump(inode); warn("---- test xattr inode table encode and decode ----"); char attrs[1000] = { }; char *top = encode_xattrs(inode, attrs, sizeof(attrs)); hexdump(attrs, top - attrs); printf("predicted size = %x, encoded size = %Lx\n", encode_xsize(inode), (L)(top - attrs)); inode->xcache->size = offsetof(struct xcache, xattrs); char *newtop = decode_attrs(inode, attrs, top - attrs); printf("predicted size = %x, xcache size = %x\n", decode_xsize(inode, attrs, top - attrs), inode->xcache->size); assert(top == newtop); xcache_dump(inode); free(inode->xcache); inode->xcache = NULL; warn("---- xattr update ----"); set_xattr(inode, "hello", 5, "world!", 6, 0); set_xattr(inode, "empty", 5, "zot", 0, 0); set_xattr(inode, "foo", 3, "foobar", 6, 0); xcache_dump(inode); warn("---- xattr remove ----"); // del_xattr(inode, "hello", 5); xcache_dump(inode); warn("---- xattr lookup ----"); for (int i = 0, len; i < 3; i++) { char *namelist[] = { "hello", "foo", "world" }, *name = namelist[i]; char data[100]; int size = get_xattr(inode, name, len = strlen(name), data, sizeof(data)); if (size < 0) printf("xattr %.*s not found (%s)\n", len, name, strerror(-size)); else printf("found xattr %.*s => %.*s\n", len, name, size, data); } warn("---- list xattrs ----"); int len = xattr_list(inode, attrs, sizeof(attrs)); printf("xattr list length = %i\n", xattr_list(inode, NULL, 0)); hexdump(attrs, len); warn("---- atom reverse map ----"); for (int i = 0; i < 5; i++) { unsigned atom = i, offset; struct buffer_head *buffer = blockread_unatom(inode, atom, &offset); loff_t where = from_be_u64(((be_u64 *)bufdata(buffer))[offset]); blockput_dirty(buffer); buffer = blockread(mapping(inode), where >> sb->blockbits); printf("atom %.3Lx at dirent %.4Lx, ", (L)atom, (L)where); hexdump(bufdata(buffer) + (where & sb->blockmask), 16); blockput(buffer); } warn("---- atom recycle ----"); set_xattr(inode, "hello", 5, NULL, 0, 0); show_freeatoms(sb); printf("got free atom %x\n", get_freeatom(inode)); printf("got free atom %x\n", get_freeatom(inode)); printf("got free atom %x\n", get_freeatom(inode)); warn("---- dump atom table ----"); dump_atoms(inode); show_buffers(inode->map); exit(0); }
int set_extrameta(struct asfd *asfd, BFILE *bfd, const char *path, struct sbuf *sb, const char *extrameta, size_t metalen, struct conf **confs) { size_t l=0; char cmdtmp='\0'; unsigned int s=0; const char *metadata=NULL; int errors=0; metadata=extrameta; l=metalen; while(l>0) { char *m=NULL; if((sscanf(metadata, "%c%08X", &cmdtmp, &s))!=2) { logw(asfd, confs, "sscanf of metadata failed for %s: %s\n", path, metadata); return -1; } metadata+=9; l-=9; if(!(m=(char *)malloc_w(s+1, __func__))) return -1; memcpy(m, metadata, s); m[s]='\0'; metadata+=s; l-=s; switch(cmdtmp) { #if defined(HAVE_WIN32) case META_VSS: if(set_vss(bfd, m, s, confs)) errors++; break; #endif #if defined(HAVE_LINUX_OS) || \ defined(HAVE_FREEBSD_OS) || \ defined(HAVE_OPENBSD_OS) || \ defined(HAVE_NETBSD_OS) #ifdef HAVE_ACL case META_ACCESS_ACL: if(set_acl(asfd, path, sb, m, s, cmdtmp, confs)) errors++; break; case META_DEFAULT_ACL: if(set_acl(asfd, path, sb, m, s, cmdtmp, confs)) errors++; break; #endif #endif #if defined(HAVE_LINUX_OS) #ifdef HAVE_XATTR case META_XATTR: if(set_xattr(asfd, path, sb, m, s, cmdtmp, confs)) errors++; break; #endif #endif #if defined(HAVE_FREEBSD_OS) || \ defined(HAVE_OPENBSD_OS) || \ defined(HAVE_NETBSD_OS) #ifdef HAVE_XATTR case META_XATTR_BSD: if(set_xattr(asfd, path, sb, m, s, cmdtmp, confs)) errors++; break; #endif #endif default: logp("unknown metadata: %c\n", cmdtmp); logw(asfd, confs, "unknown metadata: %c\n", cmdtmp); errors++; break; } free(m); } return errors; }