1 /* test35: utime() Author: Jan-Mark Wams (jms@cs.vu.nl) */
24 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
25 #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
26 #define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a)
27 #define Mkfifo(f) if (mkfifo(f,0777)!=0) printf("Can't make fifo %s\n", f)
28 #define Mkdir(f) if (mkdir(f,0777)!=0) printf("Can't make dir %s\n", f)
29 #define Creat(f) if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f)
30 #define Time(t) if (time(t) == (time_t)-1) printf("Time error\n")
31 #define Chown(f,u,g) if (chown(f,u,g) != 0) printf("Can't chown %s\n", f)
32 #define Chmod(f,m) if (chmod(f,m) != 0) printf("Can't chmod %s\n", f)
34 #define PASSWD_FILE "/etc/passwd"
38 char *MaxName
; /* Name of maximum length */
39 char MaxPath
[PATH_MAX
]; /* Same for path */
40 char *NameTooLong
; /* Name of maximum +1 length */
41 char PathTooLong
[PATH_MAX
+ 1]; /* Same for path, both too long */
46 void makelongnames(void);
47 void getids(uid_t
* uid
, gid_t
* gid
);
49 int main(int argc
, char *argv
[])
54 if (argc
== 2) m
= atoi(argv
[1]);
57 superuser
= (geteuid() == 0);
59 #ifdef _POSIX_CHOWN_RESTRICTED
60 # if _POSIX_CHOWN_RESTRICTED - 0 != -1
61 I_can_chown
= superuser
;
66 # include "error, this case requires dynamic checks and is not handled"
69 for (i
= 0; i
< ITERATIONS
; i
++) {
70 if (m
& 0001) test35a();
71 if (m
& 0002) test35b();
72 if (m
& 0004) test35c();
79 { /* Test normal operation. */
87 /* Creat scratch file. */
90 /* Set file times back two seconds. */
92 ub
.actime
= st
.st_atime
- 2;
93 ub
.modtime
= st
.st_mtime
- 2;
98 if (ub
.actime
!= st
.st_atime
) e(1);
99 if (ub
.modtime
!= st
.st_mtime
) e(2);
101 /* The status changed time sould be changed. */
102 #ifndef V1_FILESYSTEM
103 if (st
.st_ctime
< time1
) e(3);
105 if (st
.st_ctime
> time2
) e(4);
107 /* Add twenty seconds. */
109 ub
.actime
= st
.st_atime
+ 20;
110 ub
.modtime
= st
.st_mtime
+ 20;
115 if (ub
.actime
!= st
.st_atime
) e(5);
116 if (ub
.modtime
!= st
.st_mtime
) e(6);
117 if (st
.st_ctime
< time1
) e(7);
118 #ifndef V1_FILESYSTEM
119 if (st
.st_ctime
> time2
) e(8);
122 /* Try 100 times to do utime in less than one second. */
126 utime("foo", (struct utimbuf
*) NULL
);
128 } while (time1
!= time2
&& cnt
++ < 100);
129 if (time1
== time2
) {
132 if (st
.st_atime
!= time1
) e(9);
133 if (st
.st_mtime
!= time1
) e(10);
136 if (st
.st_atime
> time2
) e(11);
137 if (st
.st_mtime
> time2
) e(12);
139 if (st
.st_atime
< time1
) e(13);
140 if (st
.st_mtime
< time1
) e(14);
142 if (st
.st_ctime
< time1
) e(15);
143 if (st
.st_ctime
> time2
) e(16);
145 System("rm -rf ../DIR_35/*");
152 /* MaxPath and MaxName checkup. */
154 MaxPath
[strlen(MaxPath
) - 2] = '/';
155 MaxPath
[strlen(MaxPath
) - 1] = 'a'; /* make ././.../a */
157 if (utime(MaxName
, NULL
) != 0) e(1);
158 if (utime(MaxPath
, NULL
) != 0) e(2);
160 /* The owner doesn't need write permisson to set times. */
162 if (chmod("foo", 0) != 0) e(3);
163 if (utime("foo", NULL
) != 0) e(4);
164 if (chmod("foo", 0777) != 0) e(5);
165 if (utime("foo", NULL
) != 0) e(6);
167 System("rm -rf ../DIR_35/*");
175 int fd
, does_truncate
, stat_loc
;
179 /* Access problems. */
183 Chmod("bar", 0000); /* No search permisson at all. */
184 if (utime("bar/tryme", NULL
) != 0) e(1);
187 Chmod("bar", 0677); /* No search permisson. */
188 if (utime("bar/tryme", NULL
) != -1) e(2);
189 if (errno
!= EACCES
) e(3);
195 case -1: printf("Can't fork\n"); break;
199 /* Get two differend non root uids. */
202 if (uid
== 0) getids(&uid
, &gid
);
210 if (uid
== uid2
) getids(&uid2
, &gid2
);
211 if (uid
== uid2
) e(5);
213 /* Creat a number of files for root, user and user2. */
214 Creat("rootfile"); /* Owned by root. */
215 Chmod("rootfile", 0600);
216 Chown("rootfile", 0, 0);
217 Creat("user2file"); /* Owned by user 2, writeable. */
218 Chmod("user2file", 0020);
219 Chown("user2file", uid2
, gid
);
220 Creat("user2private"); /* Owned by user 2, privately. */
221 Chmod("user2private", 0600);
222 Chown("user2private", uid2
, gid
);
229 /* We now are user ``uid'' from group ``gid''. */
230 ub
.actime
= (time_t) 12345L;
231 ub
.modtime
= (time_t) 12345L;
233 if (utime("rootfile", NULL
) != -1) e(6);
234 if (errno
!= EACCES
) e(7);
235 if (utime("rootfile", &ub
) != -1) e(8);
236 if (errno
!= EPERM
) e(9);
238 if (utime("user2file", NULL
) != 0) e(10);
239 if (utime("user2file", &ub
) != -1) e(11);
240 if (errno
!= EPERM
) e(12);
242 if (utime("user2private", NULL
) != -1) e(13);
243 if (errno
!= EACCES
) e(14);
244 if (utime("user2private", &ub
) != -1) e(15);
245 if (errno
!= EPERM
) e(16);
250 if (stat_loc
!= 0) e(17); /* Alarm? */
254 /* Test names that are too long. */
255 does_truncate
= does_fs_truncate();
256 fd
= creat(NameTooLong
, 0777);
258 if (utime(NameTooLong
, NULL
) != 0) e(18);
260 if (utime(NameTooLong
, NULL
) != -1) e(19);
261 if (errno
!= ENAMETOOLONG
) e(20);
265 /* Make PathTooLong contain ././.../a */
266 PathTooLong
[strlen(PathTooLong
) - 2] = '/';
267 PathTooLong
[strlen(PathTooLong
) - 1] = 'a';
269 if (utime(PathTooLong
, NULL
) != -1) e(21);
270 if (errno
!= ENAMETOOLONG
) e(22);
272 /* Non existing file name. */
273 if (utime("nonexist", NULL
) != -1) e(23);
274 if (errno
!= ENOENT
) e(24);
276 /* Empty file name. */
277 if (utime("", NULL
) != -1) e(25);
278 if (errno
!= ENOENT
) e(26);
280 System("rm -rf ../DIR_35/*");
288 max_name_length
= name_max("."); /* Aka NAME_MAX, but not every FS supports
289 * the same length, hence runtime check */
290 MaxName
= malloc(max_name_length
+ 1);
291 NameTooLong
= malloc(max_name_length
+ 1 + 1); /* Name of maximum +1 length */
292 memset(MaxName
, 'a', max_name_length
);
293 MaxName
[max_name_length
] = '\0';
295 for (i
= 0; i
< PATH_MAX
- 1; i
++) { /* idem path */
299 MaxPath
[PATH_MAX
- 1] = '\0';
301 strcpy(NameTooLong
, MaxName
); /* copy them Max to ToLong */
302 strcpy(PathTooLong
, MaxPath
);
304 NameTooLong
[max_name_length
] = 'a';
305 NameTooLong
[max_name_length
+1] = '\0';/* extend ToLongName by one too many */
306 PathTooLong
[PATH_MAX
- 1] = '/';
307 PathTooLong
[PATH_MAX
] = '\0'; /* inc ToLongPath by one */
310 /* Getids returns a valid uid and gid. Is used PASSWD FILE.
311 ** It assumes the following format for a passwd file line:
312 ** <user_name>:<passwd>:<uid>:<gid>:<other_stuff>
313 ** If no uids and gids can be found, it will only return 0 ids.
315 void getids(r_uid
, r_gid
)
326 static uid_t a_uid
[N
]; /* Array for uids. */
327 static gid_t a_gid
[N
]; /* Array for gids. */
328 static int nuid
= 0, ngid
= 0;/* The number of user & group ids. */
329 static int cuid
= 0, cgid
= 0;/* The current id index. */
331 /* If we don't have any uids go read some from the passwd file. */
333 a_uid
[nuid
++] = 0; /* Root uid and gid. */
335 if ((fp
= fopen(PASSWD_FILE
, "r")) == NULL
) {
336 printf("Can't open ");
339 while (fp
!= NULL
&& fgets(line
, sizeof(line
), fp
) != NULL
) {
340 p
= (unsigned char *)strchr(line
, ':');
341 if (p
!= NULL
) p
= (unsigned char *)strchr((char *)p
+ 1, ':');
345 while (isdigit(*p
)) {
347 uid
+= (uid_t
) (*p
- '0');
350 if (*p
!= ':') continue;
353 while (isdigit(*p
)) {
355 gid
+= (gid_t
) (*p
- '0');
358 if (*p
!= ':') continue;
360 for (i
= 0; i
< nuid
; i
++)
361 if (a_uid
[i
] == uid
) break;
362 if (i
== nuid
) a_uid
[nuid
++] = uid
;
365 for (i
= 0; i
< ngid
; i
++)
366 if (a_gid
[i
] == gid
) break;
367 if (i
== ngid
) a_gid
[ngid
++] = gid
;
369 if (nuid
>= N
&& ngid
>= N
) break;
372 if (fp
!= NULL
) fclose(fp
);
375 /* We now have uids and gids in a_uid and a_gid. */
376 if (cuid
>= nuid
) cuid
= 0;
377 if (cgid
>= ngid
) cgid
= 0;
378 *r_uid
= a_uid
[cuid
++];
379 *r_gid
= a_gid
[cgid
++];