From: Dmitry V. Levin Date: Tue, 26 Apr 2016 00:21:26 +0000 (+0000) Subject: Fix decoding of statfs family syscalls X-Git-Tag: v4.12~284 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=67c2f6741027fe9076b0127a68b9382ff369101d;p=strace Fix decoding of statfs family syscalls Fix decoders of fstatfs, fstatfs64, statfs, and statfs64 syscalls by rewriting them using mpers infrastructure. * fetch_struct_statfs.c: New file. * fstatfs.c: Likewise. * fstatfs64.c: Likewise. * print_statfs.c: Likewise. * statfs.h: Likewise. * statfs64.c: Likewise. * statfs.c: Remove everything except SYS_FUNC(statfs). * configure.ac: Remove the check for struct statfs64 in . Add checks for struct statfs and struct statfs64 in . Add checks for f_frsize and f_flags members of these structures. * defs.h (struct strace_statfs): New forward declaration. (print_struct_statfs, print_struct_statfs64): New prototypes. * Makefile.am (libstrace_a_SOURCES): Add fstatfs.c, fstatfs64.c, statfs.c, and statfs64.c. (strace_SOURCES): Add fetch_struct_statfs.c, print_statfs.c, and statfs.h. * NEWS: Mention this fix. * tests/fstatfs.c: New file. * tests/fstatfs64.c: Likewise. * tests/statfs64.c: Likewise. * tests/xstatfs.c: Likewise. * tests/xstatfs64.c: Likewise. * tests/xstatfsx.c: Likewise. * tests/fstatfs.test: New test. * tests/fstatfs64.test: Likewise. * tests/statfs64.test: Likewise. * tests/statfs.c: Rewrite using xstatfs.c. * tests/statfs.test: Update. * tests/.gitignore: Add fstatfs, fstatfs64, and statfs64. * tests/Makefile.am (check_PROGRAMS): Likewise. (DECODER_TESTS): Add fstatfs.test, fstatfs64.test, and statfs64.test. (EXTRA_DIST): Add xstatfs.c, xstatfs64.c, and xstatfsx.c. --- diff --git a/Makefile.am b/Makefile.am index f02a4211..96146dd0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -64,6 +64,10 @@ noinst_LIBRARIES = libstrace.a libstrace_a_CPPFLAGS = $(strace_CPPFLAGS) libstrace_a_CFLAGS = $(strace_CFLAGS) libstrace_a_SOURCES = \ + fstatfs.c \ + fstatfs64.c \ + statfs.c \ + statfs64.c \ sync_file_range.c \ sync_file_range2.c \ upeek.c \ @@ -103,6 +107,7 @@ strace_SOURCES = \ fcntl.c \ fetch_seccomp_fprog.c \ fetch_struct_flock.c \ + fetch_struct_statfs.c \ file.c \ file_handle.c \ flock.c \ @@ -157,6 +162,7 @@ strace_SOURCES = \ print_mq_attr.c \ print_msgbuf.c \ print_sigevent.c \ + print_statfs.c \ print_time.c \ print_timex.c \ printmode.c \ @@ -190,6 +196,7 @@ strace_SOURCES = \ socketutils.c \ sram_alloc.c \ statfs.c \ + statfs.h \ strace.c \ swapon.c \ syscall.c \ diff --git a/NEWS b/NEWS index 4cd5677b..08e23093 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,7 @@ Noteworthy changes in release ?.?? (????-??-??) * Implemented simultaneous use of -p option and tracing of a command. (addresses Debian bug #549942). * Enhanced decoding of personality, sched_getaffinity, - and sched_setaffinity syscalls. + sched_setaffinity, statfs, statfs64, fstatfs, and fstatfs64 syscalls. * Enhanced decoding of getxpid, getxuid, and getxgid syscalls on alpha. * Added decoding of bind, listen, and setsockopt direct syscalls on sparc. * Implemented caching of netlink conversations to reduce amount of time diff --git a/configure.ac b/configure.ac index 2b29c945..8a776d2e 100644 --- a/configure.ac +++ b/configure.ac @@ -304,8 +304,6 @@ AC_CHECK_TYPES([struct stat64, struct __old_kernel_stat],,, [#include #include ]) -AC_CHECK_TYPES([struct statfs64],,, [#include ]) - AC_CHECK_TYPES(m4_normalize([ struct pt_all_user_regs, struct ia64_fpreg, @@ -393,7 +391,6 @@ AC_CHECK_HEADERS(m4_normalize([ sys/sem.h sys/shm.h sys/signalfd.h - sys/vfs.h sys/xattr.h ])) @@ -434,6 +431,30 @@ AC_CHECK_HEADERS([linux/bpf.h], [ fi ]) +AC_CHECK_TYPES([struct statfs], [ + AC_CHECK_MEMBERS([struct statfs.f_frsize],,, [#include +#include ]) + AC_CHECK_MEMBERS([struct statfs.f_flags],,, [#include +#include ]) + AC_CHECK_MEMBERS([struct statfs.f_fsid.val],,, [#include +#include ]) + AC_CHECK_MEMBERS([struct statfs.f_fsid.__val],,, [#include +#include ]) +],, [#include +#include ]) + +AC_CHECK_TYPES([struct statfs64], [ + AC_CHECK_MEMBERS([struct statfs64.f_frsize],,, [#include +#include ]) + AC_CHECK_MEMBERS([struct statfs64.f_flags],,, [#include +#include ]) + AC_CHECK_MEMBERS([struct statfs64.f_fsid.val],,, [#include +#include ]) + AC_CHECK_MEMBERS([struct statfs64.f_fsid.__val],,, [#include +#include ]) +],, [#include +#include ]) + AC_CHECK_DECLS([sys_errlist]) AC_CHECK_DECLS(m4_normalize([ PTRACE_PEEKUSER, diff --git a/defs.h b/defs.h index e345fd94..ef579ebe 100644 --- a/defs.h +++ b/defs.h @@ -634,6 +634,10 @@ extern void tprint_open_modes(int); extern const char *sprint_open_modes(int); extern void print_seccomp_filter(struct tcb *tcp, unsigned long); +struct strace_statfs; +extern void print_struct_statfs(struct tcb *tcp, long); +extern void print_struct_statfs64(struct tcb *tcp, long, unsigned long); + extern int block_ioctl(struct tcb *, const unsigned int, long); extern int evdev_ioctl(struct tcb *, const unsigned int, long); extern int loop_ioctl(struct tcb *, const unsigned int, long); diff --git a/fetch_struct_statfs.c b/fetch_struct_statfs.c new file mode 100644 index 00000000..7c8b0885 --- /dev/null +++ b/fetch_struct_statfs.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014-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 "defs.h" + +#include DEF_MPERS_TYPE(struct_statfs) +#include DEF_MPERS_TYPE(struct_statfs64) + +#include +#include +typedef struct statfs struct_statfs; +typedef struct statfs64 struct_statfs64; + +#include MPERS_DEFS + +#include "statfs.h" + +#define ASSIGN_NUMBER(dst, src) \ + if (sizeof(src) == sizeof(int)) \ + dst = (unsigned int) (src); \ + else if (sizeof(src) == sizeof(long)) \ + dst = (unsigned long) (src); \ + else \ + dst = (unsigned long long) (src) + +MPERS_PRINTER_DECL(bool, fetch_struct_statfs)(struct tcb *tcp, const long addr, struct strace_statfs *p) +{ + struct_statfs b; + + if (umove_or_printaddr(tcp, addr, &b)) + return false; + + ASSIGN_NUMBER(p->f_type, b.f_type); + ASSIGN_NUMBER(p->f_bsize, b.f_bsize); + ASSIGN_NUMBER(p->f_blocks, b.f_blocks); + ASSIGN_NUMBER(p->f_bfree, b.f_bfree); + ASSIGN_NUMBER(p->f_bavail, b.f_bavail); + ASSIGN_NUMBER(p->f_files, b.f_files); + ASSIGN_NUMBER(p->f_ffree, b.f_ffree); +#if defined HAVE_STRUCT_STATFS_F_FSID_VAL + ASSIGN_NUMBER(p->f_fsid[0], b.f_fsid.val[0]); + ASSIGN_NUMBER(p->f_fsid[1], b.f_fsid.val[1]); +#elif defined HAVE_STRUCT_STATFS_F_FSID___VAL + ASSIGN_NUMBER(p->f_fsid[0], b.f_fsid.__val[0]); + ASSIGN_NUMBER(p->f_fsid[1], b.f_fsid.__val[1]); +#endif + ASSIGN_NUMBER(p->f_namelen, b.f_namelen); +#ifdef HAVE_STRUCT_STATFS_F_FRSIZE + ASSIGN_NUMBER(p->f_frsize, b.f_frsize); +#endif +#ifdef HAVE_STRUCT_STATFS_F_FLAGS + ASSIGN_NUMBER(p->f_flags, b.f_flags); +#endif + + return true; +} + +#if defined ARM || (defined AARCH64 && defined IN_MPERS) +/* See arch/arm/kernel/sys_oabi-compat.c for details. */ +# define COMPAT_STATFS64_PADDED_SIZE (sizeof(struct_statfs64) + 4) +#endif + +MPERS_PRINTER_DECL(bool, fetch_struct_statfs64)(struct tcb *tcp, const long addr, const unsigned long size, struct strace_statfs *p) +{ + struct_statfs64 b; + + if (sizeof(b) != size +#ifdef COMPAT_STATFS64_PADDED_SIZE + && sizeof(b) != COMPAT_STATFS64_PADDED_SIZE +#endif + ) { + printaddr(addr); + return false; + } + + if (umove_or_printaddr(tcp, addr, &b)) + return false; + + ASSIGN_NUMBER(p->f_type, b.f_type); + ASSIGN_NUMBER(p->f_bsize, b.f_bsize); + ASSIGN_NUMBER(p->f_blocks, b.f_blocks); + ASSIGN_NUMBER(p->f_bfree, b.f_bfree); + ASSIGN_NUMBER(p->f_bavail, b.f_bavail); + ASSIGN_NUMBER(p->f_files, b.f_files); + ASSIGN_NUMBER(p->f_ffree, b.f_ffree); +#if defined HAVE_STRUCT_STATFS64_F_FSID_VAL + ASSIGN_NUMBER(p->f_fsid[0], b.f_fsid.val[0]); + ASSIGN_NUMBER(p->f_fsid[1], b.f_fsid.val[1]); +#elif defined HAVE_STRUCT_STATFS64_F_FSID___VAL + ASSIGN_NUMBER(p->f_fsid[0], b.f_fsid.__val[0]); + ASSIGN_NUMBER(p->f_fsid[1], b.f_fsid.__val[1]); +#endif + ASSIGN_NUMBER(p->f_namelen, b.f_namelen); +#ifdef HAVE_STRUCT_STATFS64_F_FRSIZE + ASSIGN_NUMBER(p->f_frsize, b.f_frsize); +#endif +#ifdef HAVE_STRUCT_STATFS64_F_FLAGS + ASSIGN_NUMBER(p->f_flags, b.f_flags); +#endif + + return true; +} diff --git a/fstatfs.c b/fstatfs.c new file mode 100644 index 00000000..1f358240 --- /dev/null +++ b/fstatfs.c @@ -0,0 +1,12 @@ +#include "defs.h" + +SYS_FUNC(fstatfs) +{ + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + } else { + print_struct_statfs(tcp, tcp->u_arg[1]); + } + return 0; +} diff --git a/fstatfs64.c b/fstatfs64.c new file mode 100644 index 00000000..63eb3dfa --- /dev/null +++ b/fstatfs64.c @@ -0,0 +1,14 @@ +#include "defs.h" + +SYS_FUNC(fstatfs64) +{ + const unsigned long size = tcp->u_arg[1]; + + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprintf(", %lu, ", size); + } else { + print_struct_statfs64(tcp, tcp->u_arg[2], size); + } + return 0; +} diff --git a/print_statfs.c b/print_statfs.c new file mode 100644 index 00000000..17f4c6f6 --- /dev/null +++ b/print_statfs.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014-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 "defs.h" +#include "statfs.h" +#include "xlat/fsmagic.h" +#include "xlat/statfs_flags.h" + +static void +print_statfs_type(const char *const prefix, const unsigned long long magic) +{ + tprints(prefix); + const char *s = xlat_search(fsmagic, ARRAY_SIZE(fsmagic), magic); + if (s) + tprints(s); + else + tprintf("%#llx", magic); +} + +static void +print_statfs_flags(const char *const prefix, const unsigned long long flags) +{ + if (flags & ST_VALID) { + tprints(prefix); + printflags(statfs_flags, flags, "ST_???"); + } +} + +static void +print_statfs_number(const char *const prefix, const unsigned long long number) +{ + tprints(prefix); + tprintf("%llu", number); +} + +void +print_struct_statfs(struct tcb *tcp, const long addr) +{ +#ifdef HAVE_STRUCT_STATFS + struct strace_statfs b; + + if (!fetch_struct_statfs(tcp, addr, &b)) + return; + + print_statfs_type("{f_type=", b.f_type); + print_statfs_number(", f_bsize=", b.f_bsize); + print_statfs_number(", f_blocks=", b.f_blocks); + print_statfs_number(", f_bfree=", b.f_bfree); + print_statfs_number(", f_bavail=", b.f_bavail); + print_statfs_number(", f_files=", b.f_files); + print_statfs_number(", f_ffree=", b.f_ffree); +# if defined HAVE_STRUCT_STATFS_F_FSID_VAL \ + || defined HAVE_STRUCT_STATFS_F_FSID___VAL + print_statfs_number(", f_fsid={", b.f_fsid[0]); + print_statfs_number(", ", b.f_fsid[1]); + tprints("}"); +# endif + print_statfs_number(", f_namelen=", b.f_namelen); +# ifdef HAVE_STRUCT_STATFS_F_FRSIZE + print_statfs_number(", f_frsize=", b.f_frsize); +# endif +# ifdef HAVE_STRUCT_STATFS_F_FLAGS + print_statfs_flags(", f_flags=", b.f_flags); +# endif + tprints("}"); +#else + printaddr(addr); +#endif +} + +void +print_struct_statfs64(struct tcb *tcp, const long addr, const unsigned long size) +{ +#ifdef HAVE_STRUCT_STATFS64 + struct strace_statfs b; + + if (!fetch_struct_statfs64(tcp, addr, size, &b)) + return; + + print_statfs_type("{f_type=", b.f_type); + print_statfs_number(", f_bsize=", b.f_bsize); + print_statfs_number(", f_blocks=", b.f_blocks); + print_statfs_number(", f_bfree=", b.f_bfree); + print_statfs_number(", f_bavail=", b.f_bavail); + print_statfs_number(", f_files=", b.f_files); + print_statfs_number(", f_ffree=", b.f_ffree); +# if defined HAVE_STRUCT_STATFS64_F_FSID_VAL \ + || defined HAVE_STRUCT_STATFS64_F_FSID___VAL + print_statfs_number(", f_fsid={", b.f_fsid[0]); + print_statfs_number(", ", b.f_fsid[1]); + tprints("}"); +# endif + print_statfs_number(", f_namelen=", b.f_namelen); +# ifdef HAVE_STRUCT_STATFS64_F_FRSIZE + print_statfs_number(", f_frsize=", b.f_frsize); +# endif +# ifdef HAVE_STRUCT_STATFS64_F_FLAGS + print_statfs_flags(", f_flags=", b.f_flags); +# endif + tprints("}"); +#else + printaddr(addr); +#endif +} diff --git a/statfs.c b/statfs.c index bcbb73d2..00dd04c4 100644 --- a/statfs.c +++ b/statfs.c @@ -1,91 +1,4 @@ -/* - * Copyright (c) 1991, 1992 Paul Kranenburg - * Copyright (c) 1993 Branko Lankester - * Copyright (c) 1993-1996 Rick Sladkey - * Copyright (c) 1996-1999 Wichert Akkerman - * Copyright (c) 2003 Ulrich Drepper - * Copyright (c) 2012 Andreas Schwab - * Copyright (c) 2014-2015 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 "defs.h" -#ifdef HAVE_SYS_VFS_H -# include -#endif -#include "xlat/fsmagic.h" -#include "xlat/statfs_flags.h" - -static const char * -sprintfstype(const unsigned int magic) -{ - static char buf[32]; - const char *s; - - s = xlat_search(fsmagic, ARRAY_SIZE(fsmagic), magic); - if (s) - return s; - sprintf(buf, "%#x", magic); - return buf; -} - -static void -print_statfs_flags(const char *const prefix, const unsigned int flags) -{ - if (flags & ST_VALID) { - tprints(prefix); - printflags(statfs_flags, flags, "ST_???"); - } -} - -static void -printstatfs(struct tcb *tcp, const long addr) -{ - struct statfs statbuf; - - if (umove_or_printaddr(tcp, addr, &statbuf)) - return; - tprintf("{f_type=%s, f_bsize=%lu, f_blocks=%lu, f_bfree=%lu, ", - sprintfstype(statbuf.f_type), - (unsigned long)statbuf.f_bsize, - (unsigned long)statbuf.f_blocks, - (unsigned long)statbuf.f_bfree); - tprintf("f_bavail=%lu, f_files=%lu, f_ffree=%lu, f_fsid={%d, %d}", - (unsigned long)statbuf.f_bavail, - (unsigned long)statbuf.f_files, - (unsigned long)statbuf.f_ffree, - statbuf.f_fsid.__val[0], statbuf.f_fsid.__val[1]); - tprintf(", f_namelen=%lu", (unsigned long)statbuf.f_namelen); -#ifdef _STATFS_F_FRSIZE - tprintf(", f_frsize=%lu", (unsigned long)statbuf.f_frsize); -#endif -#ifdef _STATFS_F_FLAGS - print_statfs_flags(", f_flags=", statbuf.f_flags); -#endif - tprints("}"); -} SYS_FUNC(statfs) { @@ -93,127 +6,7 @@ SYS_FUNC(statfs) printpath(tcp, tcp->u_arg[0]); tprints(", "); } else { - printstatfs(tcp, tcp->u_arg[1]); + print_struct_statfs(tcp, tcp->u_arg[1]); } return 0; } - -SYS_FUNC(fstatfs) -{ - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); - } else { - printstatfs(tcp, tcp->u_arg[1]); - } - return 0; -} - -#ifdef HAVE_STRUCT_STATFS64 -static void -printstatfs64(struct tcb *tcp, long addr) -{ - struct statfs64 statbuf; - - if (umove_or_printaddr(tcp, addr, &statbuf)) - return; - tprintf("{f_type=%s, f_bsize=%llu, f_blocks=%llu, f_bfree=%llu, ", - sprintfstype(statbuf.f_type), - (unsigned long long)statbuf.f_bsize, - (unsigned long long)statbuf.f_blocks, - (unsigned long long)statbuf.f_bfree); - tprintf("f_bavail=%llu, f_files=%llu, f_ffree=%llu, f_fsid={%d, %d}", - (unsigned long long)statbuf.f_bavail, - (unsigned long long)statbuf.f_files, - (unsigned long long)statbuf.f_ffree, - statbuf.f_fsid.__val[0], statbuf.f_fsid.__val[1]); - tprintf(", f_namelen=%lu", (unsigned long)statbuf.f_namelen); -#ifdef _STATFS_F_FRSIZE - tprintf(", f_frsize=%llu", (unsigned long long)statbuf.f_frsize); -#endif -#ifdef _STATFS_F_FLAGS - print_statfs_flags(", f_flags=", statbuf.f_flags); -#endif - tprints("}"); -} - -struct compat_statfs64 { - uint32_t f_type; - uint32_t f_bsize; - uint64_t f_blocks; - uint64_t f_bfree; - uint64_t f_bavail; - uint64_t f_files; - uint64_t f_ffree; - fsid_t f_fsid; - uint32_t f_namelen; - uint32_t f_frsize; - uint32_t f_flags; - uint32_t f_spare[4]; -} -#if defined AARCH64 || defined X86_64 || defined X32 || defined IA64 - ATTRIBUTE_PACKED ATTRIBUTE_ALIGNED(4) -#endif -; -#if defined AARCH64 || defined ARM -/* See arch/arm/kernel/sys_oabi-compat.c for details. */ -# define COMPAT_STATFS64_PADDED_SIZE (sizeof(struct compat_statfs64) + 4) -#endif - -static void -printcompat_statfs64(struct tcb *tcp, const long addr) -{ - struct compat_statfs64 statbuf; - - if (umove_or_printaddr(tcp, addr, &statbuf)) - return; - tprintf("{f_type=%s, f_bsize=%lu, f_blocks=%llu, f_bfree=%llu, ", - sprintfstype(statbuf.f_type), - (unsigned long)statbuf.f_bsize, - (unsigned long long)statbuf.f_blocks, - (unsigned long long)statbuf.f_bfree); - tprintf("f_bavail=%llu, f_files=%llu, f_ffree=%llu, f_fsid={%d, %d}", - (unsigned long long)statbuf.f_bavail, - (unsigned long long)statbuf.f_files, - (unsigned long long)statbuf.f_ffree, - statbuf.f_fsid.__val[0], statbuf.f_fsid.__val[1]); - tprintf(", f_namelen=%lu", (unsigned long)statbuf.f_namelen); - tprintf(", f_frsize=%lu", (unsigned long)statbuf.f_frsize); - print_statfs_flags(", f_flags=", statbuf.f_flags); - tprints("}"); -} - -static int -do_statfs64_fstatfs64(struct tcb *tcp) -{ - if (entering(tcp)) { - tprintf(", %lu, ", tcp->u_arg[1]); - } else { - if (tcp->u_arg[1] == sizeof(struct statfs64)) - printstatfs64(tcp, tcp->u_arg[2]); - else if (tcp->u_arg[1] == sizeof(struct compat_statfs64) -#ifdef COMPAT_STATFS64_PADDED_SIZE - || tcp->u_arg[1] == COMPAT_STATFS64_PADDED_SIZE -#endif - ) - printcompat_statfs64(tcp, tcp->u_arg[2]); - else - tprints("{???}"); - } - return 0; -} - -SYS_FUNC(statfs64) -{ - if (entering(tcp)) - printpath(tcp, tcp->u_arg[0]); - return do_statfs64_fstatfs64(tcp); -} - -SYS_FUNC(fstatfs64) -{ - if (entering(tcp)) - printfd(tcp, tcp->u_arg[0]); - return do_statfs64_fstatfs64(tcp); -} -#endif /* HAVE_STRUCT_STATFS64 */ diff --git a/statfs.h b/statfs.h new file mode 100644 index 00000000..9341687c --- /dev/null +++ b/statfs.h @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#ifndef STRACE_STATFS_H +#define STRACE_STATFS_H + +struct strace_statfs { + unsigned long long f_type; + unsigned long long f_bsize; + unsigned long long f_blocks; + unsigned long long f_bfree; + unsigned long long f_bavail; + unsigned long long f_files; + unsigned long long f_ffree; + unsigned long f_fsid[2]; + unsigned long long f_namelen; + unsigned long long f_frsize; + unsigned long long f_flags; +}; + +#endif /* STRACE_STATFS_H */ diff --git a/statfs64.c b/statfs64.c new file mode 100644 index 00000000..f4598317 --- /dev/null +++ b/statfs64.c @@ -0,0 +1,14 @@ +#include "defs.h" + +SYS_FUNC(statfs64) +{ + const unsigned long size = tcp->u_arg[1]; + + if (entering(tcp)) { + printpath(tcp, tcp->u_arg[0]); + tprintf(", %lu, ", size); + } else { + print_struct_statfs64(tcp, tcp->u_arg[2], size); + } + return 0; +} diff --git a/tests/.gitignore b/tests/.gitignore index ef39fe20..9cac19d7 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -56,6 +56,8 @@ fork-f fstat fstat64 fstatat64 +fstatfs +fstatfs64 fsync ftruncate ftruncate64 @@ -198,6 +200,7 @@ stack-fcall stat stat64 statfs +statfs64 swap symlink symlinkat diff --git a/tests/Makefile.am b/tests/Makefile.am index bd170fdd..6aa5d0e5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -110,6 +110,8 @@ check_PROGRAMS = \ fstat \ fstat64 \ fstatat64 \ + fstatfs \ + fstatfs64 \ fsync \ ftruncate \ ftruncate64 \ @@ -250,6 +252,7 @@ check_PROGRAMS = \ stat \ stat64 \ statfs \ + statfs64 \ swap \ symlink \ symlinkat \ @@ -366,6 +369,8 @@ DECODER_TESTS = \ fstat.test \ fstat64.test \ fstatat64.test \ + fstatfs.test \ + fstatfs64.test \ fsync.test \ ftruncate.test \ ftruncate64.test \ @@ -498,6 +503,7 @@ DECODER_TESTS = \ stat.test \ stat64.test \ statfs.test \ + statfs64.test \ sun_path.test \ swap.test \ symlink.test \ @@ -614,6 +620,9 @@ EXTRA_DIST = init.sh run.sh match.awk \ xattr.expected \ xchownx.c \ xselect.c \ + xstatfs.c \ + xstatfs64.c \ + xstatfsx.c \ xstatx.c \ $(TESTS) diff --git a/tests/fstatfs.c b/tests/fstatfs.c new file mode 100644 index 00000000..7ff39dcf --- /dev/null +++ b/tests/fstatfs.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015-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 "tests.h" +#include + +#ifdef __NR_fstatfs + +# define SYSCALL_ARG_FMT "%d" +# define SYSCALL_ARG(file, desc) (desc) +# define SYSCALL_NR __NR_fstatfs +# define SYSCALL_NAME "fstatfs" +# include "xstatfs.c" + +#else + +SKIP_MAIN_UNDEFINED("__NR_fstatfs") + +#endif diff --git a/tests/fstatfs.test b/tests/fstatfs.test new file mode 100755 index 00000000..646e66f2 --- /dev/null +++ b/tests/fstatfs.test @@ -0,0 +1,5 @@ +#!/bin/sh + +# Check fstatfs syscall decoding. + +. "${srcdir=.}/statfs.test" diff --git a/tests/fstatfs64.c b/tests/fstatfs64.c new file mode 100644 index 00000000..6c599744 --- /dev/null +++ b/tests/fstatfs64.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015-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 "tests.h" +#include + +#ifdef __NR_fstatfs64 + +# define SYSCALL_ARG_FMT "%d" +# define SYSCALL_ARG(file, desc) (desc) +# define SYSCALL_NR __NR_fstatfs64 +# define SYSCALL_NAME "fstatfs64" +# include "xstatfs64.c" + +#else + +SKIP_MAIN_UNDEFINED("__NR_fstatfs64") + +#endif diff --git a/tests/fstatfs64.test b/tests/fstatfs64.test new file mode 100755 index 00000000..179ff1bf --- /dev/null +++ b/tests/fstatfs64.test @@ -0,0 +1,5 @@ +#!/bin/sh + +# Check fstatfs64 syscall decoding. + +. "${srcdir=.}/statfs.test" diff --git a/tests/statfs.c b/tests/statfs.c index 9b6ba55a..5a87afc1 100644 --- a/tests/statfs.c +++ b/tests/statfs.c @@ -26,13 +26,18 @@ */ #include "tests.h" -#include +#include -int -main(void) -{ - struct statfs stb; - if (statfs("/proc/self/status", &stb)) - perror_msg_and_fail("statfs"); - return 0; -} +#ifdef __NR_statfs + +# define SYSCALL_ARG_FMT "\"%s\"" +# define SYSCALL_ARG(file, desc) (file) +# define SYSCALL_NR __NR_statfs +# define SYSCALL_NAME "statfs" +# include "xstatfs.c" + +#else + +SKIP_MAIN_UNDEFINED("__NR_statfs") + +#endif diff --git a/tests/statfs.test b/tests/statfs.test index 214d5210..6075576f 100755 --- a/tests/statfs.test +++ b/tests/statfs.test @@ -1,15 +1,11 @@ #!/bin/sh -# Check how statfs/statfs64 syscalls are traced. +# Check statfs syscall decoding. . "${srcdir=.}/init.sh" # this test probes /proc/self/status [ -f /proc/self/status ] || - framework_skip_ '/proc/self/status is not available' + framework_skip_ '/proc/self/status is not available' -run_prog -run_strace -efile $args -match_grep - -exit 0 +run_strace_match_diff -a17 diff --git a/tests/statfs64.c b/tests/statfs64.c new file mode 100644 index 00000000..b85dce2c --- /dev/null +++ b/tests/statfs64.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015-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 "tests.h" +#include + +#ifdef __NR_statfs64 + +# define SYSCALL_ARG_FMT "\"%s\"" +# define SYSCALL_ARG(file, desc) (file) +# define SYSCALL_NR __NR_statfs64 +# define SYSCALL_NAME "statfs64" +# include "xstatfs64.c" + +#else + +SKIP_MAIN_UNDEFINED("__NR_statfs64") + +#endif diff --git a/tests/statfs64.test b/tests/statfs64.test new file mode 100755 index 00000000..9c0aa278 --- /dev/null +++ b/tests/statfs64.test @@ -0,0 +1,5 @@ +#!/bin/sh + +# Check statfs64 syscall decoding. + +. "${srcdir=.}/statfs.test" diff --git a/tests/xstatfs.c b/tests/xstatfs.c new file mode 100644 index 00000000..26c43dee --- /dev/null +++ b/tests/xstatfs.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015-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. + */ + +#define SYSCALL_INVOKE(file, desc, ptr, size) \ + syscall(SYSCALL_NR, SYSCALL_ARG(file, desc), ptr) +#define PRINT_SYSCALL_HEADER(file, desc, size) \ + printf("%s(" SYSCALL_ARG_FMT ", ", SYSCALL_NAME, SYSCALL_ARG(file, desc)) + +#define STRUCT_STATFS struct statfs +#ifdef HAVE_STRUCT_STATFS_F_FRSIZE +# define PRINT_F_FRSIZE +#endif +#ifdef HAVE_STRUCT_STATFS_F_FLAGS +# define PRINT_F_FLAGS +#endif +#if defined HAVE_STRUCT_STATFS_F_FSID_VAL +# define PRINT_F_FSID f_fsid.val +#elif defined HAVE_STRUCT_STATFS_F_FSID___VAL +# define PRINT_F_FSID f_fsid.__val +#endif + +#include "xstatfsx.c" diff --git a/tests/xstatfs64.c b/tests/xstatfs64.c new file mode 100644 index 00000000..8f50de29 --- /dev/null +++ b/tests/xstatfs64.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015-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. + */ + +#define SYSCALL_INVOKE(file, desc, ptr, size) \ + syscall(SYSCALL_NR, SYSCALL_ARG(file, desc), size, ptr) +#define PRINT_SYSCALL_HEADER(file, desc, size) \ + printf("%s(" SYSCALL_ARG_FMT ", %u, ", SYSCALL_NAME, \ + SYSCALL_ARG(file, desc), (unsigned) size) + +#define STRUCT_STATFS struct statfs64 +#ifdef HAVE_STRUCT_STATFS64_F_FRSIZE +# define PRINT_F_FRSIZE +#endif +#ifdef HAVE_STRUCT_STATFS64_F_FLAGS +# define PRINT_F_FLAGS +#endif +#if defined HAVE_STRUCT_STATFS64_F_FSID_VAL +# define PRINT_F_FSID f_fsid.val +#elif defined HAVE_STRUCT_STATFS64_F_FSID___VAL +# define PRINT_F_FSID f_fsid.__val +#endif +#define CHECK_ODD_SIZE + +#include "xstatfsx.c" diff --git a/tests/xstatfsx.c b/tests/xstatfsx.c new file mode 100644 index 00000000..8e54fce5 --- /dev/null +++ b/tests/xstatfsx.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015-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 + +#include +#include + +#include "xlat.h" +#include "xlat/fsmagic.h" +#include "xlat/statfs_flags.h" + +#define PRINT_NUM(arg) \ + if (sizeof(b->arg) == sizeof(int)) \ + printf(", %s=%u", #arg, (unsigned int) b->arg); \ + else if (sizeof(b->arg) == sizeof(long)) \ + printf(", %s=%lu", #arg, (unsigned long) b->arg); \ + else \ + printf(", %s=%llu", #arg, (unsigned long long) b->arg) + +static void +print_statfs_type(const char *const prefix, const unsigned int magic) +{ + fputs(prefix, stdout); + unsigned int i; + for (i = 0; i < ARRAY_SIZE(fsmagic); ++i) + if (magic == fsmagic[i].val) { + fputs(fsmagic[i].str, stdout); + return; + } + printf("%#x", magic); +} + +static void +print_statfs(const char *const sample, const char *magic_str) +{ + int fd = open(sample, O_RDONLY); + if (fd < 0) + perror_msg_and_fail("open: %s", sample); + + STRUCT_STATFS *const b = tail_alloc(sizeof(*b)); + long rc = SYSCALL_INVOKE(sample, fd, b, sizeof(*b)); + if (rc) + perror_msg_and_skip(SYSCALL_NAME); + + PRINT_SYSCALL_HEADER(sample, fd, sizeof(*b)); + if (magic_str) + printf("{f_type=%s", magic_str); + else + print_statfs_type("{f_type=", b->f_type); + PRINT_NUM(f_bsize); + PRINT_NUM(f_blocks); + PRINT_NUM(f_bfree); + PRINT_NUM(f_bavail); + PRINT_NUM(f_files); + PRINT_NUM(f_ffree); +#ifdef PRINT_F_FSID + printf(", f_fsid={%u, %u}", b->PRINT_F_FSID[0], b->PRINT_F_FSID[1]); +#endif + PRINT_NUM(f_namelen); +#ifdef PRINT_F_FRSIZE + PRINT_NUM(f_frsize); +#endif +#ifdef PRINT_F_FLAGS + if (b->f_flags & ST_VALID) { + printf(", f_flags="); + printflags(statfs_flags, b->f_flags, "ST_???"); + } +#endif + printf("}) = 0\n"); +} + +int +main(void) +{ + print_statfs("/proc/self/status", "PROC_SUPER_MAGIC"); + + print_statfs(".", NULL); + + long rc = SYSCALL_INVOKE("", -1, 0, sizeof(STRUCT_STATFS)); + PRINT_SYSCALL_HEADER("", -1, sizeof(STRUCT_STATFS)); + printf("NULL) = %ld %s (%m)\n", rc, errno2name()); + +#ifdef CHECK_ODD_SIZE + const unsigned long addr = (unsigned long) 0xfacefeeddeadbeef; + rc = SYSCALL_INVOKE("", -1, addr, sizeof(STRUCT_STATFS) + 1); + PRINT_SYSCALL_HEADER("", -1, sizeof(STRUCT_STATFS) + 1); + printf("%#lx) = %ld %s (%m)\n", addr, rc, errno2name()); +#endif + + puts("+++ exited with 0 +++"); + return 0; +}