source: trunk/minix/test/test32.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 9.9 KB
Line 
1/* test32: rename() Author: Jan-Mark Wams (jms@cs.vu.nl) */
2
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <sys/wait.h>
6#include <stdlib.h>
7#include <unistd.h>
8#include <string.h>
9#include <fcntl.h>
10#include <limits.h>
11#include <errno.h>
12#include <time.h>
13#include <stdio.h>
14
15#define MAX_ERROR 4
16#define ITERATIONS 2
17
18#define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
19#define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
20#define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a)
21#define Creat(f) if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f)
22
23int errct = 0;
24int subtest = 1;
25int superuser;
26char MaxName[NAME_MAX + 1]; /* Name of maximum length */
27char MaxPath[PATH_MAX]; /* Same for path */
28char ToLongName[NAME_MAX + 2]; /* Name of maximum +1 length */
29char ToLongPath[PATH_MAX + 1]; /* Same for path, both too long */
30
31_PROTOTYPE(void main, (int argc, char *argv[]));
32_PROTOTYPE(void test32a, (void));
33_PROTOTYPE(void test32b, (void));
34_PROTOTYPE(void test32c, (void));
35_PROTOTYPE(void makelongnames, (void));
36_PROTOTYPE(void e, (int number));
37_PROTOTYPE(void quit, (void));
38
39void main(argc, argv)
40int argc;
41char *argv[];
42{
43 int i, m = 0xFFFF;
44
45 sync();
46 if (argc == 2) m = atoi(argv[1]);
47 printf("Test 32 ");
48 fflush(stdout);
49 System("rm -rf DIR_32; mkdir DIR_32");
50 Chdir("DIR_32");
51 makelongnames();
52 superuser = (geteuid() == 0);
53
54 for (i = 0; i < ITERATIONS; i++) {
55 if (m & 0001) test32a();
56 if (m & 0002) test32b();
57 if (m & 0004) test32c();
58 }
59 quit();
60}
61
62#define BUF_SIZE 1024
63
64void test32a()
65{ /* Test normal operation. */
66 struct stat st1, st2;
67 int fd1, fd2;
68 time_t time1, time2, time3;
69 char buf[BUF_SIZE];
70
71 subtest = 1;
72 System("rm -rf ../DIR_32/*");
73
74 /* Test normal file renamal. */
75 System("echo haha > old");
76 Stat("old", &st1);
77 if (rename("old", "new") != 0) e(1);
78 Stat("new", &st2);
79
80 /* The status of new should be the same as old. */
81 if (st1.st_dev != st2.st_dev) e(2);
82 if (st1.st_ino != st2.st_ino) e(3);
83 if (st1.st_mode != st2.st_mode) e(4);
84 if (st1.st_nlink != st2.st_nlink) e(5);
85 if (st1.st_uid != st2.st_uid) e(6);
86 if (st1.st_gid != st2.st_gid) e(7);
87 if (st1.st_rdev != st2.st_rdev) e(8);
88 if (st1.st_size != st2.st_size) e(9);
89 if (st1.st_atime != st2.st_atime) e(10);
90 if (st1.st_mtime != st2.st_mtime) e(11);
91 if (st1.st_ctime != st2.st_ctime) e(12);
92
93 /* If new exists, it should be removed. */
94 System("ln new new2");
95 System("echo foobar > old");
96 Stat("old", &st1);
97 if (rename("old", "new") != 0) e(13);
98 Stat("new", &st2);
99
100 /* The status of new should be the same as old. */
101 if (st1.st_dev != st2.st_dev) e(14);
102 if (st1.st_ino != st2.st_ino) e(15);
103 if (st1.st_mode != st2.st_mode) e(16);
104 if (st1.st_nlink != st2.st_nlink) e(17);
105 if (st1.st_uid != st2.st_uid) e(18);
106 if (st1.st_gid != st2.st_gid) e(19);
107 if (st1.st_rdev != st2.st_rdev) e(20);
108 if (st1.st_size != st2.st_size) e(21);
109 if (st1.st_atime != st2.st_atime) e(22);
110 if (st1.st_mtime != st2.st_mtime) e(23);
111 if (st1.st_ctime != st2.st_ctime) e(24);
112
113 /* The link count on new2 should be one since the old new is removed. */
114 Stat("new2", &st1);
115 if (st1.st_nlink != 1) e(25);
116
117 /* Check if status for "." is updated. */
118 System("> OLD");
119 Stat(".", &st1);
120 time(&time1);
121 while (time1 == time((time_t *)0))
122 ;
123 time(&time2);
124 rename("OLD", "NEW");
125 Stat(".", &st2);
126 time(&time3);
127 while (time3 == time((time_t *)0))
128 ;
129 time(&time3);
130 if (st1.st_ctime >= st2.st_ctime) e(26);
131 if (st1.st_mtime >= st2.st_mtime) e(27);
132 if (st1.st_ctime > time1) e(28);
133 if (st1.st_mtime > time1) e(29);
134 if (st1.st_ctime >= time2) e(30);
135 if (st1.st_mtime >= time2) e(31);
136 if (st2.st_ctime < time2) e(32);
137 if (st2.st_mtime < time2) e(33);
138 if (st2.st_ctime >= time3) e(34);
139 if (st2.st_mtime >= time3) e(35);
140
141 /* If the new file is removed while it's open it should still be
142 * readable. */
143 System("rm -rf new NEW old OLD");
144 if ((fd1 = creat("new", 0644)) != 3) e(36);
145 if (write(fd1, "Hi there! I am Sammy the string", 33) != 33) e(37);
146 if (close(fd1) != 0) e(38);
147 if ((fd1 = creat("old", 0644)) != 3) e(39);
148 if (write(fd1, "I need a new name", 18) != 18) e(40);
149 if (close(fd1) != 0) e(41);
150 if ((fd1 = open("new", O_RDONLY)) != 3) e(42);
151 if ((fd2 = open("new", O_RDONLY)) != 4) e(43);
152 if (rename("old", "new") != 0) e(44);
153 if (stat("old", &st1) == 0) e(45);
154 if (close(fd1) != 0) e(46);
155 if ((fd1 = open("new", O_RDONLY)) != 3) e(47);
156 if (read(fd2, buf, BUF_SIZE) != 33) e(48);
157 if (strcmp(buf, "Hi there! I am Sammy the string") != 0) e(49);
158 if (read(fd1, buf, BUF_SIZE) != 18) e(50);
159 if (strcmp(buf, "I need a new name") != 0) e(51);
160 if (close(fd1) != 0) e(52);
161 if (close(fd2) != 0) e(53);
162}
163
164void test32b()
165{
166 char MaxPath2[PATH_MAX]; /* Same for path */
167 char MaxName2[NAME_MAX + 1]; /* Name of maximum length */
168 int fd, i;
169 int stat_loc;
170 struct stat st;
171
172 subtest = 2;
173 System("rm -rf ../DIR_32/*");
174
175 /* Test maximal file name length. */
176 if ((fd = creat(MaxName, 0777)) != 3) e(1);
177 if (close(fd) != 0) e(2);
178 strcpy(MaxName2, MaxName);
179 MaxName2[strlen(MaxName2) - 1] ^= 1;
180 if (rename(MaxName, MaxName2) != 0) e(3);
181 if (rename(MaxName2, MaxName) != 0) e(4);
182 MaxName2[strlen(MaxName2) - 1] ^= 2;
183 if (rename(MaxName, MaxName2) != 0) e(5);
184 MaxPath[strlen(MaxPath) - 2] = '/';
185 MaxPath[strlen(MaxPath) - 1] = 'a'; /* make ././.../a */
186 if ((fd = creat(MaxPath, 0777)) != 3) e(6);
187 if (close(fd) != 0) e(7);
188 strcpy(MaxPath2, MaxPath);
189 MaxPath2[strlen(MaxPath2) - 1] ^= 1;
190 if (rename(MaxPath, MaxPath2) != 0) e(8);
191 if (rename(MaxPath2, MaxPath) != 0) e(9);
192 MaxPath2[strlen(MaxPath2) - 1] ^= 2;
193 if (rename(MaxPath, MaxPath2) != 0) e(10);
194 MaxPath[strlen(MaxPath) - 1] = '/'; /* make ././.../a */
195
196 /* Test if linked files are renamable. */
197 System("> foo; ln foo bar");
198 if (rename("foo", "bar") != 0) e(11);
199 if (rename("bar", "foo") != 0) e(12);
200 System("ln foo foobar");
201 if (rename("foo", "foobar") != 0) e(13);
202 if (rename("bar", "foobar") != 0) e(14);
203
204 /* Since the same files have the same links.... */
205 if (rename("bar", "bar") != 0) e(15);
206 if (rename("foo", "foo") != 0) e(16);
207 if (rename("foobar", "foobar") != 0) e(17);
208
209 /* In ``rename(old, new)'' with new existing, there is always an new
210 * entry. */
211 for (i = 0; i < 5; i++) {
212 System("echo old > old");
213 System("echo news > new");
214 switch (fork()) {
215 case -1: printf("Can't fork\n"); break;
216 case 0:
217 alarm(20);
218 sleep(1);
219 rename("old", "new");
220 exit(0);
221 default:
222 while (stat("old", &st) != 0)
223 if (stat("new", &st) != 0) e(18);
224 wait(&stat_loc);
225 if (stat_loc != 0) e(19); /* Alarm? */
226 }
227 }
228
229}
230
231void test32c()
232{ /* Test behavior under error contitions. */
233 struct stat st1;
234 int stat_loc;
235
236 subtest = 3;
237 System("rm -rf ../DIR_32/*");
238
239 /* Test if we have access. */
240 system("chmod 777 noacc nowrite > /dev/null 2>/dev/null");
241 system("rm -rf noacc nowrite");
242
243 System("mkdir noacc nowrite");
244 System("> noacc/file");
245 System("> nowrite/file");
246 System("> file");
247 System("chmod 677 noacc");
248 System("chmod 577 nowrite");
249 if (!superuser) {
250 if (rename("noacc/file", "nono") != -1) e(1);
251 if (errno != EACCES) e(2);
252 if (rename("nowrite/file", "nono") != -1) e(3);
253 if (errno != EACCES) e(4);
254 if (rename("file", "noacc/file") != -1) e(5);
255 if (errno != EACCES) e(6);
256 if (rename("file", "nowrite/file") != -1) e(7);
257 if (errno != EACCES) e(8);
258 }
259 if (superuser) {
260 /* Super user heeft access. */
261 if (rename("noacc/file", "noacc/yes") != 0) e(9);
262 if (rename("nowrite/file", "nowrite/yes") != 0) e(10);
263 if (rename("file", "yes") != 0) e(11);
264 if (rename("noacc/yes", "noacc/file") != 0) e(12);
265 if (rename("nowrite/yes", "nowrite/file") != 0) e(13);
266 if (rename("yes", "file") != 0) e(14);
267 }
268 System("chmod 777 noacc nowrite");
269
270 /* If rmdir() doesn't remove a directory, rename() shouldn't eighter. */
271 System("mkdir newdir olddir");
272 System("rm -rf /tmp/sema.11[ab]");
273 switch (fork()) {
274 case -1: printf("Can't fork\n"); break;
275 case 0:
276 alarm(20);
277 switch (fork()) {
278 case -1: printf("Can't fork\n"); break;
279 case 0:
280 /* Child A. */
281 alarm(20);
282 if (chdir("newdir") != 0) e(15);
283 Creat("/tmp/sema.11a");
284 while (stat("/tmp/sema.11a", &st1) == -1) sleep(1);
285 exit(0);
286 default:
287 wait(&stat_loc);
288 if (stat_loc != 0) e(16); /* Alarm? */
289 }
290
291 /* Child B. */
292 if (chdir("olddir") != 0) e(17);
293 Creat("/tmp/sema.11b");
294 while (stat("/tmp/sema.11b", &st1) == -1) sleep(1);
295 exit(0);
296 default:
297 /* Wait for child A. It will keep ``newdir'' bussy. */
298 while (stat("/tmp/sema.11a", &st1) == -1) sleep(1);
299 if (rmdir("newdir") == -1) {
300 if (rename("olddir", "newdir") != -1) e(18);
301 if (errno != EBUSY) e(19);
302 }
303 (void) unlink("/tmp/sema.11a");
304
305 /* Wait for child B. It will keep ``olddir'' bussy. */
306 while (stat("/tmp/sema.11b", &st1) == -1) sleep(1);
307 if (rmdir("olddir") == -1) {
308 if (rename("olddir", "newdir") != -1) e(20);
309 if (errno != EBUSY) e(21);
310 }
311 (void) unlink("/tmp/sema.11b");
312 wait(&stat_loc);
313 if (stat_loc != 0) e(22); /* Alarm? */
314 }
315}
316
317void makelongnames()
318{
319 register int i;
320
321 memset(MaxName, 'a', NAME_MAX);
322 MaxName[NAME_MAX] = '\0';
323 for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */
324 MaxPath[i++] = '.';
325 MaxPath[i] = '/';
326 }
327 MaxPath[PATH_MAX - 1] = '\0';
328
329 strcpy(ToLongName, MaxName); /* copy them Max to ToLong */
330 strcpy(ToLongPath, MaxPath);
331
332 ToLongName[NAME_MAX] = 'a';
333 ToLongName[NAME_MAX + 1] = '\0'; /* extend ToLongName by one too many */
334 ToLongPath[PATH_MAX - 1] = '/';
335 ToLongPath[PATH_MAX] = '\0'; /* inc ToLongPath by one */
336}
337
338void e(n)
339int n;
340{
341 int err_num = errno; /* Save in case printf clobbers it. */
342
343 printf("Subtest %d, error %d errno=%d: ", subtest, n, errno);
344 errno = err_num;
345 perror("");
346 if (errct++ > MAX_ERROR) {
347 printf("Too many errors; test aborted\n");
348 chdir("..");
349 system("rm -rf DIR*");
350 exit(1);
351 }
352 errno = 0;
353}
354
355void quit()
356{
357 Chdir("..");
358 System("rm -rf DIR_32");
359
360 if (errct == 0) {
361 printf("ok\n");
362 exit(0);
363 } else {
364 printf("%d errors\n", errct);
365 exit(1);
366 }
367}
Note: See TracBrowser for help on using the repository browser.