From 8d3743868ebce77fe03c5b1ff6435baa8d084293 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Wed, 3 Aug 2016 14:05:39 +0000 Subject: [PATCH] Fix printing of mode_t, umode_t, and umask types Print numeric umode_t type using %#03ho format. Print return value of umask syscall using %#03lo format. When printing symbolic mode_t type, always print lower 9 bits, and print the numeric part using %#03o format. * defs.h (sprintmode): Remove. (print_symbolic_mode_t, print_numeric_umode_t, print_numeric_long_umask): New prototypes. * printmode.c (sprintmode): Remove. (print_symbolic_mode_t, print_numeric_umode_t, print_numeric_long_umask): New functions. * chmod.c (decode_chmod): Use print_numeric_umode_t. * ipc_msg.c (SYS_FUNC(msgget)): Likewise. * ipc_msgctl.c (print_msqid_ds): Likewise. * ipc_sem.c (SYS_FUNC(semget)): Likewise. * ipc_shm.c (SYS_FUNC(shmget)): Likewise. * ipc_shmctl.c (print_shmid_ds): Likewise. * mq.c (SYS_FUNC(mq_open)): Likewise. * open.c (decode_open, SYS_FUNC(creat)): Likewise. * umask.c (SYS_FUNC(umask)): Likewise. * mknod.c (decode_mknod): Use print_symbolic_mode_t. * printstat.h (DO_PRINTSTAT): Likewise. * syscall.c (trace_syscall_exiting): Use print_numeric_long_umask. * tests/umode_t.c: New file. * tests/Makefile.am (EXTRA_DIST): Add it. * tests/creat.c: Rewrite as a thin wrapper around umode_t.c * tests/mkdir.c: Likewise. * tests/mkdirat.c: Likewise. * tests/mknod.c: Extend test coverage of mknod syscall. * tests/mknodat.c: Extend test coverage of mknodat syscall. * tests/umask.c: Extend test coverage of umask syscall. * tests/creat.test: Update the value specified for strace -a parameter. * tests/mkdir.test: Likewise. * tests/mkdirat.test: Likewise. * tests/mknodat.test: Likewise. --- chmod.c | 6 ++-- defs.h | 4 ++- ipc_msg.c | 2 +- ipc_msgctl.c | 2 +- ipc_sem.c | 2 +- ipc_shm.c | 2 +- ipc_shmctl.c | 2 +- mknod.c | 5 ++-- mq.c | 4 ++- open.c | 6 ++-- printmode.c | 53 ++++++++++++++++++++-------------- printstat.h | 28 +++++++++--------- syscall.c | 3 +- tests/Makefile.am | 1 + tests/creat.c | 18 ++---------- tests/creat.test | 2 +- tests/mkdir.c | 18 ++---------- tests/mkdir.test | 2 +- tests/mkdirat.c | 21 ++++---------- tests/mkdirat.test | 2 +- tests/mknod.c | 59 ++++++++++++++++++++++++------------- tests/mknodat.c | 63 ++++++++++++++++++++++++++++++++-------- tests/mknodat.test | 2 +- tests/umask.c | 16 +++++++++-- tests/umode_t.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++ umask.c | 2 +- 26 files changed, 264 insertions(+), 133 deletions(-) create mode 100644 tests/umode_t.c diff --git a/chmod.c b/chmod.c index 83741c9e..fd76490c 100644 --- a/chmod.c +++ b/chmod.c @@ -4,7 +4,8 @@ static void decode_chmod(struct tcb *tcp, const int offset) { printpath(tcp, tcp->u_arg[offset]); - tprintf(", %#lo", tcp->u_arg[offset + 1]); + tprints(", "); + print_numeric_umode_t(tcp->u_arg[offset + 1]); } SYS_FUNC(chmod) @@ -25,7 +26,8 @@ SYS_FUNC(fchmodat) SYS_FUNC(fchmod) { printfd(tcp, tcp->u_arg[0]); - tprintf(", %#lo", tcp->u_arg[1]); + tprints(", "); + print_numeric_umode_t(tcp->u_arg[1]); return RVAL_DECODED; } diff --git a/defs.h b/defs.h index 4b7e8edd..bfe76e2d 100644 --- a/defs.h +++ b/defs.h @@ -624,8 +624,10 @@ extern int printargs_d(struct tcb *); extern void addflags(const struct xlat *, uint64_t); extern int printflags64(const struct xlat *, uint64_t, const char *); extern const char *sprintflags(const char *, const struct xlat *, uint64_t); -extern const char *sprintmode(unsigned int); extern const char *sprinttime(time_t); +extern void print_symbolic_mode_t(unsigned int); +extern void print_numeric_umode_t(unsigned short); +extern void print_numeric_long_umask(unsigned long); extern void dumpiov_in_msghdr(struct tcb *, long, unsigned long); extern void dumpiov_in_mmsghdr(struct tcb *, long); extern void dumpiov_upto(struct tcb *, int, long, unsigned long); diff --git a/ipc_msg.c b/ipc_msg.c index daa00365..f04d14d7 100644 --- a/ipc_msg.c +++ b/ipc_msg.c @@ -50,7 +50,7 @@ SYS_FUNC(msgget) tprints("IPC_PRIVATE, "); if (printflags(resource_flags, tcp->u_arg[1] & ~0777, NULL) != 0) tprints("|"); - tprintf("%#lo", tcp->u_arg[1] & 0777); + print_numeric_umode_t(tcp->u_arg[1] & 0777); return RVAL_DECODED; } diff --git a/ipc_msgctl.c b/ipc_msgctl.c index e46f6e2e..9be35cef 100644 --- a/ipc_msgctl.c +++ b/ipc_msgctl.c @@ -67,7 +67,7 @@ print_msqid_ds(struct tcb *tcp, const long addr, int cmd) printuid("uid=", msqid_ds.msg_perm.uid); printuid(", gid=", msqid_ds.msg_perm.gid); tprints(", mode="); - tprints(sprintmode(msqid_ds.msg_perm.mode)); + print_numeric_umode_t(msqid_ds.msg_perm.mode); if (cmd != IPC_STAT) { tprints("}, ...}"); diff --git a/ipc_sem.c b/ipc_sem.c index ba21b7bb..bf82f330 100644 --- a/ipc_sem.c +++ b/ipc_sem.c @@ -108,7 +108,7 @@ SYS_FUNC(semget) tprintf(", %lu, ", tcp->u_arg[1]); if (printflags(resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0) tprints("|"); - tprintf("%#lo", tcp->u_arg[2] & 0777); + print_numeric_umode_t(tcp->u_arg[2] & 0777); return RVAL_DECODED; } diff --git a/ipc_shm.c b/ipc_shm.c index c418884a..b2059c2b 100644 --- a/ipc_shm.c +++ b/ipc_shm.c @@ -50,7 +50,7 @@ SYS_FUNC(shmget) tprintf(", %lu, ", tcp->u_arg[1]); if (printflags(shm_resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0) tprints("|"); - tprintf("%#lo", tcp->u_arg[2] & 0777); + print_numeric_umode_t(tcp->u_arg[2] & 0777); return RVAL_DECODED; } diff --git a/ipc_shmctl.c b/ipc_shmctl.c index 3498455d..7ea36729 100644 --- a/ipc_shmctl.c +++ b/ipc_shmctl.c @@ -67,7 +67,7 @@ print_shmid_ds(struct tcb *tcp, const long addr, int cmd) printuid("uid=", shmid_ds.shm_perm.uid); printuid(", gid=", shmid_ds.shm_perm.gid); tprints(", mode="); - tprints(sprintmode(shmid_ds.shm_perm.mode)); + print_numeric_umode_t(shmid_ds.shm_perm.mode); if (cmd != IPC_STAT) { tprints("}, ...}"); diff --git a/mknod.c b/mknod.c index d78fa07f..dbcffd7f 100644 --- a/mknod.c +++ b/mknod.c @@ -47,11 +47,12 @@ static void decode_mknod(struct tcb *tcp, int offset) { - int mode = tcp->u_arg[offset + 1]; + unsigned short mode = tcp->u_arg[offset + 1]; unsigned int dev; printpath(tcp, tcp->u_arg[offset]); - tprintf(", %s", sprintmode(mode)); + tprints(", "); + print_symbolic_mode_t(mode); switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: diff --git a/mq.c b/mq.c index e12eef7c..1df2aa1f 100644 --- a/mq.c +++ b/mq.c @@ -37,7 +37,9 @@ SYS_FUNC(mq_open) tprint_open_modes(tcp->u_arg[1]); if (tcp->u_arg[1] & O_CREAT) { /* mode */ - tprintf(", %#lo, ", tcp->u_arg[2]); + tprints(", "); + print_numeric_umode_t(tcp->u_arg[2]); + tprints(", "); printmqattr(tcp, tcp->u_arg[3]); } return RVAL_DECODED; diff --git a/open.c b/open.c index 90dd10fe..b712a229 100644 --- a/open.c +++ b/open.c @@ -124,7 +124,8 @@ decode_open(struct tcb *tcp, int offset) tprint_open_modes(tcp->u_arg[offset + 1]); if (tcp->u_arg[offset + 1] & O_CREAT) { /* mode */ - tprintf(", %#lo", tcp->u_arg[offset + 2]); + tprints(", "); + print_numeric_umode_t(tcp->u_arg[offset + 2]); } return RVAL_DECODED | RVAL_FD; @@ -144,7 +145,8 @@ SYS_FUNC(openat) SYS_FUNC(creat) { printpath(tcp, tcp->u_arg[0]); - tprintf(", %#lo", tcp->u_arg[1]); + tprints(", "); + print_numeric_umode_t(tcp->u_arg[1]); return RVAL_DECODED | RVAL_FD; } diff --git a/printmode.c b/printmode.c index ad875078..1babed6d 100644 --- a/printmode.c +++ b/printmode.c @@ -36,27 +36,38 @@ #include "xlat/modetypes.h" -const char * -sprintmode(unsigned int mode) +void +print_symbolic_mode_t(const unsigned int mode) { - static char buf[sizeof("S_IFSOCK|S_ISUID|S_ISGID|S_ISVTX|%o") - + sizeof(int)*3 - + /*paranoia:*/ 8]; - const char *s; - - if ((mode & S_IFMT) == 0) - s = ""; - else if ((s = xlookup(modetypes, mode & S_IFMT)) == NULL) { - sprintf(buf, "%#o", mode); - return buf; + const char *ifmt; + + if (mode & S_IFMT) { + ifmt = xlookup(modetypes, mode & S_IFMT); + if (!ifmt) { + tprintf("%#03o", mode); + return; + } + } else { + ifmt = NULL; } - s = buf + sprintf(buf, "%s%s%s%s", s, - (mode & S_ISUID) ? "|S_ISUID" : "", - (mode & S_ISGID) ? "|S_ISGID" : "", - (mode & S_ISVTX) ? "|S_ISVTX" : ""); - mode &= ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX); - if (mode) - sprintf((char*)s, "|%#o", mode); - s = (*buf == '|') ? buf + 1 : buf; - return *s ? s : "0"; + + tprintf("%s%s%s%s%s%#03o", + ifmt ? ifmt : "", + ifmt ? "|" : "", + (mode & S_ISUID) ? "S_ISUID|" : "", + (mode & S_ISGID) ? "S_ISGID|" : "", + (mode & S_ISVTX) ? "S_ISVTX|" : "", + mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX)); +} + +void +print_numeric_umode_t(const unsigned short mode) +{ + tprintf("%#03ho", mode); +} + +void +print_numeric_long_umask(const unsigned long mode) +{ + tprintf("%#03lo", mode); } diff --git a/printstat.h b/printstat.h index 5bf745c5..562d5cad 100644 --- a/printstat.h +++ b/printstat.h @@ -51,47 +51,49 @@ static void DO_PRINTSTAT(struct tcb *tcp, const STRUCT_STAT *statbuf) { + tprints("{"); if (!abbrev(tcp)) { - tprintf("{st_dev=makedev(%u, %u), st_ino=%llu, st_mode=%s, ", + tprintf("st_dev=makedev(%u, %u), st_ino=%llu, st_mode=", (unsigned int) STAT_MAJOR(statbuf->st_dev), (unsigned int) STAT_MINOR(statbuf->st_dev), - widen_to_ull(statbuf->st_ino), - sprintmode(statbuf->st_mode)); - tprintf("st_nlink=%u, st_uid=%u, st_gid=%u, ", + widen_to_ull(statbuf->st_ino)); + print_symbolic_mode_t(statbuf->st_mode); + tprintf(", st_nlink=%u, st_uid=%u, st_gid=%u", (unsigned int) statbuf->st_nlink, (unsigned int) statbuf->st_uid, (unsigned int) statbuf->st_gid); #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - tprintf("st_blksize=%u, ", (unsigned int) statbuf->st_blksize); + tprintf(", st_blksize=%u", (unsigned int) statbuf->st_blksize); #endif #ifdef HAVE_STRUCT_STAT_ST_BLOCKS - tprintf("st_blocks=%llu, ", widen_to_ull(statbuf->st_blocks)); + tprintf(", st_blocks=%llu", widen_to_ull(statbuf->st_blocks)); #endif } else { - tprintf("{st_mode=%s, ", sprintmode(statbuf->st_mode)); + tprints("st_mode="); + print_symbolic_mode_t(statbuf->st_mode); } switch (statbuf->st_mode & S_IFMT) { case S_IFCHR: case S_IFBLK: #ifdef HAVE_STRUCT_STAT_ST_RDEV - tprintf("st_rdev=makedev(%u, %u), ", + tprintf(", st_rdev=makedev(%u, %u)", (unsigned int) STAT_MAJOR(statbuf->st_rdev), (unsigned int) STAT_MINOR(statbuf->st_rdev)); #else /* !HAVE_STRUCT_STAT_ST_RDEV */ - tprintf("st_size=makedev(%u, %u), ", + tprintf(", st_size=makedev(%u, %u)", (unsigned int) STAT_MAJOR(statbuf->st_size), (unsigned int) STAT_MINOR(statbuf->st_size)); #endif /* !HAVE_STRUCT_STAT_ST_RDEV */ break; default: - tprintf("st_size=%llu, ", widen_to_ull(statbuf->st_size)); + tprintf(", st_size=%llu", widen_to_ull(statbuf->st_size)); break; } if (!abbrev(tcp)) { const bool cast = sizeof(statbuf->st_atime) == sizeof(int); - tprints("st_atime="); + tprints(", st_atime="); tprints(sprinttime(cast ? (time_t) (int) statbuf->st_atime: (time_t) statbuf->st_atime)); #ifdef HAVE_STRUCT_STAT_ST_ATIME_NSEC @@ -122,10 +124,10 @@ DO_PRINTSTAT(struct tcb *tcp, const STRUCT_STAT *statbuf) #ifdef HAVE_STRUCT_STAT_ST_GEN tprintf(", st_gen=%u", (unsigned int) statbuf->st_gen); #endif - tprints("}"); } else { - tprints("...}"); + tprints(", ..."); } + tprints("}"); } #undef STAT_MINOR diff --git a/syscall.c b/syscall.c index 6af0dec0..e5ac7db5 100644 --- a/syscall.c +++ b/syscall.c @@ -1040,7 +1040,8 @@ trace_syscall_exiting(struct tcb *tcp) tprintf("= %#lx", tcp->u_rval); break; case RVAL_OCTAL: - tprintf("= %#lo", tcp->u_rval); + tprints("= "); + print_numeric_long_umask(tcp->u_rval); break; case RVAL_UDECIMAL: #if SUPPORTED_PERSONALITIES > 1 diff --git a/tests/Makefile.am b/tests/Makefile.am index 69b69065..3fa3b3b0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -759,6 +759,7 @@ EXTRA_DIST = init.sh run.sh match.awk \ struct_flock.c \ sun_path.expected \ uio.expected \ + umode_t.c \ umovestr.expected \ unix-pair-send-recv.expected \ unix-pair-sendto-recvfrom.expected \ diff --git a/tests/creat.c b/tests/creat.c index 8572e7f4..89fcef9b 100644 --- a/tests/creat.c +++ b/tests/creat.c @@ -3,21 +3,9 @@ #ifdef __NR_creat -# include -# include - -# define TMP_FILE "creat" - -int -main(void) -{ - long rc = syscall(__NR_creat, TMP_FILE, 0400); - printf("creat(\"%s\", %#o) = %ld %s (%m)\n", - TMP_FILE, 0400, rc, errno2name()); - - puts("+++ exited with 0 +++"); - return 0; -} +# define TEST_SYSCALL_NR __NR_creat +# define TEST_SYSCALL_STR "creat" +# include "umode_t.c" #else diff --git a/tests/creat.test b/tests/creat.test index 49fddd21..069648f7 100755 --- a/tests/creat.test +++ b/tests/creat.test @@ -3,4 +3,4 @@ # Check creat syscall decoding. . "${srcdir=.}/init.sh" -run_strace_match_diff -a21 +run_strace_match_diff -a20 diff --git a/tests/mkdir.c b/tests/mkdir.c index dbb43c3b..79fe94f1 100644 --- a/tests/mkdir.c +++ b/tests/mkdir.c @@ -3,21 +3,9 @@ #ifdef __NR_mkdir -# include -# include - -int -main(void) -{ - static const char sample[] = "mkdir"; - - long rc = syscall(__NR_mkdir, sample, 0600); - printf("mkdir(\"%s\", 0600) = %ld %s (%m)\n", - sample, rc, errno2name()); - - puts("+++ exited with 0 +++"); - return 0; -} +# define TEST_SYSCALL_NR __NR_mkdir +# define TEST_SYSCALL_STR "mkdir" +# include "umode_t.c" #else diff --git a/tests/mkdir.test b/tests/mkdir.test index 98d5a526..38ed6928 100755 --- a/tests/mkdir.test +++ b/tests/mkdir.test @@ -3,4 +3,4 @@ # Check mkdir syscall decoding. . "${srcdir=.}/init.sh" -run_strace_match_diff -a21 +run_strace_match_diff -a20 diff --git a/tests/mkdirat.c b/tests/mkdirat.c index cbdf16c5..fc2732d0 100644 --- a/tests/mkdirat.c +++ b/tests/mkdirat.c @@ -3,22 +3,11 @@ #ifdef __NR_mkdirat -# include -# include - -int -main(void) -{ - static const char sample[] = "mkdirat.sample"; - const long fd = (long) 0xdeadbeefffffffff; - - long rc = syscall(__NR_mkdirat, fd, sample, 0600); - printf("mkdirat(%d, \"%s\", 0600) = %ld %s (%m)\n", - (int) fd, sample, rc, errno2name()); - - puts("+++ exited with 0 +++"); - return 0; -} +# define TEST_SYSCALL_NR __NR_mkdirat +# define TEST_SYSCALL_STR "mkdirat" +# define TEST_SYSCALL_PREFIX_ARGS (long int) 0xdeadbeefffffffff, +# define TEST_SYSCALL_PREFIX_STR "-1, " +# include "umode_t.c" #else diff --git a/tests/mkdirat.test b/tests/mkdirat.test index e41ce357..0fcb841a 100755 --- a/tests/mkdirat.test +++ b/tests/mkdirat.test @@ -3,4 +3,4 @@ # Check mkdirat syscall decoding. . "${srcdir=.}/init.sh" -run_strace_match_diff -a36 +run_strace_match_diff -a28 diff --git a/tests/mknod.c b/tests/mknod.c index 91ce751e..4847f32a 100644 --- a/tests/mknod.c +++ b/tests/mknod.c @@ -14,38 +14,57 @@ # include # endif -# define TMP_FILE "mknod" +static const char sample[] = "mknod"; + +static long +call_mknod(unsigned short mode, unsigned long dev) +{ + unsigned long lmode = (unsigned long) 0xffffffffffff0000 | mode; + return syscall(__NR_mknod, sample, lmode, dev); +} int main(void) { - long rc = syscall(__NR_mknod, TMP_FILE, 0, 0xdeadbeef); - printf("mknod(\"%s\", 0) = %ld %s (%m)\n", - TMP_FILE, rc, errno2name()); + unsigned long dev = (unsigned long) 0xdeadbeefbadc0ded; + + long rc = call_mknod(0, dev); + printf("mknod(\"%s\", 000) = %ld %s (%m)\n", + sample, rc, errno2name()); + + rc = call_mknod(0xffff, dev); + printf("mknod(\"%s\", %#03ho) = %ld %s (%m)\n", + sample, (unsigned short) -1, rc, errno2name()); + + rc = call_mknod(S_IFREG, 0); + printf("mknod(\"%s\", S_IFREG|000) = %ld %s (%m)\n", + sample, rc, errno2name()); + + rc = call_mknod(S_IFDIR | 06, 0); + printf("mknod(\"%s\", S_IFDIR|006) = %ld %s (%m)\n", + sample, rc, errno2name()); - rc = syscall(__NR_mknod, TMP_FILE, -1L, 0xdeadbeef); - printf("mknod(\"%s\", %#o) = %ld %s (%m)\n", - TMP_FILE, -1, rc, errno2name()); + rc = call_mknod(S_IFLNK | 060, 0); + printf("mknod(\"%s\", S_IFLNK|060) = %ld %s (%m)\n", + sample, rc, errno2name()); - rc = syscall(__NR_mknod, TMP_FILE, S_IFREG|0600, 0); - printf("mknod(\"%s\", S_IFREG|0600) = %ld %s (%m)\n", - TMP_FILE, rc, errno2name()); + rc = call_mknod(S_IFIFO | 0600, 0); + printf("mknod(\"%s\", S_IFIFO|0600) = %ld %s (%m)\n", + sample, rc, errno2name()); - unsigned long dev = - (unsigned long) 0xdeadbeef00000000 | makedev(1, 7); + dev = (unsigned long) 0xdeadbeef00000000 | makedev(1, 7); - rc = syscall(__NR_mknod, TMP_FILE, S_IFCHR | 0400, dev); - printf("mknod(\"%s\", S_IFCHR|0400, makedev(1, 7)) = %ld %s (%m)\n", - TMP_FILE, rc, errno2name()); + rc = call_mknod(S_IFCHR | 024, dev); + printf("mknod(\"%s\", S_IFCHR|024, makedev(1, 7)) = %ld %s (%m)\n", + sample, rc, errno2name()); - const unsigned long mode = - ((unsigned long) 0xfacefeedffffffff & ~S_IFMT) | S_IFBLK; + const unsigned short mode = (0xffff & ~S_IFMT) | S_IFBLK; dev = (unsigned long) 0xdeadbeefbadc0ded; - rc = syscall(__NR_mknod, TMP_FILE, mode, dev); - printf("mknod(\"%s\", S_IFBLK|S_ISUID|S_ISGID|S_ISVTX|%#o" + rc = call_mknod(mode, dev); + printf("mknod(\"%s\", S_IFBLK|S_ISUID|S_ISGID|S_ISVTX|%#03ho" ", makedev(%u, %u)) = %ld %s (%m)\n", - TMP_FILE, (unsigned) mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX), + sample, mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX), major((unsigned) dev), minor((unsigned) dev), rc, errno2name()); diff --git a/tests/mknodat.c b/tests/mknodat.c index 2cdc47cf..991bc4b2 100644 --- a/tests/mknodat.c +++ b/tests/mknodat.c @@ -14,21 +14,60 @@ # include # endif +static const char sample[] = "mknodat_sample"; +static const long int fd = (long int) 0xdeadbeefffffffff; + +static long +call_mknodat(unsigned short mode, unsigned long dev) +{ + unsigned long lmode = (unsigned long) 0xffffffffffff0000 | mode; + return syscall(__NR_mknodat, fd, sample, lmode, dev); +} + int main(void) { - static const char sample[] = "mknokat_sample"; - const long int fd = (long int) 0xdeadbeefffffffff; - long rc = syscall(__NR_mknodat, fd, sample, S_IFREG|0600, 0); - printf("mknodat(%d, \"%s\", S_IFREG|0600) = %ld %s (%m)\n", - (int) fd, sample, rc, errno2name()); - - const unsigned long dev = - (unsigned long) 0xdeadbeef00000000 | makedev(1, 7); - - rc = syscall(__NR_mknodat, fd, sample, S_IFCHR | 0400, dev); - printf("mknodat(%d, \"%s\", S_IFCHR|0400, makedev(1, 7)) = %ld %s (%m)\n", - (int) fd, sample, rc, errno2name()); + unsigned long dev = (unsigned long) 0xdeadbeefbadc0ded; + + long rc = call_mknodat(0, dev); + printf("mknodat(-1, \"%s\", 000) = %ld %s (%m)\n", + sample, rc, errno2name()); + + rc = call_mknodat(0xffff, dev); + printf("mknodat(-1, \"%s\", %#03ho) = %ld %s (%m)\n", + sample, (unsigned short) -1, rc, errno2name()); + + rc = call_mknodat(S_IFREG, 0); + printf("mknodat(-1, \"%s\", S_IFREG|000) = %ld %s (%m)\n", + sample, rc, errno2name()); + + rc = call_mknodat(S_IFDIR | 06, 0); + printf("mknodat(-1, \"%s\", S_IFDIR|006) = %ld %s (%m)\n", + sample, rc, errno2name()); + + rc = call_mknodat(S_IFLNK | 060, 0); + printf("mknodat(-1, \"%s\", S_IFLNK|060) = %ld %s (%m)\n", + sample, rc, errno2name()); + + rc = call_mknodat(S_IFIFO | 0600, 0); + printf("mknodat(-1, \"%s\", S_IFIFO|0600) = %ld %s (%m)\n", + sample, rc, errno2name()); + + dev = (unsigned long) 0xdeadbeef00000000 | makedev(1, 7); + + rc = call_mknodat(S_IFCHR | 024, dev); + printf("mknodat(-1, \"%s\", S_IFCHR|024, makedev(1, 7)) = %ld %s (%m)\n", + sample, rc, errno2name()); + + const unsigned short mode = (0xffff & ~S_IFMT) | S_IFBLK; + dev = (unsigned long) 0xdeadbeefbadc0ded; + + rc = call_mknodat(mode, dev); + printf("mknodat(-1, \"%s\", S_IFBLK|S_ISUID|S_ISGID|S_ISVTX|%#03ho" + ", makedev(%u, %u)) = %ld %s (%m)\n", + sample, mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX), + major((unsigned) dev), minor((unsigned) dev), + rc, errno2name()); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/mknodat.test b/tests/mknodat.test index edf0498b..1701a368 100755 --- a/tests/mknodat.test +++ b/tests/mknodat.test @@ -3,4 +3,4 @@ # Check mknodat syscall decoding. . "${srcdir=.}/init.sh" -run_strace_match_diff +run_strace_match_diff -a35 diff --git a/tests/umask.c b/tests/umask.c index 2dcea283..86903a95 100644 --- a/tests/umask.c +++ b/tests/umask.c @@ -1,11 +1,23 @@ #include #include +void +test_umask(const mode_t mode) +{ + mode_t rc = umask(0xffff0000 | mode); + printf("umask(%#03ho) = %#03o\n", (unsigned short) mode, rc); +} + int main(void) { - mode_t rc = umask(044); - printf("umask(%#o) = %#o\n", 044, rc); + test_umask(0); + test_umask(06); + test_umask(026); + test_umask(0126); + test_umask(07777); + test_umask(0107777); + test_umask(-1); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/umode_t.c b/tests/umode_t.c new file mode 100644 index 00000000..e9ece4bc --- /dev/null +++ b/tests/umode_t.c @@ -0,0 +1,72 @@ +/* + * Check decoding of umode_t type syscall arguments. + * + * Copyright (c) 2016 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#ifndef TEST_SYSCALL_PREFIX_ARGS +# define TEST_SYSCALL_PREFIX_ARGS +#endif +#ifndef TEST_SYSCALL_PREFIX_STR +# define TEST_SYSCALL_PREFIX_STR "" +#endif + +static const char sample[] = TEST_SYSCALL_STR; + +static void +test_syscall(unsigned short mode) +{ + unsigned long lmode = (unsigned long) 0xffffffffffff0000 | mode; + long rc = syscall(TEST_SYSCALL_NR, TEST_SYSCALL_PREFIX_ARGS + sample, lmode); + + printf("%s(%s\"%s\", %#03ho) = %ld %s (%m)\n", + sample, TEST_SYSCALL_PREFIX_STR, sample, mode, rc, errno2name()); +} + +int +main(void) +{ + test_syscall(0); + test_syscall(0xffff); + test_syscall(06); + test_syscall(060); + test_syscall(0600); + test_syscall(024); + test_syscall(S_IFREG); + test_syscall(S_IFDIR | 06); + test_syscall(S_IFLNK | 060); + test_syscall(S_IFIFO | 0600); + test_syscall(S_IFCHR | 024); + test_syscall((0xffff & ~S_IFMT) | S_IFBLK); + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/umask.c b/umask.c index dda40d4a..d42258a9 100644 --- a/umask.c +++ b/umask.c @@ -2,7 +2,7 @@ SYS_FUNC(umask) { - tprintf("%#lo", tcp->u_arg[0]); + print_numeric_umode_t(tcp->u_arg[0]); return RVAL_DECODED | RVAL_OCTAL; } -- 2.40.0