1 /* test40: link() unlink() Aithor: Jan-Mark Wams (jms@cs.vu.nl) */
4 * Not tested readonly file systems
6 * Not tested unlinking bussy files
23 char MaxName
[NAME_MAX
+ 1]; /* Name of maximum length */
24 char MaxPath
[PATH_MAX
]; /* Same for path */
25 char ToLongName
[NAME_MAX
+ 2]; /* Name of maximum +1 length */
26 char ToLongPath
[PATH_MAX
+ 1]; /* Same for path, both too long */
29 #define ITERATIONS 2 /* LINK_MAX is high, so time consuming. */
31 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
32 #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
33 #define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a)
35 _PROTOTYPE(void main
, (int argc
, char *argv
[]));
36 _PROTOTYPE(void test40a
, (void));
37 _PROTOTYPE(void test40b
, (void));
38 _PROTOTYPE(void test40c
, (void));
39 _PROTOTYPE(int stateq
, (struct stat
*stp1
, struct stat
*stp2
));
40 _PROTOTYPE(void makelongnames
, (void));
41 _PROTOTYPE(void e
, (int __n
));
42 _PROTOTYPE(void quit
, (void));
51 if (argc
== 2) m
= atoi(argv
[1]);
54 System("rm -rf DIR_40; mkdir DIR_40");
56 superuser
= (getuid() == 0);
59 for (i
= 0; i
< ITERATIONS
; i
++) {
60 if (m
& 0001) test40a();
61 if (m
& 0002) test40b();
62 if (m
& 0004) test40c();
68 { /* Test normal operation. */
69 struct stat st1
, st2
, st3
;
74 /* Clean up any residu. */
75 System("rm -rf ../DIR_40/*");
77 System("touch foo"); /* make source file */
78 Stat("foo", &st1
); /* get info of foo */
79 Stat(".", &st2
); /* and the cwd */
81 while (time1
>= time((time_t *)0))
83 if (link("foo", "bar") != 0) e(1); /* link foo to bar */
84 Stat("foo", &st3
); /* get new status */
85 if (st1
.st_nlink
+ 1 != st3
.st_nlink
) e(2); /* link count foo up 1 */
87 if (st1
.st_ctime
>= st3
.st_ctime
) e(3); /* check stattime changed */
89 Stat(".", &st1
); /* get parend dir info */
90 if (st2
.st_ctime
>= st1
.st_ctime
) e(4); /* ctime and mtime */
91 if (st2
.st_mtime
>= st1
.st_mtime
) e(5); /* should be updated */
92 Stat("bar", &st2
); /* get info of bar */
93 if (st2
.st_nlink
!= st3
.st_nlink
) e(6); /* link count foo == bar */
94 if (st2
.st_ino
!= st3
.st_ino
) e(7); /* ino should be same */
95 if (st2
.st_mode
!= st3
.st_mode
) e(8); /* check mode same */
96 if (st2
.st_uid
!= st3
.st_uid
) e(9); /* check uid same */
97 if (st2
.st_gid
!= st3
.st_gid
) e(10); /* check gid same */
98 if (st2
.st_size
!= st3
.st_size
) e(11); /* check size */
99 if (st2
.st_ctime
!= st3
.st_ctime
) e(12); /* check ctime */
100 if (st2
.st_atime
!= st3
.st_atime
) e(13); /* check atime */
101 if (st2
.st_mtime
!= st3
.st_mtime
) e(14); /* check mtime */
102 Stat("foo", &st1
); /* get fooinfo */
103 Stat(".", &st2
); /* get dir info */
105 while (time1
>= time((time_t *)0))
107 if (unlink("bar") != 0) e(15);/* rm bar */
108 if (stat("bar", &st2
) != -1) e(16); /* it's gone */
109 Stat("foo", &st3
); /* get foo again */
110 if (st1
.st_nlink
!= st3
.st_nlink
+ 1) e(17); /* link count back to normal */
111 #ifndef V1_FILESYSTEM
112 if (st1
.st_ctime
>= st3
.st_ctime
) e(18); /* check ctime */
114 Stat(".", &st3
); /* get parend dir info */
115 if (st2
.st_ctime
>= st3
.st_ctime
) e(19); /* ctime and mtime */
116 if (st2
.st_mtime
>= st3
.st_mtime
) e(20); /* should be updated */
127 /* Clean up any residu. */
128 System("rm -rf ../DIR_40/*");
130 /* Test what happens if we make LINK_MAX number of links. */
132 for (nlink
= 2; nlink
<= LINK_MAX
; nlink
++) {
133 sprintf(bar
, "bar.%d", nlink
);
134 if (link("foo", bar
) != 0) e(2);
136 if (st
.st_nlink
!= nlink
) e(3);
138 if (st
.st_nlink
!= nlink
) e(4);
141 /* Check if we have LINK_MAX links that are all the same. */
143 if (st
.st_nlink
!= LINK_MAX
) e(5);
144 for (nlink
= 2; nlink
<= LINK_MAX
; nlink
++) {
145 sprintf(bar
, "bar.%d", nlink
);
147 if (!stateq(&st
, &st2
)) e(6);
150 /* Test no more links are possible. */
151 if (link("foo", "nono") != -1) e(7);
152 if (stat("nono", &st
) != -1) e(8);
154 if (st
.st_nlink
!= LINK_MAX
) e(9); /* recheck the number of links */
156 /* Now unlink() the bar.### files */
157 for (nlink
= LINK_MAX
; nlink
>= 2; nlink
--) {
158 sprintf(bar
, "bar.%d", nlink
);
160 if (st
.st_nlink
!= nlink
) e(10);
162 if (!stateq(&st
, &st2
)) e(11);
163 if (unlink(bar
) != 0) e(12);
166 if (st
.st_nlink
!= 1) e(13); /* number of links back to 1 */
168 /* Test max path ed. */
169 if (link("foo", MaxName
) != 0) e(14); /* link to MaxName */
170 if (unlink(MaxName
) != 0) e(15); /* and remove it */
171 MaxPath
[strlen(MaxPath
) - 2] = '/';
172 MaxPath
[strlen(MaxPath
) - 1] = 'a'; /* make ././.../a */
173 if (link("foo", MaxPath
) != 0) e(16); /* it should be */
174 if (unlink(MaxPath
) != 0) e(17); /* (un)linkable */
176 System("rm -f ../DIR_40/*"); /* clean cwd */
183 /* Clean up any residu. */
184 System("rm -rf ../DIR_40/*");
186 /* Check some simple things. */
187 if (link("bar/nono", "nono") != -1) e(1); /* nonexistent */
188 if (errno
!= ENOENT
) e(2);
190 System("touch DIR_40/foo");
191 System("chmod 677 DIR_40"); /* make inaccesable */
193 if (unlink("DIR_40/foo") != -1) e(3);
194 if (errno
!= EACCES
) e(4);
196 if (link("DIR_40/bar/nono", "DIR_40/nono") != -1) e(5); /* nono no be */
198 if (errno
!= ENOENT
) e(6); /* su has access */
201 if (errno
!= EACCES
) e(7); /* we don't ;-) */
203 System("chmod 577 DIR_40"); /* make unwritable */
205 if (link("DIR_40/foo", "DIR_40/nono") != 0) e(8);
206 if (unlink("DIR_40/nono") != 0) e(9);
209 if (link("DIR_40/foo", "DIR_40/nono") != -1) e(10);
210 if (errno
!= EACCES
) e(11);
211 if (unlink("DIR_40/foo") != -1) e(12); /* try to rm foo/foo */
212 if (errno
!= EACCES
) e(13);
214 System("chmod 755 DIR_40"); /* back to normal */
217 /* Too-long path and name test */
218 ToLongPath
[strlen(ToLongPath
) - 2] = '/';
219 ToLongPath
[strlen(ToLongPath
) - 1] = 'a'; /* make ././.../a */
220 if (link("foo", ToLongPath
) != -1) e(18); /* path is too long */
221 if (errno
!= ENAMETOOLONG
) e(19);
222 if (unlink(ToLongPath
) != -1) e(20); /* path is too long */
223 if (errno
!= ENAMETOOLONG
) e(21);
224 if (link("foo", "foo") != -1) e(22); /* try linking foo to foo */
225 if (errno
!= EEXIST
) e(23);
226 if (link("foo", "bar") != 0) e(24); /* make a link to bar */
227 if (link("foo", "bar") != -1) e(25); /* try linking to bar again */
228 if (errno
!= EEXIST
) e(26);
229 if (link("foo", "bar") != -1) e(27); /* try linking to bar again */
230 if (errno
!= EEXIST
) e(28);
231 if (unlink("nono") != -1) e(29); /* try rm <not exist> */
232 if (errno
!= ENOENT
) e(30);
233 if (unlink("") != -1) e(31); /* try unlinking empty */
234 if (errno
!= ENOENT
) e(32);
235 if (link("foo", "") != -1) e(33); /* try linking to "" */
236 if (errno
!= ENOENT
) e(34);
237 if (link("", "foo") != -1) e(35); /* try linking "" */
238 if (errno
!= ENOENT
) e(36);
239 if (link("", "") != -1) e(37);/* try linking "" to "" */
240 if (errno
!= ENOENT
) e(38);
241 if (link("/foo/bar/foo", "a") != -1) e(39); /* try no existing path */
242 if (errno
!= ENOENT
) e(40);
243 if (link("foo", "/foo/bar/foo") != -1) e(41); /* try no existing path */
244 if (errno
!= ENOENT
) e(42);
245 if (link("/a/b/c", "/d/e/f") != -1) e(43); /* try no existing path */
246 if (errno
!= ENOENT
) e(44);
247 if (link("abc", "a") != -1) e(45); /* try no existing file */
248 if (errno
!= ENOENT
) e(46);
249 if (link("foo/bar", "bar") != -1) e(47); /* foo is a file */
250 if (errno
!= ENOTDIR
) e(48);
251 if (link("foo", "foo/bar") != -1) e(49); /* foo is not a dir */
252 if (errno
!= ENOTDIR
) e(50);
253 if (unlink("foo/bar") != -1) e(51); /* foo still no dir */
254 if (errno
!= ENOTDIR
) e(52);
256 if (link(".", "root") != -1) e(55);
257 if (errno
!= EPERM
) e(56); /* noroot can't */
258 if (unlink("root") != -1) e(57);
259 if (errno
!= ENOENT
) e(58);
261 if (mkdir("dir", 0777) != 0) e(59);
263 if (rmdir("dir") != 0) e(63);
266 if (unlink("dir") != -1) e(64);
267 if (errno
!= EPERM
) e(65); /* that ain't w'rkn */
268 if (rmdir("dir") != 0) e(66); /* that's the way to do it */
272 int stateq(stp1
, stp2
)
273 struct stat
*stp1
, *stp2
;
275 if (stp1
->st_dev
!= stp2
->st_dev
) return 0;
276 if (stp1
->st_ino
!= stp2
->st_ino
) return 0;
277 if (stp1
->st_mode
!= stp2
->st_mode
) return 0;
278 if (stp1
->st_nlink
!= stp2
->st_nlink
) return 0;
279 if (stp1
->st_uid
!= stp2
->st_uid
) return 0;
280 if (stp1
->st_gid
!= stp2
->st_gid
) return 0;
281 if (stp1
->st_rdev
!= stp2
->st_rdev
) return 0;
282 if (stp1
->st_size
!= stp2
->st_size
) return 0;
283 if (stp1
->st_atime
!= stp2
->st_atime
) return 0;
284 if (stp1
->st_mtime
!= stp2
->st_mtime
) return 0;
285 if (stp1
->st_ctime
!= stp2
->st_ctime
) return 0;
293 memset(MaxName
, 'a', NAME_MAX
);
294 MaxName
[NAME_MAX
] = '\0';
295 for (i
= 0; i
< PATH_MAX
- 1; i
++) { /* idem path */
299 MaxPath
[PATH_MAX
- 1] = '\0';
301 strcpy(ToLongName
, MaxName
); /* copy them Max to ToLong */
302 strcpy(ToLongPath
, MaxPath
);
304 ToLongName
[NAME_MAX
] = 'a';
305 ToLongName
[NAME_MAX
+ 1] = '\0'; /* extend ToLongName by one
307 ToLongPath
[PATH_MAX
- 1] = '/';
308 ToLongPath
[PATH_MAX
] = '\0'; /* inc ToLongPath by one */
314 int err_num
= errno
; /* Save in case printf clobbers it. */
316 printf("Subtest %d, error %d errno=%d: ", subtest
, n
, errno
);
319 if (errct
++ > MAX_ERROR
) {
320 printf("Too many errors; test aborted\n");
322 system("rm -rf DIR*");
331 system("rm -rf DIR_40");
337 printf("%d errors\n", errct
);