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);
141) Attempt to create file that already exists - EEXIST
152) Attempt to open a directory for writing - EISDIR
163) Pathname does not exist - ENOENT
174) Open for write but no write permission - EACCES
18
19read(int fd, void *buf, size_t count);
201) Read using invalid file descriptor - EBADF
21
22write(int fd, const void *buf, size_t count);
231) Write using invalid file descriptor - EBADF
242) Attempt to write to read-only file - EBADF
25
26lseek(int fildes, off_t offset, int whence);
271) Seeking on an invalid file descriptor - EBADF
282) Invalid "whence" (3rd param) value -  EINVAL
29
30close(int fd);
311) Attempt to close an invalid file descriptor - EBADF
32
33stat(const char *file_name, struct stat *buf);
341) Pathname is a null string -  ENOENT
352) Pathname does not exist - ENOENT
36
37fstat(int filedes, struct stat *buf);
381) Attempt to stat using an invalid file descriptor - EBADF
39
40isatty (int desc);
41Not applicable. We will test that it returns 1 when expected and a case
42where it should return 0.
43
44rename(const char *oldpath, const char *newpath);
451) newpath is an existing directory, but oldpath is not a directory. - EISDIR
462) newpath is a non-empty directory. - ENOTEMPTY or EEXIST
473) newpath is a subdirectory of old path. - EINVAL
484) oldpath does not exist. - ENOENT
49
50unlink(const char *pathname);
511) pathname does not have write access. - EACCES
522) pathname does not exist. - ENOENT
53
54time(time_t *t);
55Not applicable.
56
57system (const char * string);
581) See if shell available - returns 0
592) See if shell available - returns !0
603) Execute simple shell command - returns 0
614) Invalid string/command. -  returns 127.  */
62
63static 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
76static void stop (void) {}
77
78/* A NULL string.  We pass this to stat below instead of a NULL
79   literal to avoid -Wnonnull warnings.  */
80const char *null_str;
81
82void
83test_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
142void
143test_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
183void
184test_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
215void
216test_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
257void
258test_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
283void
284test_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
318void
319test_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
349void
350test_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
377char sys[1512];
378
379void
380test_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
411void
412test_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
464char name[1256];
465
466void
467test_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
506void
507test_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
522static const char *
523strerrno (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
559int
560main ()
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