#ifdef HAVE_CONFIG_H # include "config.h" #endif #include <assert.h> #include <unistd.h> #include <stdio.h> #include <time.h> #if defined MAJOR_IN_SYSMACROS # include <sys/sysmacros.h> #elif defined MAJOR_IN_MKDEV # include <sys/mkdev.h> #else # include <sys/types.h> #endif #undef STAT_PREFIX #undef NR_stat #if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64 # include <sys/stat.h> # define STAT_PREFIX "(stat(64)?\\(|newfstatat\\(AT_FDCWD, )" #else # include <sys/syscall.h> # if defined __NR_stat # define NR_stat __NR_stat # define STAT_PREFIX "stat\\(" # elif defined __NR_newstat # define NR_stat __NR_newstat # define STAT_PREFIX "newstat\\(" # endif # ifdef STAT_PREFIX /* for S_IFMT */ # define stat libc_stat # define stat64 libc_stat64 # include <sys/stat.h> # 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 <asm/stat.h> # endif /* STAT_PREFIX */ #endif /* _FILE_OFFSET_BITS */ #ifdef STAT_PREFIX 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_PREFIX "\"%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("\\}"); #ifndef NR_stat printf("(, 0)?"); #endif printf("\\) += 0\n"); return 0; } #else /* !STAT_PREFIX */ int main(void) { return 77; } #endif