From 7b01014080f8d0a8aa446018246369343ea8f7ed Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Wed, 7 Jan 2015 19:30:37 +0000 Subject: [PATCH] tests: check verbose decoding of 32-bit and 64-bit struct stat * tests/stat.c: New file. * tests/stat32.c: Likewise. * tests/stat32-v.test: New file. * tests/stat64-v.test: Likewise. * tests/Makefile.am (check_PROGRAMS): Add stat and stat32. (stat_CFLAGS): Define. (TESTS): Add stat32-v.test and stat64-v.test. * tests/.gitignore: Add stat and stat32. --- tests/.gitignore | 2 + tests/Makefile.am | 5 ++ tests/stat.c | 171 ++++++++++++++++++++++++++++++++++++++++++++ tests/stat32-v.test | 43 +++++++++++ tests/stat32.c | 1 + tests/stat64-v.test | 38 ++++++++++ 6 files changed, 260 insertions(+) create mode 100644 tests/stat.c create mode 100755 tests/stat32-v.test create mode 100644 tests/stat32.c create mode 100755 tests/stat64-v.test diff --git a/tests/.gitignore b/tests/.gitignore index b53ef6ad..af463d08 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -8,6 +8,8 @@ scm_rights set_ptracer_any sigaction stack-fcall +stat +stat32 statfs uid uid16 diff --git a/tests/Makefile.am b/tests/Makefile.am index e307c577..b88ed55e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -13,12 +13,15 @@ check_PROGRAMS = \ set_ptracer_any \ sigaction \ stack-fcall \ + stat \ + stat32 \ statfs \ uid \ uid16 \ uid32 \ uio +stat_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64 statfs_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64 uio_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64 stack_fcall_SOURCES = stack-fcall.c \ @@ -33,6 +36,8 @@ TESTS = \ scm_rights-fd.test \ sigaction.test \ stat.test \ + stat32-v.test \ + stat64-v.test \ statfs.test \ mmsg.test \ net.test \ diff --git a/tests/stat.c b/tests/stat.c new file mode 100644 index 00000000..21e37fbd --- /dev/null +++ b/tests/stat.c @@ -0,0 +1,171 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#if defined MAJOR_IN_SYSMACROS +# include +#elif defined MAJOR_IN_MKDEV +# include +#else +# include +#endif + +#undef STAT_FNAME +#undef NR_stat + +#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64 +# include +# define STAT_FNAME "stat(64)?" +#else +# include +# if defined __NR_stat +# define NR_stat __NR_stat +# define STAT_FNAME "stat" +# elif defined __NR_newstat +# define NR_stat __NR_newstat +# define STAT_FNAME "newstat" +# endif +# ifdef STAT_FNAME +/* for S_IFMT */ +# define stat libc_stat +# define stat64 libc_stat64 +# include +# undef stat +# undef stat64 +# undef st_atime +# undef st_mtime +# undef st_ctime + +# undef dev_t +# undef ino_t +# undef mode_t +# undef nlink_t +# undef uid_t +# undef gid_t +# undef off_t +# undef loff_t +# define dev_t __kernel_dev_t +# define ino_t __kernel_ino_t +# define mode_t __kernel_mode_t +# define nlink_t __kernel_nlink_t +# define uid_t __kernel_uid_t +# define gid_t __kernel_gid_t +# define off_t __kernel_off_t +# define loff_t __kernel_loff_t +# include +# endif /* STAT_FNAME */ +#endif /* _FILE_OFFSET_BITS */ + +#ifdef STAT_FNAME + +static void +print_ftype(unsigned int mode) +{ + if (S_ISREG(mode)) + printf("S_IFREG"); + else if (S_ISDIR(mode)) + printf("S_IFDIR"); + else if (S_ISCHR(mode)) + printf("S_IFCHR"); + else if (S_ISBLK(mode)) + printf("S_IFBLK"); + else + printf("%#o", mode & S_IFMT); +} + +static void +print_perms(unsigned int mode) +{ + printf("%#o", mode & ~S_IFMT); +} + +static void +print_time(time_t t) +{ + if (!t) { + printf("0"); + return; + } + + struct tm *p = localtime(&t); + + if (p) + printf("%02d/%02d/%02d-%02d:%02d:%02d", + p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, + p->tm_hour, p->tm_min, p->tm_sec); + else + printf("%llu", (unsigned long long) t); +} + +int +main(int ac, const char **av) +{ + assert(ac == 2); + struct stat stb; + +#ifdef NR_stat + if (sizeof(stb.st_size) > 4) + return 77; + assert(syscall(NR_stat, av[1], &stb) == 0); +#else + assert(stat(av[1], &stb) == 0); +#endif + + printf(STAT_FNAME "\\(\"%s\", \\{", av[1]); + printf("st_dev=makedev\\(%u, %u\\)", + (unsigned int) major(stb.st_dev), + (unsigned int) minor(stb.st_dev)); + printf(", st_ino=%llu", (unsigned long long) stb.st_ino); + printf(", st_mode="); + print_ftype(stb.st_mode); + printf("\\|"); + print_perms(stb.st_mode); + printf(", st_nlink=%u", (unsigned int) stb.st_nlink); + printf(", st_uid=%u", (unsigned int) stb.st_uid); + printf(", st_gid=%u", (unsigned int) stb.st_gid); +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + printf(", st_blksize=%u", (unsigned int) stb.st_blksize); +#endif +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS + printf(", st_blocks=%u", (unsigned int) stb.st_blocks); +#endif + + switch (stb.st_mode & S_IFMT) { + case S_IFCHR: case S_IFBLK: +#ifdef HAVE_STRUCT_STAT_ST_RDEV + printf(", st_rdev=makedev\\(%u, %u\\)", + (unsigned int) major(stb.st_rdev), + (unsigned int) minor(stb.st_rdev)); +#else + printf(", st_size=makedev\\(%u, %u\\)", + (unsigned int) major(stb.st_size), + (unsigned int) minor(stb.st_size)); +#endif + break; + default: + printf(", st_size=%llu", (unsigned long long) stb.st_size); + } + + printf(", st_atime="); + print_time(stb.st_atime); + printf(", st_mtime="); + print_time(stb.st_mtime); + printf(", st_ctime="); + print_time(stb.st_ctime); + printf("(, st_flags=[0-9]+)?"); + printf("(, st_fstype=[^,]*)?"); + printf("(, st_gen=[0-9]+)?"); + printf("\\}\\) += 0\n"); + return 0; +} + +#else /* !STAT_FNAME */ +int main(void) +{ + return 77; +} +#endif diff --git a/tests/stat32-v.test b/tests/stat32-v.test new file mode 100755 index 00000000..74373c30 --- /dev/null +++ b/tests/stat32-v.test @@ -0,0 +1,43 @@ +#!/bin/sh + +# Check verbose decoding of 32-bit stat syscall. + +. "${srcdir=.}/init.sh" + +check_prog dd +check_prog grep +check_prog touch + +OUT="$LOG.out" +size=233811181 +sample=stat32_sample + +umask 022 +truncate_cmd="dd seek=$size obs=1 count=0 if=/dev/null of=$sample" +$truncate_cmd > "$OUT" 2>&1 || { + cat "$OUT" + framework_skip_ 'failed to create a large sparse file' +} + +./stat32 $sample > /dev/null || { + if [ $? -eq 77 ]; then + framework_skip_ '32-bit stat syscall is not available' + else + fail_ 'stat32 failed' + fi +} + +touch -t 0102030405 $sample + +for f in $sample . /dev/null; do + args="-v -efile ./stat32 $f" + $STRACE -o "$LOG" $args > "$OUT" && + LC_ALL=C grep -E -x -f "$OUT" "$LOG" > /dev/null || { + cat "$OUT" "$LOG" + fail_ "$STRACE $args output mismatch" + } +done + +rm -f $sample "$OUT" + +exit 0 diff --git a/tests/stat32.c b/tests/stat32.c new file mode 100644 index 00000000..a0742519 --- /dev/null +++ b/tests/stat32.c @@ -0,0 +1 @@ +#include "stat.c" diff --git a/tests/stat64-v.test b/tests/stat64-v.test new file mode 100755 index 00000000..7e08e258 --- /dev/null +++ b/tests/stat64-v.test @@ -0,0 +1,38 @@ +#!/bin/sh + +# Check verbose decoding of 64-bit stat syscall. + +. "${srcdir=.}/init.sh" + +check_prog dd +check_prog grep +check_prog touch + +OUT="$LOG.out" +size=46118400000 +sample=stat64_sample + +umask 022 +truncate_cmd="dd seek=$size obs=1 count=0 if=/dev/null of=$sample" +$truncate_cmd > "$OUT" 2>&1 || { + cat "$OUT" + framework_skip_ 'failed to create a large sparse file' +} + +./stat $sample > /dev/null || + fail_ 'stat failed' + +touch -t 0102030405 $sample + +for f in $sample . /dev/null; do + args="-v -efile ./stat $f" + $STRACE -o "$LOG" $args > "$OUT" && + LC_ALL=C grep -E -x -f "$OUT" "$LOG" > /dev/null || { + cat "$OUT" "$LOG" + fail_ "$STRACE $args output mismatch" + } +done + +rm -f $sample "$OUT" + +exit 0 -- 2.40.0