1 /* test35: utime() Author: Jan-Mark Wams (jms@cs.vu.nl) */
23 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
24 #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
25 #define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a)
26 #define Mkfifo(f) if (mkfifo(f,0777)!=0) printf("Can't make fifo %s\n", f)
27 #define Mkdir(f) if (mkdir(f,0777)!=0) printf("Can't make dir %s\n", f)
28 #define Creat(f) if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f)
29 #define Time(t) if (time(t) == (time_t)-1) printf("Time error\n")
30 #define Chown(f,u,g) if (chown(f,u,g) != 0) printf("Can't chown %s\n", f)
31 #define Chmod(f,m) if (chmod(f,m) != 0) printf("Can't chmod %s\n", f)
33 #define PASSWD_FILE "/etc/passwd"
37 char *MaxName
; /* Name of maximum length */
38 char MaxPath
[PATH_MAX
]; /* Same for path */
39 char *NameTooLong
; /* Name of maximum +1 length */
40 char PathTooLong
[PATH_MAX
+ 1]; /* Same for path, both too long */
45 void makelongnames(void);
46 void getids(uid_t
* uid
, gid_t
* gid
);
48 int main(int argc
, char *argv
[])
53 if (argc
== 2) m
= atoi(argv
[1]);
56 superuser
= (geteuid() == 0);
58 #ifdef _POSIX_CHOWN_RESTRICTED
59 # if _POSIX_CHOWN_RESTRICTED - 0 != -1
60 I_can_chown
= superuser
;
65 # include "error, this case requires dynamic checks and is not handled"
68 for (i
= 0; i
< ITERATIONS
; i
++) {
69 if (m
& 0001) test35a();
70 if (m
& 0002) test35b();
71 if (m
& 0004) test35c();
78 { /* Test normal operation. */
86 /* Creat scratch file. */
89 /* Set file times back two seconds. */
91 ub
.actime
= st
.st_atime
- 2;
92 ub
.modtime
= st
.st_mtime
- 2;
97 if (ub
.actime
!= st
.st_atime
) e(1);
98 if (ub
.modtime
!= st
.st_mtime
) e(2);
100 /* The status changed time sould be changed. */
101 #ifndef V1_FILESYSTEM
102 if (st
.st_ctime
< time1
) e(3);
104 if (st
.st_ctime
> time2
) e(4);
106 /* Add twenty seconds. */
108 ub
.actime
= st
.st_atime
+ 20;
109 ub
.modtime
= st
.st_mtime
+ 20;
114 if (ub
.actime
!= st
.st_atime
) e(5);
115 if (ub
.modtime
!= st
.st_mtime
) e(6);
116 if (st
.st_ctime
< time1
) e(7);
117 #ifndef V1_FILESYSTEM
118 if (st
.st_ctime
> time2
) e(8);
121 /* Try 100 times to do utime in less than one second. */
125 utime("foo", (struct utimbuf
*) NULL
);
127 } while (time1
!= time2
&& cnt
++ < 100);
128 if (time1
== time2
) {
131 if (st
.st_atime
!= time1
) e(9);
132 if (st
.st_mtime
!= time1
) e(10);
135 if (st
.st_atime
> time2
) e(11);
136 if (st
.st_mtime
> time2
) e(12);
138 if (st
.st_atime
< time1
) e(13);
139 if (st
.st_mtime
< time1
) e(14);
141 if (st
.st_ctime
< time1
) e(15);
142 if (st
.st_ctime
> time2
) e(16);
144 System("rm -rf ../DIR_35/*");
151 /* MaxPath and MaxName checkup. */
153 MaxPath
[strlen(MaxPath
) - 2] = '/';
154 MaxPath
[strlen(MaxPath
) - 1] = 'a'; /* make ././.../a */
156 if (utime(MaxName
, NULL
) != 0) e(1);
157 if (utime(MaxPath
, NULL
) != 0) e(2);
159 /* The owner doesn't need write permisson to set times. */
161 if (chmod("foo", 0) != 0) e(3);
162 if (utime("foo", NULL
) != 0) e(4);
163 if (chmod("foo", 0777) != 0) e(5);
164 if (utime("foo", NULL
) != 0) e(6);
166 System("rm -rf ../DIR_35/*");
174 int fd
, does_truncate
, stat_loc
;
178 /* Access problems. */
182 Chmod("bar", 0000); /* No search permisson at all. */
183 if (utime("bar/tryme", NULL
) != 0) e(1);
186 Chmod("bar", 0677); /* No search permisson. */
187 if (utime("bar/tryme", NULL
) != -1) e(2);
188 if (errno
!= EACCES
) e(3);
194 case -1: printf("Can't fork\n"); break;
198 /* Get two differend non root uids. */
201 if (uid
== 0) getids(&uid
, &gid
);
209 if (uid
== uid2
) getids(&uid2
, &gid2
);
210 if (uid
== uid2
) e(5);
212 /* Creat a number of files for root, user and user2. */
213 Creat("rootfile"); /* Owned by root. */
214 Chmod("rootfile", 0600);
215 Chown("rootfile", 0, 0);
216 Creat("user2file"); /* Owned by user 2, writeable. */
217 Chmod("user2file", 0020);
218 Chown("user2file", uid2
, gid
);
219 Creat("user2private"); /* Owned by user 2, privately. */
220 Chmod("user2private", 0600);
221 Chown("user2private", uid2
, gid
);
228 /* We now are user ``uid'' from group ``gid''. */
229 ub
.actime
= (time_t) 12345L;
230 ub
.modtime
= (time_t) 12345L;
232 if (utime("rootfile", NULL
) != -1) e(6);
233 if (errno
!= EACCES
) e(7);
234 if (utime("rootfile", &ub
) != -1) e(8);
235 if (errno
!= EPERM
) e(9);
237 if (utime("user2file", NULL
) != 0) e(10);
238 if (utime("user2file", &ub
) != -1) e(11);
239 if (errno
!= EPERM
) e(12);
241 if (utime("user2private", NULL
) != -1) e(13);
242 if (errno
!= EACCES
) e(14);
243 if (utime("user2private", &ub
) != -1) e(15);
244 if (errno
!= EPERM
) e(16);
249 if (stat_loc
!= 0) e(17); /* Alarm? */
253 /* Test names that are too long. */
254 does_truncate
= does_fs_truncate();
255 fd
= creat(NameTooLong
, 0777);
257 if (utime(NameTooLong
, NULL
) != 0) e(18);
259 if (utime(NameTooLong
, NULL
) != -1) e(19);
260 if (errno
!= ENAMETOOLONG
) e(20);
264 /* Make PathTooLong contain ././.../a */
265 PathTooLong
[strlen(PathTooLong
) - 2] = '/';
266 PathTooLong
[strlen(PathTooLong
) - 1] = 'a';
268 if (utime(PathTooLong
, NULL
) != -1) e(21);
269 if (errno
!= ENAMETOOLONG
) e(22);
271 /* Non existing file name. */
272 if (utime("nonexist", NULL
) != -1) e(23);
273 if (errno
!= ENOENT
) e(24);
275 /* Empty file name. */
276 if (utime("", NULL
) != -1) e(25);
277 if (errno
!= ENOENT
) e(26);
279 System("rm -rf ../DIR_35/*");
287 max_name_length
= name_max("."); /* Aka NAME_MAX, but not every FS supports
288 * the same length, hence runtime check */
289 MaxName
= malloc(max_name_length
+ 1);
290 NameTooLong
= malloc(max_name_length
+ 1 + 1); /* Name of maximum +1 length */
291 memset(MaxName
, 'a', max_name_length
);
292 MaxName
[max_name_length
] = '\0';
294 for (i
= 0; i
< PATH_MAX
- 1; i
++) { /* idem path */
298 MaxPath
[PATH_MAX
- 1] = '\0';
300 strcpy(NameTooLong
, MaxName
); /* copy them Max to ToLong */
301 strcpy(PathTooLong
, MaxPath
);
303 NameTooLong
[max_name_length
] = 'a';
304 NameTooLong
[max_name_length
+1] = '\0';/* extend ToLongName by one too many */
305 PathTooLong
[PATH_MAX
- 1] = '/';
306 PathTooLong
[PATH_MAX
] = '\0'; /* inc ToLongPath by one */
309 /* Getids returns a valid uid and gid. Is used PASSWD FILE.
310 ** It assumes the following format for a passwd file line:
311 ** <user_name>:<passwd>:<uid>:<gid>:<other_stuff>
312 ** If no uids and gids can be found, it will only return 0 ids.
314 void getids(r_uid
, r_gid
)
325 static uid_t a_uid
[N
]; /* Array for uids. */
326 static gid_t a_gid
[N
]; /* Array for gids. */
327 static int nuid
= 0, ngid
= 0;/* The number of user & group ids. */
328 static int cuid
= 0, cgid
= 0;/* The current id index. */
330 /* If we don't have any uids go read some from the passwd file. */
332 a_uid
[nuid
++] = 0; /* Root uid and gid. */
334 if ((fp
= fopen(PASSWD_FILE
, "r")) == NULL
) {
335 printf("Can't open ");
338 while (fp
!= NULL
&& fgets(line
, sizeof(line
), fp
) != NULL
) {
339 p
= strchr(line
, ':');
340 if (p
!= NULL
) p
= strchr(p
+ 1, ':');
344 while (isdigit(*p
)) {
346 uid
+= (uid_t
) (*p
- '0');
349 if (*p
!= ':') continue;
352 while (isdigit(*p
)) {
354 gid
+= (gid_t
) (*p
- '0');
357 if (*p
!= ':') continue;
359 for (i
= 0; i
< nuid
; i
++)
360 if (a_uid
[i
] == uid
) break;
361 if (i
== nuid
) a_uid
[nuid
++] = uid
;
364 for (i
= 0; i
< ngid
; i
++)
365 if (a_gid
[i
] == gid
) break;
366 if (i
== ngid
) a_gid
[ngid
++] = gid
;
368 if (nuid
>= N
&& ngid
>= N
) break;
371 if (fp
!= NULL
) fclose(fp
);
374 /* We now have uids and gids in a_uid and a_gid. */
375 if (cuid
>= nuid
) cuid
= 0;
376 if (cgid
>= ngid
) cgid
= 0;
377 *r_uid
= a_uid
[cuid
++];
378 *r_gid
= a_gid
[cgid
++];