blob: 21e37fbdb5a8a8f258ef599d8c0ca8032a49f060 [file] [log] [blame]
Dmitry V. Levin7b010142015-01-07 19:30:37 +00001#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4#include <assert.h>
5#include <unistd.h>
6#include <stdio.h>
7#include <time.h>
8
9#if defined MAJOR_IN_SYSMACROS
10# include <sys/sysmacros.h>
11#elif defined MAJOR_IN_MKDEV
12# include <sys/mkdev.h>
13#else
14# include <sys/types.h>
15#endif
16
17#undef STAT_FNAME
18#undef NR_stat
19
20#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
21# include <sys/stat.h>
22# define STAT_FNAME "stat(64)?"
23#else
24# include <sys/syscall.h>
25# if defined __NR_stat
26# define NR_stat __NR_stat
27# define STAT_FNAME "stat"
28# elif defined __NR_newstat
29# define NR_stat __NR_newstat
30# define STAT_FNAME "newstat"
31# endif
32# ifdef STAT_FNAME
33/* for S_IFMT */
34# define stat libc_stat
35# define stat64 libc_stat64
36# include <sys/stat.h>
37# undef stat
38# undef stat64
39# undef st_atime
40# undef st_mtime
41# undef st_ctime
42
43# undef dev_t
44# undef ino_t
45# undef mode_t
46# undef nlink_t
47# undef uid_t
48# undef gid_t
49# undef off_t
50# undef loff_t
51# define dev_t __kernel_dev_t
52# define ino_t __kernel_ino_t
53# define mode_t __kernel_mode_t
54# define nlink_t __kernel_nlink_t
55# define uid_t __kernel_uid_t
56# define gid_t __kernel_gid_t
57# define off_t __kernel_off_t
58# define loff_t __kernel_loff_t
59# include <asm/stat.h>
60# endif /* STAT_FNAME */
61#endif /* _FILE_OFFSET_BITS */
62
63#ifdef STAT_FNAME
64
65static void
66print_ftype(unsigned int mode)
67{
68 if (S_ISREG(mode))
69 printf("S_IFREG");
70 else if (S_ISDIR(mode))
71 printf("S_IFDIR");
72 else if (S_ISCHR(mode))
73 printf("S_IFCHR");
74 else if (S_ISBLK(mode))
75 printf("S_IFBLK");
76 else
77 printf("%#o", mode & S_IFMT);
78}
79
80static void
81print_perms(unsigned int mode)
82{
83 printf("%#o", mode & ~S_IFMT);
84}
85
86static void
87print_time(time_t t)
88{
89 if (!t) {
90 printf("0");
91 return;
92 }
93
94 struct tm *p = localtime(&t);
95
96 if (p)
97 printf("%02d/%02d/%02d-%02d:%02d:%02d",
98 p->tm_year + 1900, p->tm_mon + 1, p->tm_mday,
99 p->tm_hour, p->tm_min, p->tm_sec);
100 else
101 printf("%llu", (unsigned long long) t);
102}
103
104int
105main(int ac, const char **av)
106{
107 assert(ac == 2);
108 struct stat stb;
109
110#ifdef NR_stat
111 if (sizeof(stb.st_size) > 4)
112 return 77;
113 assert(syscall(NR_stat, av[1], &stb) == 0);
114#else
115 assert(stat(av[1], &stb) == 0);
116#endif
117
118 printf(STAT_FNAME "\\(\"%s\", \\{", av[1]);
119 printf("st_dev=makedev\\(%u, %u\\)",
120 (unsigned int) major(stb.st_dev),
121 (unsigned int) minor(stb.st_dev));
122 printf(", st_ino=%llu", (unsigned long long) stb.st_ino);
123 printf(", st_mode=");
124 print_ftype(stb.st_mode);
125 printf("\\|");
126 print_perms(stb.st_mode);
127 printf(", st_nlink=%u", (unsigned int) stb.st_nlink);
128 printf(", st_uid=%u", (unsigned int) stb.st_uid);
129 printf(", st_gid=%u", (unsigned int) stb.st_gid);
130#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
131 printf(", st_blksize=%u", (unsigned int) stb.st_blksize);
132#endif
133#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
134 printf(", st_blocks=%u", (unsigned int) stb.st_blocks);
135#endif
136
137 switch (stb.st_mode & S_IFMT) {
138 case S_IFCHR: case S_IFBLK:
139#ifdef HAVE_STRUCT_STAT_ST_RDEV
140 printf(", st_rdev=makedev\\(%u, %u\\)",
141 (unsigned int) major(stb.st_rdev),
142 (unsigned int) minor(stb.st_rdev));
143#else
144 printf(", st_size=makedev\\(%u, %u\\)",
145 (unsigned int) major(stb.st_size),
146 (unsigned int) minor(stb.st_size));
147#endif
148 break;
149 default:
150 printf(", st_size=%llu", (unsigned long long) stb.st_size);
151 }
152
153 printf(", st_atime=");
154 print_time(stb.st_atime);
155 printf(", st_mtime=");
156 print_time(stb.st_mtime);
157 printf(", st_ctime=");
158 print_time(stb.st_ctime);
159 printf("(, st_flags=[0-9]+)?");
160 printf("(, st_fstype=[^,]*)?");
161 printf("(, st_gen=[0-9]+)?");
162 printf("\\}\\) += 0\n");
163 return 0;
164}
165
166#else /* !STAT_FNAME */
167int main(void)
168{
169 return 77;
170}
171#endif