1 /* test35: utime() Author: Jan-Mark Wams (jms@cs.vu.nl) */
21 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
22 #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
23 #define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a)
24 #define Mkfifo(f) if (mkfifo(f,0777)!=0) printf("Can't make fifo %s\n", f)
25 #define Mkdir(f) if (mkdir(f,0777)!=0) printf("Can't make dir %s\n", f)
26 #define Creat(f) if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f)
27 #define Time(t) if (time(t) == (time_t)-1) printf("Time error\n")
28 #define Chown(f,u,g) if (chown(f,u,g) != 0) printf("Can't chown %s\n", f)
29 #define Chmod(f,m) if (chmod(f,m) != 0) printf("Can't chmod %s\n", f)
31 #define PASSWD_FILE "/etc/passwd"
37 char MaxName
[NAME_MAX
+ 1]; /* Name of maximum length */
38 char MaxPath
[PATH_MAX
]; /* Same for path */
39 char NameTooLong
[NAME_MAX
+ 2]; /* Name of maximum +1 length */
40 char PathTooLong
[PATH_MAX
+ 1]; /* Same for path, both too long */
42 _PROTOTYPE(void main
, (int argc
, char *argv
[]));
43 _PROTOTYPE(void test35a
, (void));
44 _PROTOTYPE(void test35b
, (void));
45 _PROTOTYPE(void test35c
, (void));
46 _PROTOTYPE(void makelongnames
, (void));
47 _PROTOTYPE(void e
, (int number
));
48 _PROTOTYPE(void quit
, (void));
49 _PROTOTYPE(void getids
, (uid_t
* uid
, gid_t
* gid
));
58 if (argc
== 2) m
= atoi(argv
[1]);
61 System("rm -rf DIR_35; mkdir DIR_35");
64 superuser
= (geteuid() == 0);
66 #ifdef _POSIX_CHOWN_RESTRICTED
67 # if _POSIX_CHOWN_RESTRICTED - 0 != -1
68 I_can_chown
= superuser
;
73 # include "error, this case requires dynamic checks and is not handled"
76 for (i
= 0; i
< ITERATIONS
; i
++) {
77 if (m
& 0001) test35a();
78 if (m
& 0002) test35b();
79 if (m
& 0004) test35c();
85 { /* Test normal operation. */
93 /* Creat scratch file. */
96 /* Set file times back two seconds. */
98 ub
.actime
= st
.st_atime
- 2;
99 ub
.modtime
= st
.st_mtime
- 2;
104 if (ub
.actime
!= st
.st_atime
) e(1);
105 if (ub
.modtime
!= st
.st_mtime
) e(2);
107 /* The status changed time sould be changed. */
108 #ifndef V1_FILESYSTEM
109 if (st
.st_ctime
< time1
) e(3);
111 if (st
.st_ctime
> time2
) e(4);
113 /* Add twenty seconds. */
115 ub
.actime
= st
.st_atime
+ 20;
116 ub
.modtime
= st
.st_mtime
+ 20;
121 if (ub
.actime
!= st
.st_atime
) e(5);
122 if (ub
.modtime
!= st
.st_mtime
) e(6);
123 if (st
.st_ctime
< time1
) e(7);
124 #ifndef V1_FILESYSTEM
125 if (st
.st_ctime
> time2
) e(8);
128 /* Try 100 times to do utime in less than one second. */
132 utime("foo", (struct utimbuf
*) NULL
);
134 } while (time1
!= time2
&& cnt
++ < 100);
135 if (time1
== time2
) {
138 if (st
.st_atime
!= time1
) e(9);
139 if (st
.st_mtime
!= time1
) e(10);
142 if (st
.st_atime
> time2
) e(11);
143 if (st
.st_mtime
> time2
) e(12);
145 if (st
.st_atime
< time1
) e(13);
146 if (st
.st_mtime
< time1
) e(14);
148 if (st
.st_ctime
< time1
) e(15);
149 if (st
.st_ctime
> time2
) e(16);
151 System("rm -rf ../DIR_35/*");
158 /* MaxPath and MaxName checkup. */
160 MaxPath
[strlen(MaxPath
) - 2] = '/';
161 MaxPath
[strlen(MaxPath
) - 1] = 'a'; /* make ././.../a */
163 if (utime(MaxName
, NULL
) != 0) e(1);
164 if (utime(MaxPath
, NULL
) != 0) e(2);
166 /* The owner doesn't need write permisson to set times. */
168 if (chmod("foo", 0) != 0) e(3);
169 if (utime("foo", NULL
) != 0) e(4);
170 if (chmod("foo", 0777) != 0) e(5);
171 if (utime("foo", NULL
) != 0) e(6);
173 System("rm -rf ../DIR_35/*");
185 /* Access problems. */
189 Chmod("bar", 0000); /* No search permisson at all. */
190 if (utime("bar/tryme", NULL
) != 0) e(1);
193 Chmod("bar", 0677); /* No search permisson. */
194 if (utime("bar/tryme", NULL
) != -1) e(2);
195 if (errno
!= EACCES
) e(3);
201 case -1: printf("Can't fork\n"); break;
205 /* Get two differend non root uids. */
208 if (uid
== 0) getids(&uid
, &gid
);
216 if (uid
== uid2
) getids(&uid2
, &gid2
);
217 if (uid
== uid2
) e(5);
219 /* Creat a number of files for root, user and user2. */
220 Creat("rootfile"); /* Owned by root. */
221 Chmod("rootfile", 0600);
222 Chown("rootfile", 0, 0);
223 Creat("user2file"); /* Owned by user 2, writeable. */
224 Chmod("user2file", 0020);
225 Chown("user2file", uid2
, gid
);
226 Creat("user2private"); /* Owned by user 2, privately. */
227 Chmod("user2private", 0600);
228 Chown("user2private", uid2
, gid
);
235 /* We now are user ``uid'' from group ``gid''. */
236 ub
.actime
= (time_t) 12345L;
237 ub
.modtime
= (time_t) 12345L;
239 if (utime("rootfile", NULL
) != -1) e(6);
240 if (errno
!= EACCES
) e(7);
241 if (utime("rootfile", &ub
) != -1) e(8);
242 if (errno
!= EPERM
) e(9);
244 if (utime("user2file", NULL
) != 0) e(10);
245 if (utime("user2file", &ub
) != -1) e(11);
246 if (errno
!= EPERM
) e(12);
248 if (utime("user2private", NULL
) != -1) e(13);
249 if (errno
!= EACCES
) e(14);
250 if (utime("user2private", &ub
) != -1) e(15);
251 if (errno
!= EPERM
) e(16);
256 if (stat_loc
!= 0) e(17); /* Alarm? */
260 /* Test names that are too long. */
261 #ifdef _POSIX_NO_TRUNC
262 # if _POSIX_NO_TRUNC - 0 != -1
263 /* Not exist might also be a propper response? */
264 if (utime(NameTooLong
, NULL
) != -1) e(18);
265 if (errno
!= ENAMETOOLONG
) e(19);
268 if (utime(NameTooLong
, NULL
) != 0) e(20);
271 # include "error, this case requires dynamic checks and is not handled"
274 /* Make PathTooLong contain ././.../a */
275 PathTooLong
[strlen(PathTooLong
) - 2] = '/';
276 PathTooLong
[strlen(PathTooLong
) - 1] = 'a';
278 if (utime(PathTooLong
, NULL
) != -1) e(21);
279 if (errno
!= ENAMETOOLONG
) e(22);
281 /* Non existing file name. */
282 if (utime("nonexist", NULL
) != -1) e(23);
283 if (errno
!= ENOENT
) e(24);
285 /* Empty file name. */
286 if (utime("", NULL
) != -1) e(25);
287 if (errno
!= ENOENT
) e(26);
289 System("rm -rf ../DIR_35/*");
296 memset(MaxName
, 'a', NAME_MAX
);
297 MaxName
[NAME_MAX
] = '\0';
298 for (i
= 0; i
< PATH_MAX
- 1; i
++) { /* idem path */
302 MaxPath
[PATH_MAX
- 1] = '\0';
304 strcpy(NameTooLong
, MaxName
); /* copy them Max to TooLong */
305 strcpy(PathTooLong
, MaxPath
);
307 NameTooLong
[NAME_MAX
] = 'a';
308 NameTooLong
[NAME_MAX
+ 1] = '\0'; /* extend NameTooLong by one too many*/
309 PathTooLong
[PATH_MAX
- 1] = '/';
310 PathTooLong
[PATH_MAX
] = '\0'; /* inc PathTooLong by one */
316 int err_num
= errno
; /* Save in case printf clobbers it. */
318 printf("Subtest %d, error %d errno=%d: ", subtest
, n
, errno
);
321 if (errct
++ > MAX_ERROR
) {
322 printf("Too many errors; test aborted\n");
324 system("rm -rf DIR* > /dev/null 2>/dev/null");
333 System("rm -rf DIR_35");
339 printf("%d errors\n", errct
);
344 /* Getids returns a valid uid and gid. Is used PASSWD FILE.
345 ** It assumes the following format for a passwd file line:
346 ** <user_name>:<passwd>:<uid>:<gid>:<other_stuff>
347 ** If no uids and gids can be found, it will only return 0 ids.
349 void getids(r_uid
, r_gid
)
360 static uid_t a_uid
[N
]; /* Array for uids. */
361 static gid_t a_gid
[N
]; /* Array for gids. */
362 static int nuid
= 0, ngid
= 0;/* The number of user & group ids. */
363 static int cuid
= 0, cgid
= 0;/* The current id index. */
365 /* If we don't have any uids go read some from the passwd file. */
367 a_uid
[nuid
++] = 0; /* Root uid and gid. */
369 if ((fp
= fopen(PASSWD_FILE
, "r")) == NULL
) {
370 printf("Can't open ");
373 while (fp
!= NULL
&& fgets(line
, sizeof(line
), fp
) != NULL
) {
374 p
= strchr(line
, ':');
375 if (p
!= NULL
) p
= strchr(p
+ 1, ':');
379 while (isdigit(*p
)) {
381 uid
+= (uid_t
) (*p
- '0');
384 if (*p
!= ':') continue;
387 while (isdigit(*p
)) {
389 gid
+= (gid_t
) (*p
- '0');
392 if (*p
!= ':') continue;
394 for (i
= 0; i
< nuid
; i
++)
395 if (a_uid
[i
] == uid
) break;
396 if (i
== nuid
) a_uid
[nuid
++] = uid
;
399 for (i
= 0; i
< ngid
; i
++)
400 if (a_gid
[i
] == gid
) break;
401 if (i
== ngid
) a_gid
[ngid
++] = gid
;
403 if (nuid
>= N
&& ngid
>= N
) break;
406 if (fp
!= NULL
) fclose(fp
);
409 /* We now have uids and gids in a_uid and a_gid. */
410 if (cuid
>= nuid
) cuid
= 0;
411 if (cgid
>= ngid
) cgid
= 0;
412 *r_uid
= a_uid
[cuid
++];
413 *r_gid
= a_gid
[cgid
++];