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.
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)
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;
}
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);
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;
}
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("}, ...}");
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;
}
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;
}
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("}, ...}");
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:
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;
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;
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;
}
#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);
}
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
#ifdef HAVE_STRUCT_STAT_ST_GEN
tprintf(", st_gen=%u", (unsigned int) statbuf->st_gen);
#endif
- tprints("}");
} else {
- tprints("...}");
+ tprints(", ...");
}
+ tprints("}");
}
#undef STAT_MINOR
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
struct_flock.c \
sun_path.expected \
uio.expected \
+ umode_t.c \
umovestr.expected \
unix-pair-send-recv.expected \
unix-pair-sendto-recvfrom.expected \
#ifdef __NR_creat
-# include <stdio.h>
-# include <unistd.h>
-
-# 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
# Check creat syscall decoding.
. "${srcdir=.}/init.sh"
-run_strace_match_diff -a21
+run_strace_match_diff -a20
#ifdef __NR_mkdir
-# include <stdio.h>
-# include <unistd.h>
-
-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
# Check mkdir syscall decoding.
. "${srcdir=.}/init.sh"
-run_strace_match_diff -a21
+run_strace_match_diff -a20
#ifdef __NR_mkdirat
-# include <stdio.h>
-# include <unistd.h>
-
-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
# Check mkdirat syscall decoding.
. "${srcdir=.}/init.sh"
-run_strace_match_diff -a36
+run_strace_match_diff -a28
# include <sys/mkdev.h>
# 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());
# include <sys/mkdev.h>
# 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;
# Check mknodat syscall decoding.
. "${srcdir=.}/init.sh"
-run_strace_match_diff
+run_strace_match_diff -a35
#include <stdio.h>
#include <sys/stat.h>
+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;
--- /dev/null
+/*
+ * Check decoding of umode_t type syscall arguments.
+ *
+ * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#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;
+}
SYS_FUNC(umask)
{
- tprintf("%#lo", tcp->u_arg[0]);
+ print_numeric_umode_t(tcp->u_arg[0]);
return RVAL_DECODED | RVAL_OCTAL;
}