1 /* Test for getdents().
2 * Just tests whatever FS the test is executed from.
3 *
4 * This test creates lots of nodes of various types, verifies that readdir()
5 * (and so getdents()) returns all of them exactly once, and nothing else
6 * (except for "." and ".."), and verifies the struct dirents are correct.
7 */
8
9 #include <sys/types.h>
10 #include <sys/stat.h>
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <dirent.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18
19 #include "common.h"
20
21 #define FILETYPES 6
22
23 #define LOOPS 30
24
25 struct filetype {
26 char *fnbase; /* type-unique base name */
27 int dt; /* dirent type that getdents() should return */
28 mode_t modebit; /* mode bit unique to this type */
29 } filetypes[FILETYPES] = {
30 { "fifo", DT_FIFO, S_IFIFO },
31 { "chr", DT_CHR, S_IFCHR },
32 { "dir", DT_DIR, S_IFDIR },
33 { "blk", DT_BLK, S_IFBLK },
34 { "reg", DT_REG, S_IFREG },
35 { "lnk", DT_LNK, S_IFLNK },
36 };
37
38 int seen[FILETYPES][LOOPS];
39
40 /* create a node named 'f' using code 'call'. check it doesn't exist
41 * before hand, and does exist afterwards, and has the expected modebit.
42 */
43
44 #define CR(f, call, modebit) do { \
45 struct stat sb; \
46 if(lstat(f, &sb) >= 0) { e(1); } \
47 if((call) < 0) { e(2); } \
48 if(lstat(f, &sb) < 0) { e(3); } \
49 if(!(sb.st_mode & (modebit))) { e(4); } \
50 } while(0)
51
52 int
main(int argc,char ** argv)53 main(int argc, char **argv)
54 {
55 int i, t;
56 DIR *dir;
57 struct dirent *de;
58
59 start(78);
60
61 /* create contents */
62
63 for(i = 0; i < LOOPS; i++) {
64 for(t = 0; t < FILETYPES; t++) {
65 int c;
66 char fn[2000];
67 mode_t m = filetypes[t].modebit;
68
69 /* think of a filename; do varying lengths to check
70 * dirent record length alignment issues
71 */
72
73 snprintf(fn, sizeof(fn), "%d.%d.%d.", t, filetypes[t].dt, i);
74 for(c = 0; c < i; c++) strcat(fn, "x");
75
76 /* create the right type */
77
78 switch(filetypes[t].dt) {
79 case DT_FIFO: CR(fn, mknod(fn, 0600|S_IFIFO, 0), m); break;
80 case DT_CHR: CR(fn, mknod(fn, 0600|S_IFCHR, 0), m); break;
81 case DT_BLK: CR(fn, mknod(fn, 0600|S_IFBLK, 0), m); break;
82 case DT_REG: CR(fn, mknod(fn, 0600|S_IFREG, 0), m); break;
83 case DT_DIR: CR(fn, mkdir(fn, 0600), m); break;
84 case DT_LNK: CR(fn, symlink("dest", fn), m); break;
85 default: e(10); break;
86 }
87 }
88 }
89
90 /* Verify that readdir() returns dirent structs with reasonable contents */
91
92 if(!(dir = opendir("."))) { e(20); return 1; }
93
94 while((de = readdir(dir))) {
95 int dt;
96 struct stat sb;
97
98 if(!strcmp(de->d_name, ".")) continue;
99 if(!strcmp(de->d_name, "..")) continue;
100
101 if(sscanf(de->d_name, "%d.%d.%d", &t, &dt, &i) != 3) {
102 e(30);
103 continue;
104 }
105
106 /* sanity check on filename numbers */
107
108 if(t < 0 || dt < 0 || i < 0) { e(31); continue; }
109 if(t >= FILETYPES || i >= LOOPS) { e(32); continue; }
110 if(seen[t][i]) { e(33); continue; }
111 seen[t][i] = 1;
112 if(filetypes[t].dt != dt) { e(34); continue; }
113 if(lstat(de->d_name, &sb) < 0) { e(35); continue; }
114 if(!(sb.st_mode & filetypes[t].modebit)) { e(36); continue; }
115
116 /* Now we know this file is ours and has the expected type;
117 * now we can verify the contents of the dirent struct. d_name
118 * is OK because sscanf and stat worked on it.
119 */
120
121 if(de->d_type != dt) { e(37); }
122 if(de->d_fileno != sb.st_ino) { e(38); }
123 if(de->d_namlen != strlen(de->d_name)) { e(39); }
124 if(de->d_reclen != _DIRENT_RECLEN(de, de->d_namlen)) { e(40); }
125 }
126
127 if(closedir(dir) < 0) e(50);
128
129 /* Verify that we have seen all files we expected to see. */
130
131 for(i = 0; i < LOOPS; i++) {
132 for(t = 0; t < FILETYPES; t++) {
133 if(!seen[t][i]) { e(60); break; }
134 }
135 }
136
137 quit();
138 }
139