<sys/socket.h>: turn off MSG_NOSIGNAL
[minix3.git] / test / test32.c
blob5fe0c07dc70b3073296c15bdc5fd854e3864b422
1 /* test32: rename() Author: Jan-Mark Wams (jms@cs.vu.nl) */
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>
15 int max_error = 4;
16 #include "common.h"
18 #define ITERATIONS 2
20 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
21 #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
22 #define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a)
23 #define Creat(f) if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f)
26 int superuser;
27 char *MaxName; /* Name of maximum length */
28 char MaxPath[PATH_MAX]; /* Same for path */
29 char *ToLongName; /* Name of maximum +1 length */
30 char ToLongPath[PATH_MAX + 1]; /* Same for path, both too long */
32 void test32a(void);
33 void test32b(void);
34 void test32c(void);
35 void makelongnames(void);
37 int main(int argc, char *argv[])
39 int i, m = 0xFFFF;
41 start(32);
43 if (argc == 2) m = atoi(argv[1]);
44 makelongnames();
45 superuser = (geteuid() == 0);
47 for (i = 0; i < ITERATIONS; i++) {
48 if (m & 0001) test32a();
49 if (m & 0002) test32b();
50 if (m & 0004) test32c();
52 quit();
54 return(-1); /* Unreachable */
57 #define BUF_SIZE 1024
59 void test32a()
60 { /* Test normal operation. */
61 struct stat st1, st2;
62 int fd1, fd2;
63 time_t time1, time2, time3;
64 char buf[BUF_SIZE];
66 subtest = 1;
67 System("rm -rf ../DIR_32/*");
69 /* Test normal file renamal. */
70 System("echo haha > old");
71 Stat("old", &st1);
72 if (rename("old", "new") != 0) e(1);
73 Stat("new", &st2);
75 /* The status of new should be the same as old. */
76 if (st1.st_dev != st2.st_dev) e(2);
77 if (st1.st_ino != st2.st_ino) e(3);
78 if (st1.st_mode != st2.st_mode) e(4);
79 if (st1.st_nlink != st2.st_nlink) e(5);
80 if (st1.st_uid != st2.st_uid) e(6);
81 if (st1.st_gid != st2.st_gid) e(7);
82 if (st1.st_rdev != st2.st_rdev) e(8);
83 if (st1.st_size != st2.st_size) e(9);
84 if (st1.st_atime != st2.st_atime) e(10);
85 if (st1.st_mtime != st2.st_mtime) e(11);
86 if (st1.st_ctime != st2.st_ctime) e(12);
88 /* If new exists, it should be removed. */
89 System("ln new new2");
90 System("echo foobar > old");
91 Stat("old", &st1);
92 if (rename("old", "new") != 0) e(13);
93 Stat("new", &st2);
95 /* The status of new should be the same as old. */
96 if (st1.st_dev != st2.st_dev) e(14);
97 if (st1.st_ino != st2.st_ino) e(15);
98 if (st1.st_mode != st2.st_mode) e(16);
99 if (st1.st_nlink != st2.st_nlink) e(17);
100 if (st1.st_uid != st2.st_uid) e(18);
101 if (st1.st_gid != st2.st_gid) e(19);
102 if (st1.st_rdev != st2.st_rdev) e(20);
103 if (st1.st_size != st2.st_size) e(21);
104 if (st1.st_atime != st2.st_atime) e(22);
105 if (st1.st_mtime != st2.st_mtime) e(23);
106 if (st1.st_ctime != st2.st_ctime) e(24);
108 /* The link count on new2 should be one since the old new is removed. */
109 Stat("new2", &st1);
110 if (st1.st_nlink != 1) e(25);
112 /* Check if status for "." is updated. */
113 System("> OLD");
114 Stat(".", &st1);
115 time(&time1);
116 while (time1 == time((time_t *)0))
118 time(&time2);
119 rename("OLD", "NEW");
120 Stat(".", &st2);
121 time(&time3);
122 while (time3 == time((time_t *)0))
124 time(&time3);
125 if (st1.st_ctime >= st2.st_ctime) e(26);
126 if (st1.st_mtime >= st2.st_mtime) e(27);
127 if (st1.st_ctime > time1) e(28);
128 if (st1.st_mtime > time1) e(29);
129 if (st1.st_ctime >= time2) e(30);
130 if (st1.st_mtime >= time2) e(31);
131 if (st2.st_ctime < time2) e(32);
132 if (st2.st_mtime < time2) e(33);
133 if (st2.st_ctime >= time3) e(34);
134 if (st2.st_mtime >= time3) e(35);
136 /* If the new file is removed while it's open it should still be
137 * readable. */
138 System("rm -rf new NEW old OLD");
139 if ((fd1 = creat("new", 0644)) != 3) e(36);
140 if (write(fd1, "Hi there! I am Sammy the string", 33) != 33) e(37);
141 if (close(fd1) != 0) e(38);
142 if ((fd1 = creat("old", 0644)) != 3) e(39);
143 if (write(fd1, "I need a new name", 18) != 18) e(40);
144 if (close(fd1) != 0) e(41);
145 if ((fd1 = open("new", O_RDONLY)) != 3) e(42);
146 if ((fd2 = open("new", O_RDONLY)) != 4) e(43);
147 if (rename("old", "new") != 0) e(44);
148 if (stat("old", &st1) == 0) e(45);
149 if (close(fd1) != 0) e(46);
150 if ((fd1 = open("new", O_RDONLY)) != 3) e(47);
151 if (read(fd2, buf, BUF_SIZE) != 33) e(48);
152 if (strcmp(buf, "Hi there! I am Sammy the string") != 0) e(49);
153 if (read(fd1, buf, BUF_SIZE) != 18) e(50);
154 if (strcmp(buf, "I need a new name") != 0) e(51);
155 if (close(fd1) != 0) e(52);
156 if (close(fd2) != 0) e(53);
159 void test32b()
161 char MaxPath2[PATH_MAX]; /* Same for path */
162 char MaxName2[NAME_MAX + 1]; /* Name of maximum length */
163 int fd, i;
164 int stat_loc;
165 struct stat st;
167 subtest = 2;
168 System("rm -rf ../DIR_32/*");
170 /* Test maximal file name length. */
171 if ((fd = creat(MaxName, 0777)) != 3) e(1);
172 if (close(fd) != 0) e(2);
173 strcpy(MaxName2, MaxName);
174 MaxName2[strlen(MaxName2) - 1] ^= 1;
175 if (rename(MaxName, MaxName2) != 0) e(3);
176 if (rename(MaxName2, MaxName) != 0) e(4);
177 MaxName2[strlen(MaxName2) - 1] ^= 2;
178 if (rename(MaxName, MaxName2) != 0) e(5);
179 MaxPath[strlen(MaxPath) - 2] = '/';
180 MaxPath[strlen(MaxPath) - 1] = 'a'; /* make ././.../a */
181 if ((fd = creat(MaxPath, 0777)) != 3) e(6);
182 if (close(fd) != 0) e(7);
183 strcpy(MaxPath2, MaxPath);
184 MaxPath2[strlen(MaxPath2) - 1] ^= 1;
185 if (rename(MaxPath, MaxPath2) != 0) e(8);
186 if (rename(MaxPath2, MaxPath) != 0) e(9);
187 MaxPath2[strlen(MaxPath2) - 1] ^= 2;
188 if (rename(MaxPath, MaxPath2) != 0) e(10);
189 MaxPath[strlen(MaxPath) - 1] = '/'; /* make ././.../a */
191 /* Test if linked files are renamable. */
192 System("> foo; ln foo bar");
193 if (rename("foo", "bar") != 0) e(11);
194 if (rename("bar", "foo") != 0) e(12);
195 System("ln foo foobar");
196 if (rename("foo", "foobar") != 0) e(13);
197 if (rename("bar", "foobar") != 0) e(14);
199 /* Since the same files have the same links.... */
200 if (rename("bar", "bar") != 0) e(15);
201 if (rename("foo", "foo") != 0) e(16);
202 if (rename("foobar", "foobar") != 0) e(17);
204 /* In ``rename(old, new)'' with new existing, there is always an new
205 * entry. */
206 for (i = 0; i < 5; i++) {
207 System("echo old > old");
208 System("echo news > new");
209 switch (fork()) {
210 case -1: printf("Can't fork\n"); break;
211 case 0:
212 alarm(20);
213 sleep(1);
214 rename("old", "new");
215 exit(0);
216 default:
217 while (stat("old", &st) == 0)
218 if (stat("new", &st) != 0) e(18);
219 wait(&stat_loc);
220 if (stat_loc != 0) e(19); /* Alarm? */
226 void test32c()
227 { /* Test behavior under error contitions. */
228 struct stat st1;
229 int stat_loc;
231 subtest = 3;
232 System("rm -rf ../DIR_32/*");
234 /* Test if we have access. */
235 system("chmod 777 noacc nowrite > /dev/null 2>/dev/null");
236 system("rm -rf noacc nowrite");
238 System("mkdir noacc nowrite");
239 System("> noacc/file");
240 System("> nowrite/file");
241 System("> file");
242 System("chmod 677 noacc");
243 System("chmod 577 nowrite");
244 if (!superuser) {
245 if (rename("noacc/file", "nono") != -1) e(1);
246 if (errno != EACCES) e(2);
247 if (rename("nowrite/file", "nono") != -1) e(3);
248 if (errno != EACCES) e(4);
249 if (rename("file", "noacc/file") != -1) e(5);
250 if (errno != EACCES) e(6);
251 if (rename("file", "nowrite/file") != -1) e(7);
252 if (errno != EACCES) e(8);
254 if (superuser) {
255 /* Super user heeft access. */
256 if (rename("noacc/file", "noacc/yes") != 0) e(9);
257 if (rename("nowrite/file", "nowrite/yes") != 0) e(10);
258 if (rename("file", "yes") != 0) e(11);
259 if (rename("noacc/yes", "noacc/file") != 0) e(12);
260 if (rename("nowrite/yes", "nowrite/file") != 0) e(13);
261 if (rename("yes", "file") != 0) e(14);
263 System("chmod 777 noacc nowrite");
265 /* If rmdir() doesn't remove a directory, rename() shouldn't eighter. */
266 System("mkdir newdir olddir");
267 System("rm -rf /tmp/sema.11[ab]");
268 switch (fork()) {
269 case -1: printf("Can't fork\n"); break;
270 case 0:
271 alarm(20);
272 switch (fork()) {
273 case -1: printf("Can't fork\n"); break;
274 case 0:
275 /* Child A. */
276 alarm(20);
277 if (chdir("newdir") != 0) e(15);
278 Creat("/tmp/sema.11a");
279 while (stat("/tmp/sema.11a", &st1) == 0) sleep(1);
280 exit(0);
281 default:
282 wait(&stat_loc);
283 if (stat_loc != 0) e(16); /* Alarm? */
286 /* Child B. */
287 if (chdir("olddir") != 0) e(17);
288 Creat("/tmp/sema.11b");
289 while (stat("/tmp/sema.11b", &st1) == 0) sleep(1);
290 exit(0);
291 default:
292 /* Wait for child A. It will keep ``newdir'' bussy. */
293 while (stat("/tmp/sema.11a", &st1) == -1) sleep(1);
294 if (rmdir("newdir") == -1) {
295 if (rename("olddir", "newdir") != -1) e(18);
296 if (errno != EBUSY) e(19);
298 (void) unlink("/tmp/sema.11a");
300 /* Wait for child B. It will keep ``olddir'' bussy. */
301 while (stat("/tmp/sema.11b", &st1) == -1) sleep(1);
302 if (rmdir("olddir") == -1) {
303 if (rename("olddir", "newdir") != -1) e(20);
304 if (errno != EBUSY) e(21);
306 (void) unlink("/tmp/sema.11b");
307 wait(&stat_loc);
308 if (stat_loc != 0) e(22); /* Alarm? */
312 void makelongnames()
314 register int i;
315 int max_name_length;
317 max_name_length = name_max("."); /* Aka NAME_MAX, but not every FS supports
318 * the same length, hence runtime check */
319 MaxName = malloc(max_name_length + 1);
320 ToLongName = malloc(max_name_length + 1 + 1); /* Name of maximum +1 length */
321 memset(MaxName, 'a', max_name_length);
322 MaxName[max_name_length] = '\0';
324 for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */
325 MaxPath[i++] = '.';
326 MaxPath[i] = '/';
328 MaxPath[PATH_MAX - 1] = '\0';
330 strcpy(ToLongName, MaxName); /* copy them Max to ToLong */
331 strcpy(ToLongPath, MaxPath);
333 ToLongName[max_name_length] = 'a';
334 ToLongName[max_name_length+1] = '\0';/* extend ToLongName by one too many */
335 ToLongPath[PATH_MAX - 1] = '/';
336 ToLongPath[PATH_MAX] = '\0'; /* inc ToLongPath by one */