1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <sys/time.h>
7 #include <errno.h>
8 #include <sys/wait.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include <time.h>
12 /* TESTS :
13  * - open(const char *pathname, int flags, mode_t mode);
14 1) Attempt to create file that already exists - EEXIST
15 2) Attempt to open a directory for writing - EISDIR
16 3) Pathname does not exist - ENOENT
17 4) Open for write but no write permission - EACCES
18 
19 read(int fd, void *buf, size_t count);
20 1) Read using invalid file descriptor - EBADF
21 
22 write(int fd, const void *buf, size_t count);
23 1) Write using invalid file descriptor - EBADF
24 2) Attempt to write to read-only file - EBADF
25 
26 lseek(int fildes, off_t offset, int whence);
27 1) Seeking on an invalid file descriptor - EBADF
28 2) Invalid "whence" (3rd param) value -  EINVAL
29 
30 close(int fd);
31 1) Attempt to close an invalid file descriptor - EBADF
32 
33 stat(const char *file_name, struct stat *buf);
34 1) Pathname is a null string -  ENOENT
35 2) Pathname does not exist - ENOENT
36 
37 fstat(int filedes, struct stat *buf);
38 1) Attempt to stat using an invalid file descriptor - EBADF
39 
40 isatty (int desc);
41 Not applicable. We will test that it returns 1 when expected and a case
42 where it should return 0.
43 
44 rename(const char *oldpath, const char *newpath);
45 1) newpath is an existing directory, but oldpath is not a directory. - EISDIR
46 2) newpath is a non-empty directory. - ENOTEMPTY or EEXIST
47 3) newpath is a subdirectory of old path. - EINVAL
48 4) oldpath does not exist. - ENOENT
49 
50 unlink(const char *pathname);
51 1) pathname does not have write access. - EACCES
52 2) pathname does not exist. - ENOENT
53 
54 time(time_t *t);
55 Not applicable.
56 
57 system (const char * string);
58 1) See if shell available - returns 0
59 2) See if shell available - returns !0
60 3) Execute simple shell command - returns 0
61 4) Invalid string/command. -  returns 127.  */
62 
63 static const char *strerrno (int err);
64 
65 /* Note that OUTDIR is defined by the test suite.  */
66 #define FILENAME    "foo.fileio.test"
67 #define RENAMED     "bar.fileio.test"
68 #define NONEXISTANT "nofoo.fileio.test"
69 #define NOWRITE     "nowrt.fileio.test"
70 #define TESTDIR1     "dir1.fileio.test"
71 #define TESTDIR2     "dir2.fileio.test"
72 #define TESTSUBDIR   "dir1.fileio.test/subdir.fileio.test"
73 
74 #define STRING      "Hello World"
75 
stop(void)76 static void stop (void) {}
77 
78 /* A NULL string.  We pass this to stat below instead of a NULL
79    literal to avoid -Wnonnull warnings.  */
80 const char *null_str;
81 
82 void
test_open(void)83 test_open (void)
84 {
85   int ret;
86 
87   /* Test opening */
88   errno = 0;
89   ret = open (OUTDIR FILENAME, O_CREAT | O_TRUNC | O_RDWR, S_IWUSR | S_IRUSR);
90   printf ("open 1: ret = %d, errno = %d %s\n", ret, errno,
91 	  ret >= 0 ? "OK" : "");
92 
93   if (ret >= 0)
94     close (ret);
95   stop ();
96   /* Creating an already existing file (created by fileio.exp) */
97   errno = 0;
98   ret = open (OUTDIR FILENAME, O_CREAT | O_EXCL | O_WRONLY, S_IWUSR | S_IRUSR);
99   printf ("open 2: ret = %d, errno = %d %s\n", ret, errno,
100 	  strerrno (errno));
101   if (ret >= 0)
102     close (ret);
103   stop ();
104   /* Open directory (for writing) */
105   errno = 0;
106   ret = open (".", O_WRONLY);
107   printf ("open 3: ret = %d, errno = %d %s\n", ret, errno,
108 	  strerrno (errno));
109   if (ret >= 0)
110     close (ret);
111   stop ();
112   /* Opening nonexistant file */
113   errno = 0;
114   ret = open (NONEXISTANT, O_RDONLY);
115   printf ("open 4: ret = %d, errno = %d %s\n", ret, errno,
116 	  strerrno (errno));
117   if (ret >= 0)
118     close (ret);
119   stop ();
120   /* Open for write but no write permission */
121   errno = 0;
122   ret = open (OUTDIR NOWRITE, O_CREAT | O_RDONLY, S_IRUSR);
123   if (ret >= 0)
124     {
125       close (ret);
126       stop ();
127       errno = 0;
128       ret = open (OUTDIR NOWRITE, O_WRONLY);
129       printf ("open 5: ret = %d, errno = %d %s\n", ret, errno,
130 	      strerrno (errno));
131       if (ret >= 0)
132 	close (ret);
133     }
134   else
135     {
136       stop ();
137       printf ("open 5: ret = %d, errno = %d\n", ret, errno);
138     }
139   stop ();
140 }
141 
142 void
test_write(void)143 test_write (void)
144 {
145   int fd, ret;
146 
147   /* Test writing */
148   errno = 0;
149   fd = open (OUTDIR FILENAME, O_WRONLY);
150   if (fd >= 0)
151     {
152       errno = 0;
153       ret = write (fd, STRING, strlen (STRING));
154       printf ("write 1: ret = %d, errno = %d %s\n", ret, errno,
155               ret == strlen (STRING) ? "OK" : "");
156       close (fd);
157     }
158   else
159     printf ("write 1: errno = %d\n", errno);
160   stop ();
161   /* Write using invalid file descriptor */
162   errno = 0;
163   ret = write (999, STRING, strlen (STRING));
164   printf ("write 2: ret = %d, errno = %d, %s\n", ret, errno,
165 	  strerrno (errno));
166   stop ();
167   /* Write to a read-only file */
168   errno = 0;
169   fd = open (OUTDIR FILENAME, O_RDONLY);
170   if (fd >= 0)
171     {
172       errno = 0;
173       ret = write (fd, STRING, strlen (STRING));
174       printf ("write 3: ret = %d, errno = %d %s\n", ret, errno,
175 	      strerrno (errno));
176       close (fd);
177     }
178   else
179     printf ("write 3: errno = %d\n", errno);
180   stop ();
181 }
182 
183 void
test_read(void)184 test_read (void)
185 {
186   int fd, ret;
187   char buf[16];
188 
189   /* Test reading */
190   errno = 0;
191   fd = open (OUTDIR FILENAME, O_RDONLY);
192   if (fd >= 0)
193     {
194       memset (buf, 0, 16);
195       errno = 0;
196       ret = read (fd, buf, 16);
197       buf[15] = '\0'; /* Don't trust anybody... */
198       if (ret == strlen (STRING))
199         printf ("read 1: %s %s\n", buf, !strcmp (buf, STRING) ? "OK" : "");
200       else
201 	printf ("read 1: ret = %d, errno = %d\n", ret, errno);
202       close (fd);
203     }
204   else
205     printf ("read 1: errno = %d\n", errno);
206   stop ();
207   /* Read using invalid file descriptor */
208   errno = 0;
209   ret = read (999, buf, 16);
210   printf ("read 2: ret = %d, errno = %d %s\n", ret, errno,
211 	  strerrno (errno));
212   stop ();
213 }
214 
215 void
test_lseek(void)216 test_lseek (void)
217 {
218   int fd;
219   off_t ret = 0;
220 
221   /* Test seeking */
222   errno = 0;
223   fd = open (OUTDIR FILENAME, O_RDONLY);
224   if (fd >= 0)
225     {
226       errno = 0;
227       ret = lseek (fd, 0, SEEK_CUR);
228       printf ("lseek 1: ret = %ld, errno = %d, %s\n", (long) ret, errno,
229               ret == 0 ? "OK" : "");
230       stop ();
231       errno = 0;
232       ret = lseek (fd, 0, SEEK_END);
233       printf ("lseek 2: ret = %ld, errno = %d, %s\n", (long) ret, errno,
234               ret == 11 ? "OK" : "");
235       stop ();
236       errno = 0;
237       ret = lseek (fd, 3, SEEK_SET);
238       printf ("lseek 3: ret = %ld, errno = %d, %s\n", (long) ret, errno,
239               ret == 3 ? "OK" : "");
240       close (fd);
241     }
242   else
243     {
244       printf ("lseek 1: ret = %ld, errno = %d %s\n", (long) ret, errno,
245 	      strerrno (errno));
246       stop ();
247       printf ("lseek 2: ret = %ld, errno = %d %s\n", (long) ret, errno,
248 	      strerrno (errno));
249       stop ();
250       printf ("lseek 3: ret = %ld, errno = %d %s\n", (long) ret, errno,
251 	      strerrno (errno));
252     }
253   /* Seeking on an invalid file descriptor */
254   stop ();
255 }
256 
257 void
test_close(void)258 test_close (void)
259 {
260   int fd, ret;
261 
262   /* Test close */
263   errno = 0;
264   fd = open (OUTDIR FILENAME, O_RDONLY);
265   if (fd >= 0)
266     {
267       errno = 0;
268       ret = close (fd);
269       printf ("close 1: ret = %d, errno = %d, %s\n", ret, errno,
270               ret == 0 ? "OK" : "");
271     }
272   else
273     printf ("close 1: errno = %d\n", errno);
274   stop ();
275   /* Close an invalid file descriptor */
276   errno = 0;
277   ret = close (999);
278   printf ("close 2: ret = %d, errno = %d, %s\n", ret, errno,
279   	  strerrno (errno));
280   stop ();
281 }
282 
283 void
test_stat(void)284 test_stat (void)
285 {
286   int ret;
287   struct stat st;
288 
289   /* Test stat */
290   errno = 0;
291   ret = stat (OUTDIR FILENAME, &st);
292   if (!ret)
293     printf ("stat 1: ret = %d, errno = %d %s\n", ret, errno,
294 	    st.st_size == 11 ? "OK" : "");
295   else
296     printf ("stat 1: ret = %d, errno = %d\n", ret, errno);
297   stop ();
298   /* NULL pathname */
299   errno = 0;
300   ret = stat (null_str, &st);
301   printf ("stat 2: ret = %d, errno = %d %s\n", ret, errno,
302   	  strerrno (errno));
303   stop ();
304   /* Empty pathname */
305   errno = 0;
306   ret = stat ("", &st);
307   printf ("stat 3: ret = %d, errno = %d %s\n", ret, errno,
308   	  strerrno (errno));
309   stop ();
310   /* Nonexistant file */
311   errno = 0;
312   ret = stat (NONEXISTANT, &st);
313   printf ("stat 4: ret = %d, errno = %d %s\n", ret, errno,
314   	  strerrno (errno));
315   stop ();
316 }
317 
318 void
test_fstat(void)319 test_fstat (void)
320 {
321   int fd, ret;
322   struct stat st;
323 
324   /* Test fstat */
325   errno = 0;
326   fd = open (OUTDIR FILENAME, O_RDONLY);
327   if (fd >= 0)
328     {
329       errno = 0;
330       ret = fstat (fd, &st);
331       if (!ret)
332 	printf ("fstat 1: ret = %d, errno = %d %s\n", ret, errno,
333 		st.st_size == 11 ? "OK" : "");
334       else
335 	printf ("fstat 1: ret = %d, errno = %d\n", ret, errno);
336       close (fd);
337     }
338   else
339     printf ("fstat 1: errno = %d\n", errno);
340   stop ();
341   /* Fstat using invalid file descriptor */
342   errno = 0;
343   ret = fstat (999, &st);
344   printf ("fstat 2: ret = %d, errno = %d %s\n", ret, errno,
345   	  strerrno (errno));
346   stop ();
347 }
348 
349 void
test_isatty(void)350 test_isatty (void)
351 {
352   int fd;
353 
354   /* Check std I/O */
355   printf ("isatty 1: stdin %s\n", isatty (0) ? "yes OK" : "no");
356   stop ();
357   printf ("isatty 2: stdout %s\n", isatty (1) ? "yes OK" : "no");
358   stop ();
359   printf ("isatty 3: stderr %s\n", isatty (2) ? "yes OK" : "no");
360   stop ();
361   /* Check invalid fd */
362   printf ("isatty 4: invalid %s\n", isatty (999) ? "yes" : "no OK");
363   stop ();
364   /* Check open file */
365   fd = open (OUTDIR FILENAME, O_RDONLY);
366   if (fd >= 0)
367     {
368       printf ("isatty 5: file %s\n", isatty (fd) ? "yes" : "no OK");
369       close (fd);
370     }
371   else
372     printf ("isatty 5: file couldn't open\n");
373   stop ();
374 }
375 
376 
377 char sys[1512];
378 
379 void
test_system(void)380 test_system (void)
381 {
382   /*
383    * Requires test framework to switch on "set remote system-call-allowed 1"
384    */
385   int ret;
386 
387   /* Test for shell ('set remote system-call-allowed' is disabled
388      by default).  */
389   ret = system (NULL);
390   printf ("system 1: ret = %d %s\n", ret, ret == 0 ? "OK" : "");
391   stop ();
392   /* Test for shell again (the testsuite will have enabled it now).  */
393   ret = system (NULL);
394   printf ("system 2: ret = %d %s\n", ret, ret != 0 ? "OK" : "");
395   stop ();
396   /* This test prepares the directory for test_rename() */
397   sprintf (sys, "mkdir -p %s/%s %s/%s", OUTDIR, TESTSUBDIR, OUTDIR, TESTDIR2);
398   ret = system (sys);
399   if (ret == 127)
400     printf ("system 3: ret = %d /bin/sh unavailable???\n", ret);
401   else
402     printf ("system 3: ret = %d %s\n", ret, ret == 0 ? "OK" : "");
403   stop ();
404   /* Invalid command (just guessing ;-) ) */
405   ret = system ("wrtzlpfrmpft");
406   printf ("system 4: ret = %d %s\n", ret,
407 	  WEXITSTATUS (ret) == 127 ? "OK" : "");
408   stop ();
409 }
410 
411 void
test_rename(void)412 test_rename (void)
413 {
414   int ret;
415   struct stat st;
416 
417   /* Test rename */
418   errno = 0;
419   ret = rename (OUTDIR FILENAME, OUTDIR RENAMED);
420   if (!ret)
421     {
422       errno = 0;
423       ret = stat (FILENAME, &st);
424       if (ret && errno == ENOENT)
425         {
426 	  errno = 0;
427 	  ret = stat (OUTDIR RENAMED, &st);
428 	  printf ("rename 1: ret = %d, errno = %d %s\n", ret, errno,
429 		  strerrno (errno));
430 	  errno = 0;
431 	}
432       else
433 	printf ("rename 1: ret = %d, errno = %d\n", ret, errno);
434     }
435   else
436     printf ("rename 1: ret = %d, errno = %d\n", ret, errno);
437   stop ();
438   /* newpath is existing directory, oldpath is not a directory */
439   errno = 0;
440   ret = rename (OUTDIR RENAMED, OUTDIR TESTDIR2);
441   printf ("rename 2: ret = %d, errno = %d %s\n", ret, errno,
442 	  strerrno (errno));
443   stop ();
444   /* newpath is a non-empty directory */
445   errno = 0;
446   ret = rename (OUTDIR TESTDIR2, OUTDIR TESTDIR1);
447   printf ("rename 3: ret = %d, errno = %d %s\n", ret, errno,
448           strerrno (errno));
449   stop ();
450   /* newpath is a subdirectory of old path */
451   errno = 0;
452   ret = rename (OUTDIR TESTDIR1, OUTDIR TESTSUBDIR);
453   printf ("rename 4: ret = %d, errno = %d %s\n", ret, errno,
454 	  strerrno (errno));
455   stop ();
456   /* oldpath does not exist */
457   errno = 0;
458   ret = rename (OUTDIR NONEXISTANT, OUTDIR FILENAME);
459   printf ("rename 5: ret = %d, errno = %d %s\n", ret, errno,
460 	  strerrno (errno));
461   stop ();
462 }
463 
464 char name[1256];
465 
466 void
test_unlink(void)467 test_unlink (void)
468 {
469   int ret;
470 
471   /* Test unlink */
472   errno = 0;
473   ret = unlink (OUTDIR RENAMED);
474   printf ("unlink 1: ret = %d, errno = %d %s\n", ret, errno,
475 	  strerrno (errno));
476   stop ();
477   /* No write access */
478   sprintf (name, "%s/%s/%s", OUTDIR, TESTDIR2, FILENAME);
479   errno = 0;
480   ret = open (name, O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
481   if (ret >= 0)
482     {
483       sprintf (sys, "chmod -w %s/%s", OUTDIR, TESTDIR2);
484       ret = system (sys);
485       if (!ret)
486         {
487 	  errno = 0;
488 	  ret = unlink (name);
489 	  printf ("unlink 2: ret = %d, errno = %d %s\n", ret, errno,
490 		  strerrno (errno));
491         }
492       else
493 	printf ("unlink 2: ret = %d chmod failed, errno= %d\n", ret, errno);
494     }
495   else
496     printf ("unlink 2: ret = %d, errno = %d\n", ret, errno);
497   stop ();
498   /* pathname doesn't exist */
499   errno = 0;
500   ret = unlink (OUTDIR NONEXISTANT);
501   printf ("unlink 3: ret = %d, errno = %d %s\n", ret, errno,
502           strerrno (errno));
503   stop ();
504 }
505 
506 void
test_time(void)507 test_time (void)
508 {
509   time_t ret, t;
510 
511   errno = 0;
512   ret = time (&t);
513   printf ("time 1: ret = %ld, errno = %d, t = %ld %s\n", (long) ret, errno, (long) t, ret == t ? "OK" : "");
514   stop ();
515   errno = 0;
516   ret = time (NULL);
517   printf ("time 2: ret = %ld, errno = %d, t = %ld %s\n",
518 	  (long) ret, errno, (long) t, ret >= t && ret < t + 10 ? "OK" : "");
519   stop ();
520 }
521 
522 static const char *
strerrno(int err)523 strerrno (int err)
524 {
525   switch (err)
526     {
527     case 0: return "OK";
528 #ifdef EACCES
529     case EACCES: return "EACCES";
530 #endif
531 #ifdef EBADF
532     case EBADF: return "EBADF";
533 #endif
534 #ifdef EEXIST
535     case EEXIST: return "EEXIST";
536 #endif
537 #ifdef EFAULT
538     case EFAULT: return "EFAULT";
539 #endif
540 #ifdef EINVAL
541     case EINVAL: return "EINVAL";
542 #endif
543 #ifdef EISDIR
544     case EISDIR: return "EISDIR";
545 #endif
546 #ifdef ENOENT
547     case ENOENT: return "ENOENT";
548 #endif
549 #ifdef ENOTEMPTY
550     case ENOTEMPTY: return "ENOTEMPTY";
551 #endif
552 #ifdef EBUSY
553     case EBUSY: return "EBUSY";
554 #endif
555     default: return "E??";
556     }
557 }
558 
559 int
main()560 main ()
561 {
562   /* Don't change the order of the calls.  They partly depend on each other */
563   test_open ();
564   test_write ();
565   test_read ();
566   test_lseek ();
567   test_close ();
568   test_stat ();
569   test_fstat ();
570   test_isatty ();
571   test_system ();
572   test_rename ();
573   test_unlink ();
574   test_time ();
575   return 0;
576 }
577