#include #include #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { int fd, fd2; char buf[512], *cp; ssize_t siz; off_t offs; struct dirent *dp; struct stat sb; long named_enabled; if (argc != 2) errx(1, "Usage: xattrtest "); if (getuid() == 0) errx(1, "Must be run as non-root"); named_enabled = pathconf(argv[1], _PC_NAMEDATTR_ENABLED); if (named_enabled <= 0) err(1, "Named attributes not enabled"); fd = open(argv[1], O_NAMEDATTR | O_CREAT, 0600); if (fd < 0) err(1, "can't open %s", argv[1]); printf("Open xattr successful\n"); siz = getdents(fd, buf, 512); if (siz < 0) err(1, "Cannot getdents"); cp = buf; while (cp < &buf[siz]) { dp = (struct dirent *)cp; printf("name=%s ino=%ld\n", dp->d_name, dp->d_ino); cp += dp->d_reclen; } if (fstat(fd, &sb) < 0) err(1, "Cannot stat attrdir"); printf("attrdir mode=0%o uid=%d gid=%d\n", sb.st_mode, sb.st_uid, sb.st_gid); fd2 = openat(fd, "def", O_CREAT | O_RDWR | O_NAMEDATTR, 0600); if (fd2 < 0) err(1, "can't openat def"); if (fstat(fd2, &sb) < 0) err(1, "can't stat def"); printf("def mode=0%o uid=%d gid=%d\n", sb.st_mode, sb.st_uid, sb.st_gid); siz = write(fd2, "xxxyyy", 6); if (siz != 6) err(1, "can't write xxxyyy"); offs = lseek(fd2, 0, SEEK_SET); if (offs != 0) err(1, "Can't lseek %ld", offs); siz = read(fd2, buf, 512); if (siz != 6) err(1, "Can't read xxxyyy"); buf[6] = '\0'; printf("got=%s\n", buf); if (fchmod(fd2, 0400) < 0) err(1, "Cannot fchmod def"); if (fstat(fd2, &sb) < 0) err(1, "can't stat def"); printf("def new mode=0%o\n", sb.st_mode); close(fd2); fd2 = openat(fd, "def", O_RDONLY | O_NAMEDATTR); if (fd2 < 0) err(1, "can't openat def for reading"); siz = read(fd2, buf, 512); if (siz != 6) err(1, "Can't read xxxyyy"); buf[6] = '\0'; printf("got=%s\n", buf); if (linkat(fd, "def", fd, "aaa", 0) >= 0) err(1, "link succeeded"); if (mkdirat(fd, "subdir", 0777) >= 0) err(1, "mkdir succeeded"); if (symlinkat("mysym", fd, "def") >= 0) err(1, "symlinkat succeeded"); close(fd2); if (renameat(fd, "def", fd, "abc") < 0) err(1, "Cannot rename def to abc"); printf("Renamed def to abc\n"); fd2 = openat(fd, "abc", O_RDWR | O_NAMEDATTR); if (fd2 >= 0) err(1, "Opened abc when it should not"); printf("Openat of abc failed as it should\n"); fd2 = openat(fd, "abc", O_RDONLY | O_NAMEDATTR); if (fd2 < 0) err(1, "Read-only openat of abc failed"); printf("Openat of abc read-only worked\n"); if (fchmod(fd2, 0600) < 0) err(1, "chmod of abc to 0600 failed"); printf("fchmod of abc to 0600 worked\n"); close(fd2); fd2 = openat(fd, "abc", O_RDWR | O_NAMEDATTR); if (fd2 < 0) err(1, "Cannot open abc rw"); printf("Did openat of abc rw\n"); close(fd2); if (unlinkat(fd, "abc", 0) < 0) err(1, "Cannot unlink abc"); printf("Unlinked abc\n"); fd2 = openat(fd, "abc", O_RDWR | O_NAMEDATTR); if (fd2 >= 0) err(1, "opened abc after unlink"); printf("Open of abc failed as it should\n"); offs = lseek(fd, 0, SEEK_SET); if (offs != 0) err(1, "Can't lseek %ld", offs); siz = getdents(fd, buf, 512); if (siz < 0) err(1, "Cannot getdents"); cp = buf; while (cp < &buf[siz]) { dp = (struct dirent *)cp; printf("name=%s\n", dp->d_name); cp += dp->d_reclen; } }