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