delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1998/12/13/03:04:21

Date: Sun, 13 Dec 1998 10:04:03 +0200 (IST)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
X-Sender: eliz AT is
To: DJ Delorie <dj AT delorie DOT com>, djgpp-workers AT delorie DOT com
Subject: Re: djgpp 2.02 and the /dev/x/foo feature
In-Reply-To: <Pine.SUN.3.91.981213095501.26792B-100000@is>
Message-ID: <Pine.SUN.3.91.981213100202.26792C-100000@is>
MIME-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com

Here's the source of the test program I used.  I thought it would be a 
good addition to djtst distribution, so I arranged this as context diffs 
to be applied by `patch' on top of unpacked djtst202.zip.

*** /dev/null	Sat Dec 12 19:05:34 1998
--- tests/libc/dos/io/filesys.c	Sat Dec 12 15:54:04 1998
***************
*** 0 ****
--- 1,462 ----
+ /* This program runs its command-line arguments through all the
+    library functions which take file names as arguments, and reports
+    any abnormal results.  All file-name oriented functions are tested,
+    except those which are mere wrappers around other functions (for
+    example, `utimes' is a trivial wrapper around `utime', and thus is
+    not tested here).
+ 
+    The original purpose of this program is to test support for special
+    file names, like "/dev/x/foo" etc.  But you can use this program
+    for any file names you like.
+ 
+    Keep in mind that you are supposed to know what you are doing when
+    you choose the file names to pass to the program.  The program
+    expects each command-line argument to be a name of a regular
+    existing file, which is deleted during the testing, and a directory
+    by the same name is created in its stead (the directory is also
+    deleted near the end of the test).  You can pass any other types of
+    arguments to the program, like non-existing files, device name, etc.,
+    but some of the tests might fail then.  For example, if you start with
+    a directory, the test of `open' will fail even if there's nothing
+    wrong with the underlying library functions.  */
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <limits.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <string.h>
+ #include <dirent.h>
+ #include <sys/vfs.h>
+ #include <utime.h>
+ #include <sys/time.h>
+ #include <process.h>
+ #include <dir.h>
+ #include <io.h>
+ 
+ #include <libc/dosio.h>
+ #include <dpmi.h>
+ #include <go32.h>
+ 
+ #define ALL_FILES (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_LABEL|FA_DIREC|FA_ARCH)
+ 
+ /* The directory where it all started.  */
+ static char *orig_dir;
+ 
+ /*
+  *
+  * Test functions.
+  *
+  */
+ 
+ /* Test functions which take zero to 2 arguments, besides the file
+    name, and return an int status.  */
+ int t_misc (const char *func, int narg, const char *fname, int arg1, int arg2)
+ {
+   int retval = -1;
+ 
+   switch (narg)
+     {
+       case 0:
+ 	if (strcmp (func, "chdir") == 0)
+ 	  {
+ 	    retval = chdir (fname);
+ 	    chdir (orig_dir);
+ 	  }
+ 	else if (strcmp (func, "rmdir") == 0)
+ 	  {
+ 	    char d_root[4];
+ 
+ 	    _put_path (fname);
+ 	    dosmemget (__tb, 2, d_root);
+ 
+ 	    /* If FNAME is on another drive, it can be the CWD on that
+ 	       drive, and DOS won't let us remove it.  So we chdir to
+ 	       the root of that drive, just in case. */
+ 	    if (d_root[0] && d_root[1] == ':')
+ 	      {
+ 		d_root[2] = '/';
+ 		d_root[3] = '\0';
+ 		chdir (d_root);
+ 	      }
+ 	    retval = rmdir (fname);
+ 	    chdir (orig_dir);
+ 	  }
+ 	else if (strcmp (func, "remove") == 0)
+ 	  {
+ 	    if (!__file_exists (fname))
+ 	      mkdir (fname, 0666);
+ 	    retval = remove (fname);
+ 	  }
+ 	else if (strcmp (func, "_use_lfn") == 0)
+ 	  retval = _use_lfn (fname);
+ 	else if (strcmp (func, "system") == 0)
+ 	  retval = system (fname);
+ 	break;
+       case 1:
+ 	if (strcmp (func, "_open") == 0)
+ 	  {
+ 	    retval = _open (fname, arg1);
+ 	    if (retval > 2)
+ 	      _close (retval);
+ 	  }
+ 	else if (strcmp (func, "chmod") == 0)
+ 	  retval = chmod (fname, arg1);
+ 	else if (strcmp (func, "access") == 0)
+ 	  retval = access (fname, arg1);
+ 	else if (strcmp (func, "mkdir") == 0)
+ 	  retval = mkdir (fname, arg1);
+ 	else if (strcmp (func, "pathconf") == 0)
+ 	  retval = pathconf (fname, arg1);
+ 	else if (strcmp (func, "truncate") == 0)
+ 	  retval = truncate (fname, arg1);
+ 	break;
+       case 2:
+ 	if (strcmp (func, "open") == 0)
+ 	  {
+ 	    retval = open (fname, arg1, arg2);
+ 	    if (retval > 2)
+ 	      close (retval);
+ 	  }
+ 	else if (strcmp (func, "_chmod") == 0)
+ 	  retval = _chmod (fname, arg1, arg2);
+ 	else if (strcmp (func, "_is_executable") == 0)
+ 	  retval = _is_executable (fname, arg1, (const char *)arg2);
+ 	else
+ 	  retval = -1;
+ 	break;
+       default:
+ 	retval = -1;
+ 	break;
+     }
+   return retval;
+ }
+ 
+ /* Test functions which copy/rename/remove the file, or transform its
+    file name.  These usually take two char * arguments.  */
+ int t_path (const char *func, int narg, const char *fname, int d1, int d2)
+ {
+   static const char *report_fmt = "%s: `%s' -> `%s'\n";
+   int retval;
+   char tpath[PATH_MAX];
+   int (*testee)(const char *, const char *) = link;
+ 
+   d2 = d1;	/* pacify gcc -Wall */
+ 
+   if (strcmp (func, "_fixpath") == 0)
+     {
+       _fixpath (fname, tpath);
+       printf (report_fmt, func, fname, tpath);
+       retval = 0;
+     }
+   else if ((strcmp (func, "link") == 0 ? testee = link : 0) != 0
+ 	   || (strcmp (func, "symlink") == 0 ? testee = symlink : 0) != 0
+ 	   || (strcmp (func, "rename") == 0 ? testee = rename : 0) != 0
+ 	   || (strcmp (func, "_rename") == 0 ? testee = _rename : 0) != 0)
+     {
+       size_t fnlast = strlen (fname) - 1;
+ 
+       /* Beginning with `!', look for a character which can be used to
+ 	 generate a name of a non-existent file by replacing with it
+ 	 the last character of FNAME.  */
+       strcpy (tpath, fname);
+       tpath[fnlast] = '!';
+       while (__file_exists (tpath))
+ 	{
+ 	  tpath[fnlast]++;
+ 
+ 	  /* Skip characters disallowed by DOS.  */
+ 	  if (strchr (".+,;=[]|<>/\\\":?*", tpath[fnlast]))
+ 	    tpath[fnlast]++;
+ 	}
+       retval = testee (fname, tpath);
+       if (retval == 0)
+ 	{
+ 	  if (testee == rename || testee == _rename)
+ 	    rename (tpath, fname);
+ 	  else
+ 	    {
+ 	      remove (tpath);
+ 
+ 	      /* `symlink' creates foo.exe */
+ 	      if (testee == symlink)
+ 		remove (strcat (tpath, ".exe"));
+ 	    }
+ 	}
+     }
+   else if (strcmp (func, "mkstemp") == 0)
+     {
+       char *s, *p;
+ 
+       strcpy (tpath, fname);
+       for (s = p = basename (tpath); p < s + 8; p++)
+ 	*p = 'X';
+       s[0] = 'f';
+       s[1] = 't';
+       *p = '\0';
+       retval = mkstemp (tpath);
+       printf (report_fmt, func, fname, tpath);
+       if (retval > 2)
+ 	{
+ 	  close (retval);
+ 	  remove (tpath);
+ 	}
+     }
+   else if (strcmp (func, "tmpnam") == 0)
+     {
+       char *p = dirname (fname);
+ 
+       if (setenv ("TMPDIR", p, 1) == -1)
+ 	{
+ 	  printf ("%s: setenv failed\n", func);
+ 	  retval = -1;
+ 	}
+       else
+ 	{
+ 	  printf (report_fmt, func, fname, tmpnam (NULL));
+ 	  retval = 0;
+ 	}
+       free (p);
+     }
+   else if (strcmp (func, "_truename") == 0)
+     {
+       char *p = _truename (fname, NULL);
+ 
+       if (p)
+ 	{
+ 	  printf (report_fmt, func, fname, p);
+ 	  retval = 0;
+ 	  free (p);
+ 	}
+       else
+ 	retval = -1;
+     }
+   else
+     retval = -1;
+ 
+   return retval;
+ }
+ 
+ /* Test findfirst.  */
+ int t_findfirst (const char *func, int narg, const char *fname, int attr, int dummy)
+ {
+   struct ffblk ff;
+ 
+   dummy = dummy;	/* shut up gcc -Wall */
+ 
+   return findfirst (fname, &ff, attr);
+ }
+ 
+ /* Test fopen.  */
+ int t_fopen (const char *func, int narg, const char *fname, int d1, int d2)
+ {
+   int retval;
+   FILE *fp = fopen (fname, "r");
+ 
+   d2 = d1;		/* keep gcc -Wall happy */
+ 
+   retval = fp == NULL ? -1 : 0;
+ 
+   if (fp)
+     fclose (fp);
+   return retval;
+ }
+ 
+ /* Test opendir.  */
+ int t_opendir (const char *func, int narg, const char *fname, int d1, int d2)
+ {
+   int retval;
+   char *fdir = dirname (fname);
+   char *base = basename (fname);
+ 
+   d2 = d1;		/* for gcc -Wall */
+ 
+   if (!fdir)
+     {
+       printf ("%s: dirname failed\n", func);
+       retval = -1;
+     }
+   else
+     {
+       DIR *dirp = opendir (fdir);
+ 
+       free (fdir);
+       if (!dirp)
+ 	retval = -1;
+       else
+ 	{
+ 	  struct dirent *de;
+ 
+ 	  retval = -1;
+ 
+ 	  /* See that we actually opened the right directory, by
+ 	     reading it until we see the file FNAME.  */
+ 	  while ((de = readdir (dirp)) != NULL)
+ 	    {
+ 	      if (strcasecmp (de->d_name, base) == 0)
+ 		{
+ 		  retval = 0;
+ 		  break;
+ 		}
+ 	    }
+ 	  closedir (dirp);
+ 	}
+     }
+   return retval;
+ }
+ 
+ /* Test spawnl.  */
+ int t_spawn (const char *func, int narg, const char *fname, int arg, int dummy)
+ {
+   dummy = dummy;	/* can't stand gcc -Wall whining */
+ 
+   if (!_is_executable (fname, -1, NULL))
+     {
+       printf ("%s: %s is not an executable file, skipping\n", func, fname);
+       return 0;
+     }
+   return spawnl (arg, fname, fname, NULL);
+ }
+ 
+ /* Test stat.  */
+ int t_stat (const char *func, int narg, const char *fname, int d1, int d2)
+ {
+   struct stat st_buf;
+ 
+   d2 = d1;		/* prevent gcc -Wall from complaining */
+   return stat (fname, &st_buf);
+ }
+ 
+ /* Test statfs.  */
+ int t_statfs (const char *func, int narg, const char *fname, int d1, int d2)
+ {
+   struct statfs sbuf;
+   int retval = statfs (fname, &sbuf);
+ 
+   d2 = d1;		/* avoid messages from gcc -Wall */
+ 
+   if (retval == 0)
+     {
+       char dos_path[FILENAME_MAX];
+       int dev_drv;
+ 
+       /* Make sure "/dev/x/foo" reports the correct drive, not the
+          current one.  */
+       _fixpath (fname, dos_path);
+       dev_drv = (dos_path[0] & 0x1f) - 1;
+       if (dev_drv != sbuf.f_fsid[0])
+ 	retval = -1;
+     }
+   return retval;
+ }
+ 
+ /* Test utime.  */
+ int t_utime (const char *func, int narg, const char *fname, int at, int mt)
+ {
+   struct utimbuf tb = {(time_t)at, (time_t)mt};
+   return utime (fname, &tb);
+ }
+ 
+ struct fs_test {
+   const char *func_name;
+   int nargs;
+   int (*tester)(const char *, int, const char *, int, int);
+   int arg1;
+   int arg2;
+   int result;
+   int negate_result;
+ } test_vec[] = {  /* the order of the tests below is not entirely arbitrary! */
+     {"_open", 1, t_misc, O_RDONLY, 0, -1, 1},
+     {"open", 2, t_misc, O_RDONLY, 0666, -1, 1},
+     {"_chmod", 2, t_misc, 0, 0, -1, 1},
+     {"chmod", 1, t_misc, S_IWUSR, 0, 0, 0},
+     {"access", 1, t_misc, R_OK, 0, 0, 0},
+     {"findfirst", 2, t_findfirst, 0, ALL_FILES, 0, 0},
+     {"_fixpath", 1, t_path, 0, 0, 0, 0},
+     {"fopen", 1, t_fopen, 0, 0, 0, 0},
+     {"_is_executable", 2, t_misc, -1, 0, 1, 0},
+     {"link", 1, t_path, 0, 0, 0, 0},
+     {"mkstemp", 0, t_path, 0, 0, -1, 1},
+     {"opendir", 0, t_opendir, 0, 0, -1, 1},
+     {"pathconf", 1, t_misc, _PC_NAME_MAX, 0, 256, 0},
+     {"_rename", 1, t_path, 0, 0, 0, 0},
+     {"rename", 1, t_path, 0, 0, 0, 0},
+     {"spawnl", 2, t_spawn, P_WAIT, 0, -1, 1},
+     {"stat", 1, t_stat, 0, 0, 0, 0},
+     {"statfs", 0, t_statfs, 0, 0, 0, 0},
+     {"symlink", 1, t_path, 0, 0, 0, 0},
+     {"system", 0, t_misc, 0, 0, -1, 1},
+     {"tmpnam", 0, t_path, 0, 0, 0, 0},
+     {"_truename", 1, t_path, 0, 0, 0, 0},
+     {"truncate", 1, t_misc, 0, 0, 0, 0},
+     {"utime", 2, t_utime, 930000000, 925000000, 0, 0},
+     {"remove", 0, t_misc, 0, 0, 0, 0},
+     {"mkdir", 1, t_misc, S_IWUSR, 0, 0, 0},
+     {"chdir", 0, t_misc, 0, 0, 0, 0},
+     {"_use_lfn", 0, t_misc, 0, 0, 1, 0},
+     {"rmdir", 0, t_misc, 0, 0, 0, 0}
+ };
+ 
+ /* Non-zero when verbose operation was requested.  */
+ static int verbose = 0;
+ 
+ /* Run a single file FILE through all the tests.  */
+ int fstest (const char *file)
+ {
+   int i, retval = 0;
+ 
+   for (i = 0; i < sizeof (test_vec) / sizeof (test_vec[0]); i++)
+     {
+       int result;
+ 
+       if (verbose)
+ 	printf ("\nTesting %s(%s)...", test_vec[i].func_name, file);
+       errno = 0;
+       result = test_vec[i].tester(test_vec[i].func_name, test_vec[i].nargs,
+ 				  file, test_vec[i].arg1, test_vec[i].arg2);
+       if (test_vec[i].negate_result
+ 	  ? result == test_vec[i].result
+ 	  : result != test_vec[i].result)
+ 	{
+ 	  printf ("%s%s(%s): incorrect result: %d (expected: %s%d)\n",
+ 		  verbose ? "\n" : "",
+ 		  test_vec[i].func_name, file, result,
+ 		  test_vec[i].negate_result ? "NOT " : "",
+ 		  test_vec[i].result);
+ 	  if (errno)
+ 	    printf ("System error was: %s\n", strerror (errno));
+ 	  retval++;
+ 	}
+     }
+   return retval;
+ }
+ 
+ int main (int argc, char **argv)
+ {
+   if (argc == 1)
+     {
+       printf ("Usage: %s [-v] file...\n", argv[0]);
+       return 0;
+     }
+ 
+   orig_dir = getcwd (NULL, PATH_MAX);
+ 
+   if (strcmp (argv[1], "-v") == 0)
+     {
+       verbose = 1;
+       --argc;
+       ++argv;
+     }
+ 
+   while (--argc)
+     {
+       char *arg = *++argv;
+ 
+       if (fstest (arg) == -1)
+ 	return 1;
+     }
+ 
+   return 0;
+ }
*** tests/libc/dos/io/makefile.~0	Thu Jan  1 19:03:16 1998
--- tests/libc/dos/io/makefile	Sat Dec 12 19:03:56 1998
***************
*** 4,8 ****
--- 4,9 ----
  SRC += cbrk.c
  SRC += ctrlc.c
  SRC += putpath.c
+ SRC += filesys.c
  
  include $(TOP)/../makefile.inc

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019