summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2011-03-10 21:00:30 +0000
committerpjd <pjd@FreeBSD.org>2011-03-10 21:00:30 +0000
commitf132b5f04d08a6d87e6c021802b3f2f5712c48ca (patch)
tree6245df65e04a2dbf41b8f82228b4d494c72cc6e0 /tools
parent5f0f37248d768af1e7c674a5f4e49cd844e96d4e (diff)
downloadFreeBSD-src-f132b5f04d08a6d87e6c021802b3f2f5712c48ca.zip
FreeBSD-src-f132b5f04d08a6d87e6c021802b3f2f5712c48ca.tar.gz
Add support for *at syscalls:
- openat(2) - unlinkat(2) - mkdirat(2) - linkat(2) - symlinkat(2) - renameat(2) - mkfifoat(2) - mknodat(2) - fchmodat(2) - fchownat(2) - fstatat(2)
Diffstat (limited to 'tools')
-rw-r--r--tools/regression/pjdfstest/pjdfstest.c198
1 files changed, 173 insertions, 25 deletions
diff --git a/tools/regression/pjdfstest/pjdfstest.c b/tools/regression/pjdfstest/pjdfstest.c
index db3bc55..d1627eb 100644
--- a/tools/regression/pjdfstest/pjdfstest.c
+++ b/tools/regression/pjdfstest/pjdfstest.c
@@ -64,15 +64,23 @@
enum action {
ACTION_OPEN,
+ ACTION_OPENAT,
ACTION_CREATE,
ACTION_UNLINK,
+ ACTION_UNLINKAT,
ACTION_MKDIR,
+ ACTION_MKDIRAT,
ACTION_RMDIR,
ACTION_LINK,
+ ACTION_LINKAT,
ACTION_SYMLINK,
+ ACTION_SYMLINKAT,
ACTION_RENAME,
+ ACTION_RENAMEAT,
ACTION_MKFIFO,
+ ACTION_MKFIFOAT,
ACTION_MKNOD,
+ ACTION_MKNODAT,
ACTION_BIND,
ACTION_CONNECT,
ACTION_CHMOD,
@@ -80,9 +88,11 @@ enum action {
#ifdef HAS_LCHMOD
ACTION_LCHMOD,
#endif
+ ACTION_FCHMODAT,
ACTION_CHOWN,
ACTION_FCHOWN,
ACTION_LCHOWN,
+ ACTION_FCHOWNAT,
#ifdef HAS_CHFLAGS
ACTION_CHFLAGS,
#endif
@@ -97,6 +107,7 @@ enum action {
ACTION_STAT,
ACTION_FSTAT,
ACTION_LSTAT,
+ ACTION_FSTATAT,
ACTION_PATHCONF,
ACTION_FPATHCONF,
ACTION_LPATHCONF,
@@ -110,6 +121,8 @@ enum action {
#define TYPE_NONE 0x0000
#define TYPE_STRING 0x0001
#define TYPE_NUMBER 0x0002
+#define TYPE_DESCRIPTOR 0x0003
+#define TYPE_MASK 0x000f
#define TYPE_OPTIONAL 0x0100
@@ -123,47 +136,58 @@ struct syscall_desc {
static struct syscall_desc syscalls[] = {
{ "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
+ { "openat", ACTION_OPENAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
{ "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
{ "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } },
+ { "unlinkat", ACTION_UNLINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
+ { "mkdirat", ACTION_MKDIRAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
{ "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } },
{ "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "linkat", ACTION_LINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "symlinkat", ACTION_SYMLINKAT, { TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
{ "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "renameat", ACTION_RENAMEAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
{ "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
+ { "mkfifoat", ACTION_MKFIFOAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
{ "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
+ { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
{ "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } },
{ "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } },
{ "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
- { "fchmod", ACTION_FCHMOD, { TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
+ { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
#ifdef HAS_LCHMOD
{ "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
#endif
+ { "fchmodat", ACTION_FCHMODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
{ "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
- { "fchown", ACTION_FCHOWN, { TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
+ { "fchown", ACTION_FCHOWN, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
{ "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
+ { "fchownat", ACTION_FCHOWNAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
#ifdef HAS_CHFLAGS
{ "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
#endif
#ifdef HAS_FCHFLAGS
- { "fchflags", ACTION_FCHFLAGS, { TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
+ { "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
#endif
#ifdef HAS_LCHFLAGS
{ "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
#endif
{ "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
- { "ftruncate", ACTION_FTRUNCATE, { TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
+ { "ftruncate", ACTION_FTRUNCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
{ "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
- { "fstat", ACTION_FSTAT, { TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
+ { "fstat", ACTION_FSTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
{ "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+ { "fstatat", ACTION_FSTATAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
- { "fpathconf", ACTION_FPATHCONF, { TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
+ { "fpathconf", ACTION_FPATHCONF, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
{ "lpathconf", ACTION_LPATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
#ifdef HAS_FREEBSD_ACL
{ "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } },
#endif
- { "write", ACTION_WRITE, { TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
+ { "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
{ NULL, -1, { TYPE_NONE } }
};
@@ -218,6 +242,9 @@ static struct flag open_flags[] = {
#ifdef O_NOCTTY
{ O_NOCTTY, "O_NOCTTY" },
#endif
+#ifdef O_DIRECTORY
+ { O_DIRECTORY, "O_DIRECTORY" },
+#endif
{ 0, NULL }
};
@@ -257,6 +284,31 @@ static struct flag chflags_flags[] = {
};
#endif
+static struct flag unlinkat_flags[] = {
+ { AT_REMOVEDIR, "AT_REMOVEDIR" },
+ { 0, NULL }
+};
+
+static struct flag linkat_flags[] = {
+ { AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" },
+ { 0, NULL }
+};
+
+static struct flag fchmodat_flags[] = {
+ { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
+ { 0, NULL }
+};
+
+static struct flag fchownat_flags[] = {
+ { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
+ { 0, NULL }
+};
+
+static struct flag fstatat_flags[] = {
+ { AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
+ { 0, NULL }
+};
+
struct name {
int n_name;
char *n_str;
@@ -499,19 +551,38 @@ call_syscall(struct syscall_desc *scall, char *argv[])
fprintf(stderr, "too few arguments\n");
exit(1);
}
- if (scall->sd_args[i] & TYPE_STRING) {
+ if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
if (strcmp(argv[i], "NULL") == 0)
args[i].str = NULL;
else if (strcmp(argv[i], "DEADCODE") == 0)
args[i].str = (void *)0xdeadc0de;
else
args[i].str = argv[i];
- } else if (scall->sd_args[i] & TYPE_NUMBER) {
+ } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_NUMBER) {
args[i].num = strtoll(argv[i], &endp, 0);
if (*endp != '\0' && !isspace((unsigned char)*endp)) {
fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp);
exit(1);
}
+ } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_DESCRIPTOR) {
+ if (strcmp(argv[i], "AT_FDCWD") == 0) {
+ args[i].num = AT_FDCWD;
+ } else if (strcmp(argv[i], "BADFD") == 0) {
+ /* In case AT_FDCWD is -1 on some systems... */
+ if (AT_FDCWD == -1)
+ args[i].num = -2;
+ else
+ args[i].num = -1;
+ } else {
+ int pos;
+
+ pos = strtoll(argv[i], &endp, 0);
+ if (*endp != '\0' && !isspace((unsigned char)*endp)) {
+ fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp);
+ exit(1);
+ }
+ args[i].num = descriptor_get(pos);
+ }
}
}
}
@@ -520,7 +591,6 @@ call_syscall(struct syscall_desc *scall, char *argv[])
*/
#define NUM(n) (args[(n)].num)
#define STR(n) (args[(n)].str)
-#define DESC(n) (descriptor_get((int)NUM(n)))
switch (scall->sd_action) {
case ACTION_OPEN:
flags = str2flags(open_flags, STR(1));
@@ -540,6 +610,24 @@ call_syscall(struct syscall_desc *scall, char *argv[])
if (rval >= 0)
descriptor_add(rval);
break;
+ case ACTION_OPENAT:
+ flags = str2flags(open_flags, STR(2));
+ if (flags & O_CREAT) {
+ if (i == 3) {
+ fprintf(stderr, "too few arguments\n");
+ exit(1);
+ }
+ rval = openat(NUM(0), STR(1), (int)flags, (mode_t)NUM(3));
+ } else {
+ if (i == 4) {
+ fprintf(stderr, "too many arguments\n");
+ exit(1);
+ }
+ rval = openat(NUM(0), STR(1), (int)flags);
+ }
+ if (rval >= 0)
+ descriptor_add(rval);
+ break;
case ACTION_CREATE:
rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
if (rval >= 0)
@@ -548,45 +636,87 @@ call_syscall(struct syscall_desc *scall, char *argv[])
case ACTION_UNLINK:
rval = unlink(STR(0));
break;
+ case ACTION_UNLINKAT:
+ rval = unlinkat(NUM(0), STR(1),
+ (int)str2flags(unlinkat_flags, STR(2)));
+ break;
case ACTION_MKDIR:
rval = mkdir(STR(0), (mode_t)NUM(1));
break;
+ case ACTION_MKDIRAT:
+ rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
+ break;
case ACTION_RMDIR:
rval = rmdir(STR(0));
break;
case ACTION_LINK:
rval = link(STR(0), STR(1));
break;
+ case ACTION_LINKAT:
+ rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
+ (int)str2flags(linkat_flags, STR(4)));
+ break;
case ACTION_SYMLINK:
rval = symlink(STR(0), STR(1));
break;
+ case ACTION_SYMLINKAT:
+ rval = symlinkat(STR(0), NUM(1), STR(2));
+ break;
case ACTION_RENAME:
rval = rename(STR(0), STR(1));
break;
+ case ACTION_RENAMEAT:
+ rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
+ break;
case ACTION_MKFIFO:
rval = mkfifo(STR(0), (mode_t)NUM(1));
break;
+ case ACTION_MKFIFOAT:
+ rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
+ break;
case ACTION_MKNOD:
+ case ACTION_MKNODAT:
{
mode_t ntype;
dev_t dev;
+ int fa;
+
+ switch (scall->sd_action) {
+ case ACTION_MKNOD:
+ fa = 0;
+ break;
+ case ACTION_MKNODAT:
+ fa = 1;
+ break;
+ default:
+ abort();
+ }
- dev = makedev(NUM(3), NUM(4));
- if (strcmp(STR(1), "c") == 0) /* character device */
+ dev = makedev(NUM(fa + 3), NUM(fa + 4));
+ if (strcmp(STR(fa + 1), "c") == 0) /* character device */
ntype = S_IFCHR;
- else if (strcmp(STR(1), "b") == 0) /* block device */
+ else if (strcmp(STR(fa + 1), "b") == 0) /* block device */
ntype = S_IFBLK;
- else if (strcmp(STR(1), "f") == 0) /* fifo special */
+ else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */
ntype = S_IFIFO;
- else if (strcmp(STR(1), "d") == 0) /* directory */
+ else if (strcmp(STR(fa + 1), "d") == 0) /* directory */
ntype = S_IFDIR;
- else if (strcmp(STR(1), "o") == 0) /* regular file */
+ else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */
ntype = S_IFREG;
else {
fprintf(stderr, "wrong argument 1\n");
exit(1);
}
- rval = mknod(STR(0), ntype | NUM(2), dev);
+ switch (scall->sd_action) {
+ case ACTION_MKNOD:
+ rval = mknod(STR(0), ntype | NUM(2), dev);
+ break;
+ case ACTION_MKNODAT:
+ rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
+ break;
+ default:
+ abort();
+ }
break;
}
case ACTION_BIND:
@@ -619,30 +749,40 @@ call_syscall(struct syscall_desc *scall, char *argv[])
rval = chmod(STR(0), (mode_t)NUM(1));
break;
case ACTION_FCHMOD:
- rval = fchmod(DESC(0), (mode_t)NUM(1));
+ rval = fchmod(NUM(0), (mode_t)NUM(1));
break;
#ifdef HAS_LCHMOD
case ACTION_LCHMOD:
rval = lchmod(STR(0), (mode_t)NUM(1));
break;
#endif
+ case ACTION_FCHMODAT:
+ rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
+ str2flags(fchmodat_flags, STR(3)));
+ break;
case ACTION_CHOWN:
rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
break;
case ACTION_FCHOWN:
- rval = fchown(DESC(0), (uid_t)NUM(1), (gid_t)NUM(2));
+ rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
break;
case ACTION_LCHOWN:
rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
break;
+ case ACTION_FCHOWNAT:
+ rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
+ (int)str2flags(fchownat_flags, STR(4)));
+ break;
#ifdef HAS_CHFLAGS
case ACTION_CHFLAGS:
- rval = chflags(STR(0), (unsigned long)str2flags(chflags_flags, STR(1)));
+ rval = chflags(STR(0),
+ (unsigned long)str2flags(chflags_flags, STR(1)));
break;
#endif
#ifdef HAS_FCHFLAGS
case ACTION_FCHFLAGS:
- rval = fchflags(DESC(0), (unsigned long)str2flags(chflags_flags, STR(1)));
+ rval = fchflags(NUM(0),
+ (unsigned long)str2flags(chflags_flags, STR(1)));
break;
#endif
#ifdef HAS_LCHFLAGS
@@ -654,7 +794,7 @@ call_syscall(struct syscall_desc *scall, char *argv[])
rval = truncate64(STR(0), NUM(1));
break;
case ACTION_FTRUNCATE:
- rval = ftruncate64(DESC(0), NUM(1));
+ rval = ftruncate64(NUM(0), NUM(1));
break;
case ACTION_STAT:
rval = stat64(STR(0), &sb);
@@ -664,7 +804,7 @@ call_syscall(struct syscall_desc *scall, char *argv[])
}
break;
case ACTION_FSTAT:
- rval = fstat64(DESC(0), &sb);
+ rval = fstat64(NUM(0), &sb);
if (rval == 0) {
show_stats(&sb, STR(1));
return (i);
@@ -677,6 +817,14 @@ call_syscall(struct syscall_desc *scall, char *argv[])
return (i);
}
break;
+ case ACTION_FSTATAT:
+ rval = fstatat(NUM(0), STR(1), &sb,
+ (int)str2flags(fstatat_flags, STR(2)));
+ if (rval == 0) {
+ show_stats(&sb, STR(3));
+ return (i);
+ }
+ break;
case ACTION_PATHCONF:
case ACTION_FPATHCONF:
case ACTION_LPATHCONF:
@@ -694,7 +842,7 @@ call_syscall(struct syscall_desc *scall, char *argv[])
lrval = pathconf(STR(0), name);
break;
case ACTION_FPATHCONF:
- lrval = fpathconf(DESC(0), name);
+ lrval = fpathconf(NUM(0), name);
break;
case ACTION_LPATHCONF:
lrval = lpathconf(STR(0), name);
@@ -745,7 +893,7 @@ call_syscall(struct syscall_desc *scall, char *argv[])
break;
#endif
case ACTION_WRITE:
- rval = write(DESC(0), STR(1), strlen(STR(1)));
+ rval = write(NUM(0), STR(1), strlen(STR(1)));
break;
default:
fprintf(stderr, "unsupported syscall\n");
OpenPOWER on IntegriCloud