1*433d6423SLionel Sambuc /* test27: stat() fstat() Author: Jan-Mark Wams (jms@cs.vu.nl) */
2*433d6423SLionel Sambuc
3*433d6423SLionel Sambuc #include <sys/types.h>
4*433d6423SLionel Sambuc #include <sys/stat.h>
5*433d6423SLionel Sambuc #include <fcntl.h>
6*433d6423SLionel Sambuc #include <unistd.h>
7*433d6423SLionel Sambuc #include <stdlib.h>
8*433d6423SLionel Sambuc #include <errno.h>
9*433d6423SLionel Sambuc #include <limits.h>
10*433d6423SLionel Sambuc #include <string.h>
11*433d6423SLionel Sambuc #include <limits.h>
12*433d6423SLionel Sambuc #include <time.h>
13*433d6423SLionel Sambuc #include <stdio.h>
14*433d6423SLionel Sambuc
15*433d6423SLionel Sambuc #define MODE_MASK (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID)
16*433d6423SLionel Sambuc int max_error = 4;
17*433d6423SLionel Sambuc #include "common.h"
18*433d6423SLionel Sambuc
19*433d6423SLionel Sambuc #define ITERATIONS 2
20*433d6423SLionel Sambuc
21*433d6423SLionel Sambuc #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
22*433d6423SLionel Sambuc #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
23*433d6423SLionel Sambuc
24*433d6423SLionel Sambuc
25*433d6423SLionel Sambuc int superuser;
26*433d6423SLionel Sambuc char *MaxName; /* Name of maximum length */
27*433d6423SLionel Sambuc char MaxPath[PATH_MAX];
28*433d6423SLionel Sambuc char *ToLongName; /* Name of maximum +1 length */
29*433d6423SLionel Sambuc char ToLongPath[PATH_MAX + 1];
30*433d6423SLionel Sambuc
31*433d6423SLionel Sambuc void test27a(void);
32*433d6423SLionel Sambuc void test27b(void);
33*433d6423SLionel Sambuc void test27c(void);
34*433d6423SLionel Sambuc void makelongnames(void);
35*433d6423SLionel Sambuc
main(int argc,char * argv[])36*433d6423SLionel Sambuc int main(int argc, char *argv[])
37*433d6423SLionel Sambuc {
38*433d6423SLionel Sambuc int i, m = 0xFFFF;
39*433d6423SLionel Sambuc
40*433d6423SLionel Sambuc start(27);
41*433d6423SLionel Sambuc if (argc == 2) m = atoi(argv[1]);
42*433d6423SLionel Sambuc superuser = (getuid() == 0);
43*433d6423SLionel Sambuc makelongnames();
44*433d6423SLionel Sambuc
45*433d6423SLionel Sambuc for (i = 0; i < ITERATIONS; i++) {
46*433d6423SLionel Sambuc if (m & 0001) test27a();
47*433d6423SLionel Sambuc if (m & 0002) test27b();
48*433d6423SLionel Sambuc if (m & 0004) test27c();
49*433d6423SLionel Sambuc }
50*433d6423SLionel Sambuc quit();
51*433d6423SLionel Sambuc
52*433d6423SLionel Sambuc return(-1); /* Unreachable */
53*433d6423SLionel Sambuc }
54*433d6423SLionel Sambuc
test27a()55*433d6423SLionel Sambuc void test27a()
56*433d6423SLionel Sambuc { /* Test Normal operation. */
57*433d6423SLionel Sambuc struct stat st1, st2;
58*433d6423SLionel Sambuc time_t time1, time2;
59*433d6423SLionel Sambuc int fd, pfd[2];
60*433d6423SLionel Sambuc
61*433d6423SLionel Sambuc subtest = 1;
62*433d6423SLionel Sambuc
63*433d6423SLionel Sambuc time(&time1); /* get time before */
64*433d6423SLionel Sambuc while (time1 >= time((time_t *)0))
65*433d6423SLionel Sambuc ; /* Wait for time to change. */
66*433d6423SLionel Sambuc System("echo 7bytes > foo; chmod 4750 foo");
67*433d6423SLionel Sambuc if (stat("foo", &st1) != 0) e(1); /* get foo's info */
68*433d6423SLionel Sambuc time(&time2);
69*433d6423SLionel Sambuc while (time2 >= time((time_t *)0))
70*433d6423SLionel Sambuc ; /* Wait for next second. */
71*433d6423SLionel Sambuc time(&time2); /* get time after */
72*433d6423SLionel Sambuc if ((st1.st_mode & MODE_MASK) != 04750) e(2);
73*433d6423SLionel Sambuc if (st1.st_nlink != 1) e(3); /* check stat */
74*433d6423SLionel Sambuc if (st1.st_uid != geteuid()) e(4);
75*433d6423SLionel Sambuc #if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
76*433d6423SLionel Sambuc if (st1.st_gid != getegid()) e(5);
77*433d6423SLionel Sambuc #endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */
78*433d6423SLionel Sambuc if (st1.st_size != (size_t) 7) e(6);
79*433d6423SLionel Sambuc if (st1.st_atime <= time1) e(7);
80*433d6423SLionel Sambuc if (st1.st_atime >= time2) e(8);
81*433d6423SLionel Sambuc if (st1.st_ctime <= time1) e(9);
82*433d6423SLionel Sambuc if (st1.st_ctime >= time2) e(10);
83*433d6423SLionel Sambuc if (st1.st_mtime <= time1) e(11);
84*433d6423SLionel Sambuc if (st1.st_mtime >= time2) e(12);
85*433d6423SLionel Sambuc
86*433d6423SLionel Sambuc /* Compair stat and fstat. */
87*433d6423SLionel Sambuc System("echo 7bytes > bar");
88*433d6423SLionel Sambuc fd = open("bar", O_RDWR | O_APPEND); /* the bar is open! */
89*433d6423SLionel Sambuc if (fd != 3) e(13); /* should be stderr + 1 */
90*433d6423SLionel Sambuc if (stat("bar", &st1) != 0) e(14); /* get bar's info */
91*433d6423SLionel Sambuc if (fstat(fd, &st2) != 0) e(15); /* get bar's info */
92*433d6423SLionel Sambuc
93*433d6423SLionel Sambuc /* St1 en st2 should be the same. */
94*433d6423SLionel Sambuc if (st1.st_dev != st2.st_dev) e(16);
95*433d6423SLionel Sambuc if (st1.st_ino != st2.st_ino) e(17);
96*433d6423SLionel Sambuc if (st1.st_mode != st2.st_mode) e(18);
97*433d6423SLionel Sambuc if (st1.st_nlink != st2.st_nlink) e(19);
98*433d6423SLionel Sambuc if (st1.st_uid != st2.st_uid) e(20);
99*433d6423SLionel Sambuc if (st1.st_gid != st2.st_gid) e(21);
100*433d6423SLionel Sambuc if (st1.st_size != st2.st_size) e(22);
101*433d6423SLionel Sambuc if (st1.st_atime != st2.st_atime) e(23);
102*433d6423SLionel Sambuc if (st1.st_ctime != st2.st_ctime) e(24);
103*433d6423SLionel Sambuc if (st1.st_mtime != st2.st_mtime) e(25);
104*433d6423SLionel Sambuc time(&time1); /* wait a sec. */
105*433d6423SLionel Sambuc while (time1 >= time((time_t *)0))
106*433d6423SLionel Sambuc ;
107*433d6423SLionel Sambuc System("chmod 755 bar"); /* chainge mode */
108*433d6423SLionel Sambuc System("rm -f foobar; ln bar foobar"); /* chainge # links */
109*433d6423SLionel Sambuc if (write(fd, "foo", 4) != 4) e(26); /* write a bit (or two) */
110*433d6423SLionel Sambuc if (stat("bar", &st2) != 0) e(27); /* get new info */
111*433d6423SLionel Sambuc if (st2.st_dev != st1.st_dev) e(28);
112*433d6423SLionel Sambuc if (st2.st_ino != st1.st_ino) e(29); /* compair the fealds */
113*433d6423SLionel Sambuc if ((st2.st_mode & MODE_MASK) != 0755) e(30);
114*433d6423SLionel Sambuc if (!S_ISREG(st2.st_mode)) e(31);
115*433d6423SLionel Sambuc if (st2.st_nlink != st1.st_nlink + 1) e(32);
116*433d6423SLionel Sambuc if (st2.st_uid != st1.st_uid) e(33);
117*433d6423SLionel Sambuc if (st2.st_gid != st1.st_gid) e(34);
118*433d6423SLionel Sambuc if (st2.st_size != (size_t) 11) e(35);
119*433d6423SLionel Sambuc if (st2.st_atime != st1.st_atime) e(36);
120*433d6423SLionel Sambuc if (st2.st_ctime <= st1.st_ctime) e(37);
121*433d6423SLionel Sambuc if (st2.st_mtime <= st1.st_mtime) e(38);
122*433d6423SLionel Sambuc if (close(fd) != 0) e(39); /* sorry the bar is closed */
123*433d6423SLionel Sambuc
124*433d6423SLionel Sambuc /* Check special file. */
125*433d6423SLionel Sambuc if (stat("/dev/tty", &st1) != 0) e(40);
126*433d6423SLionel Sambuc if (!S_ISCHR(st1.st_mode)) e(41);
127*433d6423SLionel Sambuc #if defined(__minix) && defined(_NETBSD_SOURCE)
128*433d6423SLionel Sambuc if (stat("/dev/ram", &st1) != 0) e(42);
129*433d6423SLionel Sambuc if (!S_ISBLK(st1.st_mode)) e(43);
130*433d6423SLionel Sambuc #endif
131*433d6423SLionel Sambuc
132*433d6423SLionel Sambuc /* Check fifos. */
133*433d6423SLionel Sambuc time(&time1);
134*433d6423SLionel Sambuc while (time1 >= time((time_t *)0))
135*433d6423SLionel Sambuc ;
136*433d6423SLionel Sambuc if (mkfifo("fifo", 0640) != 0) e(44);
137*433d6423SLionel Sambuc if (stat("fifo", &st1) != 0) e(45); /* get fifo's info */
138*433d6423SLionel Sambuc time(&time2);
139*433d6423SLionel Sambuc while (time2 >= time((time_t *)0))
140*433d6423SLionel Sambuc ;
141*433d6423SLionel Sambuc time(&time2);
142*433d6423SLionel Sambuc if (!S_ISFIFO(st1.st_mode)) e(46);
143*433d6423SLionel Sambuc if (st1.st_nlink != 1) e(47); /* check the stat info */
144*433d6423SLionel Sambuc if (st1.st_uid != geteuid()) e(48);
145*433d6423SLionel Sambuc #if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
146*433d6423SLionel Sambuc if (st1.st_gid != getegid()) e(49);
147*433d6423SLionel Sambuc #endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */
148*433d6423SLionel Sambuc if (st1.st_size != (size_t) 0) e(50);
149*433d6423SLionel Sambuc if (st1.st_atime <= time1) e(51);
150*433d6423SLionel Sambuc if (st1.st_atime >= time2) e(52);
151*433d6423SLionel Sambuc if (st1.st_ctime <= time1) e(53);
152*433d6423SLionel Sambuc if (st1.st_ctime >= time2) e(54);
153*433d6423SLionel Sambuc if (st1.st_mtime <= time1) e(55);
154*433d6423SLionel Sambuc if (st1.st_mtime >= time2) e(56);
155*433d6423SLionel Sambuc
156*433d6423SLionel Sambuc /* Note: the st_mode of a fstat on a pipe should contain a isfifo bit. */
157*433d6423SLionel Sambuc /* Check pipes. */
158*433d6423SLionel Sambuc time(&time1);
159*433d6423SLionel Sambuc while (time1 >= time((time_t *)0))
160*433d6423SLionel Sambuc ;
161*433d6423SLionel Sambuc if (pipe(pfd) != 0) e(57);
162*433d6423SLionel Sambuc if (fstat(pfd[0], &st1) != 0) e(58); /* get pipe input info */
163*433d6423SLionel Sambuc time(&time2);
164*433d6423SLionel Sambuc while (time2 >= time((time_t *)0))
165*433d6423SLionel Sambuc ;
166*433d6423SLionel Sambuc time(&time2);
167*433d6423SLionel Sambuc if (!(S_ISFIFO(st1.st_mode))) e(59); /* check stat struct */
168*433d6423SLionel Sambuc if (st1.st_uid != geteuid()) e(60);
169*433d6423SLionel Sambuc if (st1.st_gid != getegid()) e(61);
170*433d6423SLionel Sambuc if (st1.st_size != (size_t) 0) e(62);
171*433d6423SLionel Sambuc if (st1.st_atime <= time1) e(63);
172*433d6423SLionel Sambuc if (st1.st_atime >= time2) e(64);
173*433d6423SLionel Sambuc if (st1.st_ctime <= time1) e(65);
174*433d6423SLionel Sambuc if (st1.st_ctime >= time2) e(66);
175*433d6423SLionel Sambuc if (st1.st_mtime <= time1) e(67);
176*433d6423SLionel Sambuc if (st1.st_mtime >= time2) e(68);
177*433d6423SLionel Sambuc if (fstat(pfd[1], &st1) != 0) e(69); /* get pipe output info */
178*433d6423SLionel Sambuc if (!(S_ISFIFO(st1.st_mode))) e(70);
179*433d6423SLionel Sambuc if (st1.st_uid != geteuid()) e(71);
180*433d6423SLionel Sambuc if (st1.st_gid != getegid()) e(72);
181*433d6423SLionel Sambuc if (st1.st_size != (size_t) 0) e(73);
182*433d6423SLionel Sambuc if (st1.st_atime < time1) e(74);
183*433d6423SLionel Sambuc if (st1.st_atime > time2) e(75);
184*433d6423SLionel Sambuc if (st1.st_ctime < time1) e(76);
185*433d6423SLionel Sambuc if (st1.st_ctime > time2) e(77);
186*433d6423SLionel Sambuc if (st1.st_mtime < time1) e(78);
187*433d6423SLionel Sambuc if (st1.st_mtime > time2) e(79);
188*433d6423SLionel Sambuc if (close(pfd[0]) != 0) e(80);
189*433d6423SLionel Sambuc if (close(pfd[1]) != 0) e(81);/* close pipe */
190*433d6423SLionel Sambuc
191*433d6423SLionel Sambuc /* Check dirs. */
192*433d6423SLionel Sambuc time(&time1);
193*433d6423SLionel Sambuc while (time1 >= time((time_t *)0))
194*433d6423SLionel Sambuc ;
195*433d6423SLionel Sambuc System("mkdir dir");
196*433d6423SLionel Sambuc if (stat("dir", &st1) != 0) e(82); /* get dir info */
197*433d6423SLionel Sambuc time(&time2);
198*433d6423SLionel Sambuc while (time2 >= time((time_t *)0))
199*433d6423SLionel Sambuc ;
200*433d6423SLionel Sambuc time(&time2);
201*433d6423SLionel Sambuc if (!(S_ISDIR(st1.st_mode))) e(83); /* check stat struct */
202*433d6423SLionel Sambuc if (st1.st_uid != geteuid()) e(84);
203*433d6423SLionel Sambuc #if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
204*433d6423SLionel Sambuc if (st1.st_gid != getegid()) e(85);
205*433d6423SLionel Sambuc #endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */
206*433d6423SLionel Sambuc if (st1.st_atime < time1) e(86);
207*433d6423SLionel Sambuc if (st1.st_atime > time2) e(87);
208*433d6423SLionel Sambuc if (st1.st_ctime < time1) e(88);
209*433d6423SLionel Sambuc if (st1.st_ctime > time2) e(89);
210*433d6423SLionel Sambuc if (st1.st_mtime < time1) e(90);
211*433d6423SLionel Sambuc if (st1.st_mtime > time2) e(91);
212*433d6423SLionel Sambuc System("rm -rf ../DIR_27/*");
213*433d6423SLionel Sambuc }
214*433d6423SLionel Sambuc
test27b()215*433d6423SLionel Sambuc void test27b()
216*433d6423SLionel Sambuc { /* Test maxima. */
217*433d6423SLionel Sambuc struct stat st;
218*433d6423SLionel Sambuc int fd;
219*433d6423SLionel Sambuc
220*433d6423SLionel Sambuc subtest = 2;
221*433d6423SLionel Sambuc
222*433d6423SLionel Sambuc /* Check stats on maximum length files names. */
223*433d6423SLionel Sambuc if (mkdir(MaxName, 0777) != 0) e(1);
224*433d6423SLionel Sambuc if (stat(MaxName, &st) != 0) e(2);
225*433d6423SLionel Sambuc if ((fd = open(MaxName, O_RDONLY)) != 3) e(3);
226*433d6423SLionel Sambuc if (fstat(fd, &st) != 0) e(4);
227*433d6423SLionel Sambuc if (close(fd) != 0) e(5);
228*433d6423SLionel Sambuc if (rmdir(MaxName) != 0) e(6);
229*433d6423SLionel Sambuc if (stat(MaxPath, &st) != 0) e(7);
230*433d6423SLionel Sambuc if ((fd = open(MaxPath, O_RDONLY)) != 3) e(8);
231*433d6423SLionel Sambuc if (fstat(fd, &st) != 0) e(9);
232*433d6423SLionel Sambuc if (close(fd) != 0) e(10);
233*433d6423SLionel Sambuc System("rm -rf ../DIR_27/*");
234*433d6423SLionel Sambuc }
235*433d6423SLionel Sambuc
test27c()236*433d6423SLionel Sambuc void test27c()
237*433d6423SLionel Sambuc { /* Test error response. */
238*433d6423SLionel Sambuc struct stat st;
239*433d6423SLionel Sambuc int fd, i;
240*433d6423SLionel Sambuc
241*433d6423SLionel Sambuc subtest = 3;
242*433d6423SLionel Sambuc
243*433d6423SLionel Sambuc System("echo Hi > foo"); /* Make a file called foo. */
244*433d6423SLionel Sambuc /* Check if a un searchable dir is handled ok. */
245*433d6423SLionel Sambuc Chdir(".."); /* cd .. */
246*433d6423SLionel Sambuc System("chmod 677 DIR_27"); /* no search permission */
247*433d6423SLionel Sambuc if (stat("DIR_27/nono", &st) != -1) e(1);
248*433d6423SLionel Sambuc if (superuser) {
249*433d6423SLionel Sambuc if (errno != ENOENT) e(2); /* su has access */
250*433d6423SLionel Sambuc }
251*433d6423SLionel Sambuc if (!superuser) {
252*433d6423SLionel Sambuc if (errno != EACCES) e(3); /* we don't ;-) */
253*433d6423SLionel Sambuc }
254*433d6423SLionel Sambuc System("chmod 777 DIR_27");
255*433d6423SLionel Sambuc Chdir("DIR_27"); /* back to test dir */
256*433d6423SLionel Sambuc
257*433d6423SLionel Sambuc /* Check on ToLongName etc. */
258*433d6423SLionel Sambuc if (stat(ToLongPath, &st) != -1) e(6); /* path is too long */
259*433d6423SLionel Sambuc if (errno != ENAMETOOLONG) e(7);
260*433d6423SLionel Sambuc
261*433d6423SLionel Sambuc /* Test some common errors. */
262*433d6423SLionel Sambuc if (stat("nono", &st) != -1) e(8); /* nono nonexistent */
263*433d6423SLionel Sambuc if (errno != ENOENT) e(9);
264*433d6423SLionel Sambuc if (stat("", &st) != -1) e(10); /* try empty */
265*433d6423SLionel Sambuc if (errno != ENOENT) e(11);
266*433d6423SLionel Sambuc if (stat("foo/bar", &st) != -1) e(12); /* foo is a file */
267*433d6423SLionel Sambuc if (errno != ENOTDIR) e(13);
268*433d6423SLionel Sambuc
269*433d6423SLionel Sambuc /* Test fstat on file descriptors that are not open. */
270*433d6423SLionel Sambuc for (i = 3; i < 6; i++) {
271*433d6423SLionel Sambuc if (fstat(i, &st) != -1) e(14);
272*433d6423SLionel Sambuc if (errno != EBADF) e(15);
273*433d6423SLionel Sambuc }
274*433d6423SLionel Sambuc
275*433d6423SLionel Sambuc /* Test if a just closed file is `fstat()'-able. */
276*433d6423SLionel Sambuc if ((fd = open("foo", O_RDONLY)) != 3) e(16); /* open foo */
277*433d6423SLionel Sambuc if (fstat(fd, &st) != 0) e(17); /* get stat */
278*433d6423SLionel Sambuc if (close(fd) != 0) e(18); /* close it */
279*433d6423SLionel Sambuc if (fstat(fd, &st) != -1) e(19); /* get stat */
280*433d6423SLionel Sambuc if (errno != EBADF) e(20);
281*433d6423SLionel Sambuc System("rm -rf ../DIR_27/*");
282*433d6423SLionel Sambuc }
283*433d6423SLionel Sambuc
makelongnames()284*433d6423SLionel Sambuc void makelongnames()
285*433d6423SLionel Sambuc {
286*433d6423SLionel Sambuc register int i;
287*433d6423SLionel Sambuc int max_name_length;
288*433d6423SLionel Sambuc
289*433d6423SLionel Sambuc max_name_length = name_max("."); /* Aka NAME_MAX, but not every FS supports
290*433d6423SLionel Sambuc * the same length, hence runtime check */
291*433d6423SLionel Sambuc MaxName = malloc(max_name_length + 1);
292*433d6423SLionel Sambuc ToLongName = malloc(max_name_length + 1 + 1); /* Name of maximum +1 length */
293*433d6423SLionel Sambuc memset(MaxName, 'a', max_name_length);
294*433d6423SLionel Sambuc MaxName[max_name_length] = '\0';
295*433d6423SLionel Sambuc
296*433d6423SLionel Sambuc for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */
297*433d6423SLionel Sambuc MaxPath[i++] = '.';
298*433d6423SLionel Sambuc MaxPath[i] = '/';
299*433d6423SLionel Sambuc }
300*433d6423SLionel Sambuc MaxPath[PATH_MAX - 1] = '\0';
301*433d6423SLionel Sambuc
302*433d6423SLionel Sambuc strcpy(ToLongName, MaxName); /* copy them Max to ToLong */
303*433d6423SLionel Sambuc strcpy(ToLongPath, MaxPath);
304*433d6423SLionel Sambuc
305*433d6423SLionel Sambuc ToLongName[max_name_length] = 'a';
306*433d6423SLionel Sambuc ToLongName[max_name_length+1] = '\0';/* extend ToLongName by one too many */
307*433d6423SLionel Sambuc ToLongPath[PATH_MAX - 1] = '/';
308*433d6423SLionel Sambuc ToLongPath[PATH_MAX] = '\0'; /* inc ToLongPath by one */
309*433d6423SLionel Sambuc }
310*433d6423SLionel Sambuc
311