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