1 /* Test for getdents().
2 * Just tests whatever FS the test is executed from.
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.
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
},
38 int seen
[FILETYPES
][LOOPS
];
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.
44 #define CR(f, call, modebit) do { \
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); } \
53 main(int argc
, char **argv
)
63 for(i
= 0; i
< LOOPS
; i
++) {
64 for(t
= 0; t
< FILETYPES
; t
++) {
67 mode_t m
= filetypes
[t
].modebit
;
69 /* think of a filename; do varying lengths to check
70 * dirent record length alignment issues
73 snprintf(fn
, sizeof(fn
), "%d.%d.%d.", t
, filetypes
[t
].dt
, i
);
74 for(c
= 0; c
< i
; c
++) strcat(fn
, "x");
76 /* create the right type */
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;
90 /* Verify that readdir() returns dirent structs with reasonable contents */
92 if(!(dir
= opendir("."))) { e(20); return 1; }
94 while((de
= readdir(dir
))) {
98 if(!strcmp(de
->d_name
, ".")) continue;
99 if(!strcmp(de
->d_name
, "..")) continue;
101 if(sscanf(de
->d_name
, "%d.%d.%d", &t
, &dt
, &i
) != 3) {
106 /* sanity check on filename numbers */
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; }
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; }
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.
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); }
127 if(closedir(dir
) < 0) e(50);
129 /* Verify that we have seen all files we expected to see. */
131 for(i
= 0; i
< LOOPS
; i
++) {
132 for(t
= 0; t
< FILETYPES
; t
++) {
133 if(!seen
[t
][i
]) { e(60); break; }