diff -acrpNC5 fileutils-3.16.orig/lib/backupfile.c fileutils-3.16.djgpp/lib/backupfile.c
*** fileutils-3.16.orig/lib/backupfile.c	Wed Dec 18 03:29:38 1996
--- fileutils-3.16.djgpp/lib/backupfile.c	Mon May 22 15:13:48 2000
*************** max_backup_version (file, dir)
*** 162,172 ****
    highest_version = 0;
    file_name_length = strlen (file);
  
    while ((dp = readdir (dirp)) != 0)
      {
!       if (!REAL_DIR_ENTRY (dp) || NLENGTH (dp) <= file_name_length)
  	continue;
  
        this_version = version_number (file, dp->d_name, file_name_length);
        if (this_version > highest_version)
  	highest_version = this_version;
--- 162,181 ----
    highest_version = 0;
    file_name_length = strlen (file);
  
    while ((dp = readdir (dirp)) != 0)
      {
!       if (!REAL_DIR_ENTRY (dp)
! #if !defined(MSDOS) || defined(__DJGPP__)
! 	  || (NLENGTH (dp) <= file_name_length
! #ifdef __DJGPP__
! 	      /* When long filenames aren't supported, examine all files.  */
! 	      && _use_lfn (dir)
! #endif
! 	      )
! #endif
! 	  )
  	continue;
  
        this_version = version_number (file, dp->d_name, file_name_length);
        if (this_version > highest_version)
  	highest_version = this_version;
*************** make_version_name (file, version)
*** 188,197 ****
--- 197,223 ----
  
    backup_name = malloc (strlen (file) + 16);
    if (backup_name == 0)
      return 0;
    sprintf (backup_name, "%s.~%d~", file, version);
+ #ifdef MSDOS
+ #ifdef __DJGPP__
+   /* If long filenames are supported on the filesystem where FILE belongs,
+      we don't need to squeeze the backup suffix into 8+3 namespace.  */
+   if (!_use_lfn (file))
+ #endif
+     {
+       char *short_name;
+ 
+       /* Let `concat' do the hard job (see below) when we
+ 	 cannot use long filenames.  */
+       sprintf (backup_name, ".~%d~", version);
+       short_name = concat (file, backup_name);
+       free (backup_name);
+       backup_name = short_name;
+     }
+ #endif
    return backup_name;
  }
  
  /* If BACKUP is a numbered backup of BASE, return its version number;
     otherwise return 0.  BASE_LENGTH is the length of BASE.
*************** version_number (base, backup, base_lengt
*** 205,214 ****
--- 231,266 ----
  {
    int version;
    const char *p;
  
    version = 0;
+ #ifdef MSDOS
+ #ifdef __DJGPP__
+   /* Neither BASE nor BACKUP don't include a full pathname, so we
+      don't have a pathname to call `_use_lfn'.  But since we already
+      called `_use_lfn' with a full pathname of this file (in
+      max_backup_version above), we are asking here about the same
+      filesystem, and so the call to _use_lfn (0) should do.  */
+   if (!_use_lfn (0))
+ #endif
+     {
+       /* When long filenames aren't supported, the numbered backup
+ 	 suffix moves into the name; see `concat'.  We want filenames
+ 	 like e.g. "foo.bar" and "foo1234~" to match here.
+ 	 The call to `strncmp' is of course superflous after this,
+ 	 but letting the non-LFN systems suffer leaves the code cleaner.  */
+       const char *pbase = base, *pbackup = backup;
+       int len;
+ 
+       for (len = base_length; len; len--)
+ 	if (*pbase++ != *pbackup++)
+ 	  {
+ 	    base_length -= len;
+ 	    break;
+ 	  }
+     }
+ #endif
    if (!strncmp (base, backup, base_length) && ISDIGIT (backup[base_length]))
      {
        for (p = &backup[base_length]; ISDIGIT (*p); ++p)
  	version = version * 10 + *p - '0';
        if (p[0] != '~' || p[1])
*************** concat (str1, str2)
*** 231,237 ****
--- 283,392 ----
    newstr = malloc (str1_length + strlen (str2) + 1);
    if (newstr == 0)
      return 0;
    strcpy (newstr, str1);
    strcpy (newstr + str1_length, str2);
+ #ifdef MSDOS
+ #ifdef __DJGPP__
+   if (!_use_lfn (newstr))
+ #endif
+     {
+       /* Without long filenames, we have to live with the darn 8+3
+ 	 basename restriction.  The only way to have numbered
+ 	 backups in that case is to eat some characters off the end
+ 	 of the original name.  */
+       char *base = basename (newstr);
+       int baselen = strlen (base);
+       char *dot;
+       char *str2_start = newstr + str1_length;
+       int s2_len = strlen (str2_start);
+       int extlen;
+       int str2_starts_with_dot;
+ 
+       /* Kludgy feature: if `STR1' already has an extension, and
+ 	 `STR2' begins with ".~", we remove the `~'.  This is so
+ 	 we could salvage at least 1 character of the original
+ 	 extension for the first 9 backups (e.g., "foo.c" + ".~7~"
+ 	 is ``concatenated'' into "foo.c7~", not "foo.~7~").  */
+       if (memchr (base, '.', baselen - s2_len)
+ 	  && (*str2_start == '.' && str2_start[1] == '~'))
+ 	{
+ 	  memmove (str2_start + 1, str2_start + 2, s2_len - 1);
+ 	  s2_len--;
+ 	  baselen--;
+ 	}
+ 
+       /* Weed out all but the first dot in `base'.  */
+       dot = memchr (base, '.', baselen);
+       if (dot)
+ 	{
+ 	  char *s = dot + 1;
+ 	  char *d = s;
+ 	  int dots_before_str2 = 0;
+ 
+ 	  do {
+ 	    while (*s == '.')
+ 	      {
+ 		if (s < str2_start)
+ 		  dots_before_str2++;
+ 		else
+ 		  s2_len--;
+ 		s++;
+ 		baselen--;
+ 	      }
+ 	  } while ((*d++ = *s++));
+ 
+ 	  str2_start -= dots_before_str2;
+ 	  extlen = baselen - (dot - base) - 1; /* 1 for the dot itself */
+ 	}
+       else
+ 	{
+ 	  dot = base + baselen;
+ 	  extlen = 0;
+ 	}
+ 
+       /* Make sure `STR2' will not be truncated by the OS.  If `STR2' is
+ 	 in the extension, it must be in the first 3 characters after the
+ 	 dot; if it's before the dot, it must be one of the first 8
+ 	 characters of the basename.  */
+       str2_starts_with_dot = str2_start[0] == '.';
+       if (extlen > 3)
+ 	{
+ 	  char *new_str2_start;
+ 
+ 	  s2_len = strlen (str2_start);
+ 	  if (s2_len <= 3 + str2_starts_with_dot)
+ 	    new_str2_start = dot + !str2_starts_with_dot + 3 - s2_len;
+ 	  else
+ 	    {
+ 	      new_str2_start = dot;
+ 	      if (str2_start == new_str2_start)
+ 		{
+ 		  /* The case of foo -> foo.~10~
+ 		     The original file has no extension, but the backup
+ 		     extension is longer than 3 characters.  We need to
+ 		     move the extension into the name (make it foo10~).  */
+ 		  if (*++str2_start == '~')
+ 		    str2_start++;
+ 		  s2_len -= str2_start - dot;
+ 		}
+ 	      dot += s2_len;
+ 	    }
+ 	  memmove (new_str2_start, str2_start, s2_len + 1);
+ 	  str2_start = new_str2_start;
+ 	}
+       /* If the name part (before the dot) is longer than 8 characters,
+ 	 we cannot be sure it won't clash with an existing file.  So we
+ 	 must move `STR2' into the name.  */
+       if (dot - base > 8)
+ 	{
+ 	  if (str2_starts_with_dot)
+ 	    {
+ 	      str2_start++;
+ 	      s2_len--;
+ 	    }
+ 	  memmove (base + 8 - s2_len, str2_start, s2_len + 1);
+ 	}
+     }
+ #endif /* MSDOS */
    return newstr;
  }
diff -acrpNC5 fileutils-3.16.orig/lib/basename.c fileutils-3.16.djgpp/lib/basename.c
*** fileutils-3.16.orig/lib/basename.c	Mon Jul 15 03:56:28 1996
--- fileutils-3.16.djgpp/lib/basename.c	Mon May 22 15:13:48 2000
*************** basename (name)
*** 28,38 ****
  {
    const char *base = name;
  
    while (*name)
      {
!       if (*name == '/')
  	base = name + 1;
        ++name;
      }
    return (char *) base;
  }
--- 28,42 ----
  {
    const char *base = name;
  
    while (*name)
      {
!       if (*name == '/'
! #ifdef MSDOS
! 	  || *name == ':'
! #endif
! 	  )
  	base = name + 1;
        ++name;
      }
    return (char *) base;
  }
diff -acrpNC5 fileutils-3.16.orig/lib/dirname.c fileutils-3.16.djgpp/lib/dirname.c
*** fileutils-3.16.orig/lib/dirname.c	Mon Jul 15 03:35:12 1996
--- fileutils-3.16.djgpp/lib/dirname.c	Mon May 22 15:13:48 2000
*************** char *malloc ();
*** 33,43 ****
  #endif
  #endif
  
  /* Return the leading directories part of PATH,
     allocated with malloc.  If out of memory, return 0.
!    Assumes that trailing slashes have already been
     removed.  */
  
  char *
  dirname (path)
       char *path;
--- 33,43 ----
  #endif
  #endif
  
  /* Return the leading directories part of PATH,
     allocated with malloc.  If out of memory, return 0.
!    Does NOT assume that trailing slashes have already been
     removed.  */
  
  char *
  dirname (path)
       char *path;
*************** dirname (path)
*** 45,54 ****
--- 45,63 ----
    char *newpath;
    char *slash;
    int length;			/* Length of result, not including NUL.  */
  
    slash = strrchr (path, '/');
+ #ifdef MSDOS
+   /* If we have "d:file", make the directory be "d:"  */
+   if (slash == 0 && path[1] == ':')
+     slash = path + 1;
+   /* If we have "d:/file", make the directory be "d:/", not "d:"  */
+   if (slash && slash == path + 2 && path[1] == ':' && path[2] == '/')
+     length = 3;
+   else
+ #endif
    if (slash == 0)
      {
        /* File is in the current directory.  */
        path = ".";
        length = 1;
diff -acrpNC5 fileutils-3.16.orig/lib/euidaccess.c fileutils-3.16.djgpp/lib/euidaccess.c
*** fileutils-3.16.orig/lib/euidaccess.c	Mon Jul 15 03:37:44 1996
--- fileutils-3.16.djgpp/lib/euidaccess.c	Mon May 22 15:13:48 2000
*************** euidaccess (path, mode)
*** 150,159 ****
--- 150,160 ----
  
    if (uid == euid && gid == egid)
      /* If we are not set-uid or set-gid, access does the same.  */
      return access (path, mode);
  
+ #ifndef MSDOS
    if (stat (path, &stats))
      return -1;
  
    mode &= (X_OK | W_OK | R_OK);	/* Clear any bogus bits. */
  #if R_OK != S_IROTH || W_OK != S_IWOTH || X_OK != S_IXOTH
*************** euidaccess (path, mode)
*** 177,182 ****
--- 178,184 ----
      granted = (stats.st_mode & mode);
    if (granted == mode)
      return 0;
    errno = EACCESS;
    return -1;
+ #endif /* !MSDOS */
  }
diff -acrpNC5 fileutils-3.16.orig/lib/fileblocks.c fileutils-3.16.djgpp/lib/fileblocks.c
*** fileutils-3.16.orig/lib/fileblocks.c	Mon Jul 15 03:35:12 1996
--- fileutils-3.16.djgpp/lib/fileblocks.c	Mon May 22 15:13:48 2000
***************
*** 19,29 ****
  
  #ifdef HAVE_CONFIG_H
  # include <config.h>
  #endif
  
! #if !defined (HAVE_ST_BLOCKS) && !defined(_POSIX_VERSION)
  # include <sys/types.h>
  # include <sys/param.h>
  
  # ifndef NINDIR
  /* Some SysV's, like Irix, seem to lack these.  Hope they're correct. */
--- 19,29 ----
  
  #ifdef HAVE_CONFIG_H
  # include <config.h>
  #endif
  
! #if !defined (HAVE_ST_BLOCKS) && !defined(_POSIX_VERSION) && !defined(MSDOS)
  # include <sys/types.h>
  # include <sys/param.h>
  
  # ifndef NINDIR
  /* Some SysV's, like Irix, seem to lack these.  Hope they're correct. */
diff -acrpNC5 fileutils-3.16.orig/lib/getdate.y fileutils-3.16.djgpp/lib/getdate.y
*** fileutils-3.16.orig/lib/getdate.y	Sun Jan 19 04:11:34 1997
--- fileutils-3.16.djgpp/lib/getdate.y	Mon May 22 15:13:48 2000
*************** relunit	: tUNUMBER tYEAR_UNIT {
*** 345,400 ****
  	}
  	| tSNUMBER tYEAR_UNIT {
  	    yyRelYear += $1 * $2;
  	}
  	| tYEAR_UNIT {
! 	    yyRelYear++;
  	}
  	| tUNUMBER tMONTH_UNIT {
  	    yyRelMonth += $1 * $2;
  	}
  	| tSNUMBER tMONTH_UNIT {
  	    yyRelMonth += $1 * $2;
  	}
  	| tMONTH_UNIT {
! 	    yyRelMonth++;
  	}
  	| tUNUMBER tDAY_UNIT {
  	    yyRelDay += $1 * $2;
  	}
  	| tSNUMBER tDAY_UNIT {
  	    yyRelDay += $1 * $2;
  	}
  	| tDAY_UNIT {
! 	    yyRelDay++;
  	}
  	| tUNUMBER tHOUR_UNIT {
  	    yyRelHour += $1 * $2;
  	}
  	| tSNUMBER tHOUR_UNIT {
  	    yyRelHour += $1 * $2;
  	}
  	| tHOUR_UNIT {
! 	    yyRelHour++;
  	}
  	| tUNUMBER tMINUTE_UNIT {
  	    yyRelMinutes += $1 * $2;
  	}
  	| tSNUMBER tMINUTE_UNIT {
  	    yyRelMinutes += $1 * $2;
  	}
  	| tMINUTE_UNIT {
! 	    yyRelMinutes++;
  	}
  	| tUNUMBER tSEC_UNIT {
  	    yyRelSeconds += $1 * $2;
  	}
  	| tSNUMBER tSEC_UNIT {
  	    yyRelSeconds += $1 * $2;
  	}
  	| tSEC_UNIT {
! 	    yyRelSeconds++;
  	}
  	;
  
  number	: tUNUMBER
            {
--- 345,400 ----
  	}
  	| tSNUMBER tYEAR_UNIT {
  	    yyRelYear += $1 * $2;
  	}
  	| tYEAR_UNIT {
! 	    yyRelYear += $1;
  	}
  	| tUNUMBER tMONTH_UNIT {
  	    yyRelMonth += $1 * $2;
  	}
  	| tSNUMBER tMONTH_UNIT {
  	    yyRelMonth += $1 * $2;
  	}
  	| tMONTH_UNIT {
! 	    yyRelMonth += $1;
  	}
  	| tUNUMBER tDAY_UNIT {
  	    yyRelDay += $1 * $2;
  	}
  	| tSNUMBER tDAY_UNIT {
  	    yyRelDay += $1 * $2;
  	}
  	| tDAY_UNIT {
! 	    yyRelDay += $1;
  	}
  	| tUNUMBER tHOUR_UNIT {
  	    yyRelHour += $1 * $2;
  	}
  	| tSNUMBER tHOUR_UNIT {
  	    yyRelHour += $1 * $2;
  	}
  	| tHOUR_UNIT {
! 	    yyRelHour += $1;
  	}
  	| tUNUMBER tMINUTE_UNIT {
  	    yyRelMinutes += $1 * $2;
  	}
  	| tSNUMBER tMINUTE_UNIT {
  	    yyRelMinutes += $1 * $2;
  	}
  	| tMINUTE_UNIT {
! 	    yyRelMinutes += $1;
  	}
  	| tUNUMBER tSEC_UNIT {
  	    yyRelSeconds += $1 * $2;
  	}
  	| tSNUMBER tSEC_UNIT {
  	    yyRelSeconds += $1 * $2;
  	}
  	| tSEC_UNIT {
! 	    yyRelSeconds += $1;
  	}
  	;
  
  number	: tUNUMBER
            {
diff -acrpNC5 fileutils-3.16.orig/lib/makepath.c fileutils-3.16.djgpp/lib/makepath.c
*** fileutils-3.16.orig/lib/makepath.c	Mon Nov  4 17:59:24 1996
--- fileutils-3.16.djgpp/lib/makepath.c	Mon May 22 15:13:48 2000
*************** extern int errno;
*** 69,79 ****
  # ifndef strchr
  #  define strchr index
  # endif
  #endif
  
! #ifdef __MSDOS__
  typedef int uid_t;
  typedef int gid_t;
  #endif
  
  #include "makepath.h"
--- 69,79 ----
  # ifndef strchr
  #  define strchr index
  # endif
  #endif
  
! #if defined(__MSDOS__) && !defined(HAVE_CONFIG_H)
  typedef int uid_t;
  typedef int gid_t;
  #endif
  
  #include "makepath.h"
diff -acrpNC5 fileutils-3.16.orig/lib/path-concat.c fileutils-3.16.djgpp/lib/path-concat.c
*** fileutils-3.16.orig/lib/path-concat.c	Tue Oct  1 01:08:38 1996
--- fileutils-3.16.djgpp/lib/path-concat.c	Mon May 22 15:13:48 2000
*************** path_concat (dir, base, base_in_result)
*** 47,56 ****
--- 47,65 ----
  
    p = stpcpy (p_concat, dir);
  
    if (*(p - 1) == '/' && *base == '/')
      --p;
+ #ifdef MSDOS
+   /* Make sure "path1"+"d:/path2" yields "path1/path2".  */
+   else if (base[1] == ':' && (base += 2) == 0)
+     /* Fall-through to next else-if clause (base += 2 is never 0).  */
+     ;
+   /* Make sure "d:"+"path" yields "d:path", not "d:/path".  */
+   else if (*(p - 1) == ':')
+     ;
+ #endif
    else if (*(p - 1) != '/' && *base != '/')
      p = stpcpy (p, "/");
  
    if (base_in_result)
      *base_in_result = p;
diff -acrpNC5 fileutils-3.16.orig/lib/stripslash.c fileutils-3.16.djgpp/lib/stripslash.c
*** fileutils-3.16.orig/lib/stripslash.c	Tue Oct 29 13:42:54 1996
--- fileutils-3.16.djgpp/lib/stripslash.c	Mon May 22 15:13:48 2000
*************** strip_trailing_slashes (path)
*** 36,43 ****
--- 36,52 ----
       char *path;
  {
    int last;
  
    last = strlen (path) - 1;
+ #ifdef MSDOS
+   /* Leave alone a single slash in "d:/".  "d:" means something
+      VERY different on MSDOS.  */
+   if (path[1] == ':')
+     {
+       path += 2;
+       last -= 2;
+     }
+ #endif
    while (last > 0 && path[last] == '/')
      path[last--] = '\0';
  }
diff -acrpNC5 fileutils-3.16.orig/lib/userspec.c fileutils-3.16.djgpp/lib/userspec.c
*** fileutils-3.16.orig/lib/userspec.c	Mon Jul 15 03:35:14 1996
--- fileutils-3.16.djgpp/lib/userspec.c	Mon May 22 15:13:48 2000
*************** parse_user_spec (spec_arg, uid, gid, use
*** 158,168 ****
--- 158,173 ----
        pwd = getpwnam (u);
        if (pwd == NULL)
  	{
  
  	  if (!is_number (u))
+ #ifdef  MSDOS
+ 	    /* Under MS-DOS we allow to give away files to ANY user.  */
+ 	    *uid = 2*getuid();	/* why twice, you ask? why not? */
+ #else
  	    error_msg = "invalid user";
+ #endif
  	  else
  	    {
  	      int use_login_group;
  	      use_login_group = (separator != NULL && g == NULL);
  	      if (use_login_group)
*************** parse_user_spec (spec_arg, uid, gid, use
*** 204,214 ****
--- 209,224 ----
        /* Explicit group.  */
        grp = getgrnam (g);
        if (grp == NULL)
  	{
  	  if (!is_number (g))
+ #ifdef  MSDOS
+ 	    /* Under MS-DOS we allow to give away files to ANY group.  */
+ 	    *gid = 2*getgid();
+ #else
  	    error_msg = "invalid group";
+ #endif
  	  else
  	    *gid = atoi (g);
  	}
        else
  	*gid = grp->gr_gid;
diff -acrpNC5 fileutils-3.16.orig/src/cp.c fileutils-3.16.djgpp/src/cp.c
*** fileutils-3.16.orig/src/cp.c	Sun Jan 26 04:26:28 1997
--- fileutils-3.16.djgpp/src/cp.c	Mon May 22 15:13:48 2000
*************** do_copy (int argc, char **argv)
*** 412,421 ****
--- 412,435 ----
        usage (1);
      }
  
    dest = argv[argc - 1];
  
+ #ifdef MSDOS
+   /* "d:" means current dir on drive d:  */
+   if (dest[1] == ':' && dest[2] != '/')
+     {
+       char *newname = alloca (PATH_MAX + 1);
+       int   add_slash = dest[strlen (dest) - 1] == '/';
+ 
+       FIXPATH (dest, newname);	/* convert "d:" into an absolute pathname */
+       dest = newname;
+       if (add_slash)		/* dest/ has a special meaning in `cp' */
+ 	strcat (dest, "/");
+     }
+ #endif
+ 
    if (lstat (dest, &sb))
      {
        if (errno != ENOENT)
  	{
  	  error (0, errno, "%s", dest);
*************** do_copy (int argc, char **argv)
*** 450,459 ****
--- 464,484 ----
  	  struct dir_attr *attr_list;
  	  char *arg_in_concat = NULL;
  
  	  arg = argv[optind];
  
+ #ifdef  MSDOS
+ 	  /* Convert "d:path" into a full path.  */
+ 	  if (arg[1] == ':' && arg[2] != '/')
+ 	    {
+ 	      char *newarg = alloca (PATH_MAX);
+ 
+ 	      FIXPATH (arg, newarg);
+ 	      arg = newarg;
+ 	    }
+ #endif
+ 
  	  strip_trailing_slashes (arg);
  
  	  if (flag_path)
  	    {
  	      /* Append all of `arg' to `dest'.  */
*************** do_copy (int argc, char **argv)
*** 519,528 ****
--- 544,564 ----
  	  usage (1);
  	}
  
        source = argv[optind];
  
+ #ifdef  MSDOS
+ 	  /* Convert "d:path" into a full path.  */
+ 	  if (source[1] == ':' && source[2] != '/')
+ 	    {
+ 	      char *newsource = alloca (PATH_MAX + 1);
+ 
+ 	      FIXPATH (source, newsource);
+ 	      source = newsource;
+ 	    }
+ #endif
+ 
        /* When the force and backup options have been specified and
  	 the source and destination are the same name for an existing
  	 regular file, convert the user's command, e.g.,
  	 `cp --force --backup foo foo' to `cp --force foo fooSUFFIX'
  	 where SUFFIX is determined by any version control options used.  */
*************** copy (const char *src_path, const char *
*** 688,697 ****
--- 724,741 ----
  		  fprintf (stderr, _("%s: overwrite `%s'? "),
  			   program_name, dst_path);
  		}
  	      if (!yesno ())
  		return 0;
+ #ifdef MSDOS
+ 	      /* Make it writable, so the copy will succeed.  */
+ 	      if (chmod (dst_path, 0200))
+ 		{
+ 		  error (0, errno, "%s", dst_path);
+ 		  return 1;
+ 		}
+ #endif
  	    }
  
  	  if (backup_type != none && !S_ISDIR (dst_sb.st_mode))
  	    {
  	      char *tmp_backup = find_backup_file_name (dst_path);
*************** copy (const char *src_path, const char *
*** 964,974 ****
        struct utimbuf utb;
  
        utb.actime = src_sb.st_atime;
        utb.modtime = src_sb.st_mtime;
  
!       if (utime (dst_path, &utb))
  	{
  	  error (0, errno, "%s", dst_path);
  	  return 1;
  	}
  
--- 1008,1024 ----
        struct utimbuf utb;
  
        utb.actime = src_sb.st_atime;
        utb.modtime = src_sb.st_mtime;
  
!       if (utime (dst_path, &utb)
! #ifdef  MSDOS
! 	  /* MS-DOS doesn't allow to change timestamp of a directory :-(
! 	     If we try, we'll get an ugly error message.  */
! 	  && !S_ISDIR (src_type)
! #endif
! 	  )
  	{
  	  error (0, errno, "%s", dst_path);
  	  return 1;
  	}
  
*************** copy_dir (const char *src_path_in, const
*** 1243,1253 ****
--- 1293,1313 ----
        int fn_length = strlen (namep) + 1;
  
        dst_path = xmalloc (strlen (dst_path_in) + fn_length + 1);
        src_path = xmalloc (strlen (src_path_in) + fn_length + 1);
  
+ #ifdef MSDOS
+       if (src_path_in[strlen (src_path_in) - 1] == '/')
+ 	stpcpy (stpcpy (src_path, src_path_in), namep);
+       else
+ #endif
        stpcpy (stpcpy (stpcpy (src_path, src_path_in), "/"), namep);
+ #ifdef MSDOS
+       if (dst_path_in[strlen (dst_path_in) - 1] == '/')
+ 	stpcpy (stpcpy (dst_path, dst_path_in), namep);
+       else
+ #endif
        stpcpy (stpcpy (stpcpy (dst_path, dst_path_in), "/"), namep);
  
        ret |= copy (src_path, dst_path, new_dst, src_sb->st_dev, ancestors);
  
        /* Free the memory for `src_path'.  The memory for `dst_path'
diff -acrpNC5 fileutils-3.16.orig/src/dd.c fileutils-3.16.djgpp/src/dd.c
*** fileutils-3.16.orig/src/dd.c	Sat Nov  2 23:42:12 1996
--- fileutils-3.16.djgpp/src/dd.c	Mon May 22 15:13:48 2000
*************** static unsigned r_full = 0;
*** 167,176 ****
--- 167,180 ----
  static unsigned r_truncate = 0;
  
  /* Output representation of newline and space characters.
     They change if we're converting to EBCDIC.  */
  static unsigned char newline_character = '\n';
+ #ifdef MSDOS
+ static unsigned char cr_character = '\r';
+ static int pending_cr = 0;
+ #endif
  static unsigned char space_character = ' ';
  
  struct conversion
  {
    char *convname;
*************** copy (void)
*** 657,677 ****
    if ((conversions_mask & C_BLOCK) && col > 0)
      {
        /* If the final input line didn't end with a '\n', pad
  	 the output block to `conversion_blocksize' chars.  */
        int pending_spaces = max (0, conversion_blocksize - col);
        while (pending_spaces)
  	{
  	  output_char (space_character);
  	  --pending_spaces;
  	}
      }
  
    if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)
!     /* Add a final '\n' if there are exactly `conversion_blocksize'
!        characters in the final record. */
!     output_char (newline_character);
  
    /* Write out the last block. */
    if (oc > 0)
      {
        int nwritten = full_write (output_fd, obuf, oc);
--- 661,696 ----
    if ((conversions_mask & C_BLOCK) && col > 0)
      {
        /* If the final input line didn't end with a '\n', pad
  	 the output block to `conversion_blocksize' chars.  */
        int pending_spaces = max (0, conversion_blocksize - col);
+ 
+ #ifdef MSDOS
+       if (pending_cr)
+ 	{
+ 	  output_char (cr_character);
+ 	  if (pending_spaces)
+ 	    pending_spaces--;
+ 	}
+ #endif
        while (pending_spaces)
  	{
  	  output_char (space_character);
  	  --pending_spaces;
  	}
      }
  
    if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)
!     {
!       /* Add a final '\n' if there are exactly `conversion_blocksize'
! 	 characters in the final record. */
! #ifdef MSDOS
!       /* Make DOS-style text file (we do I/O in binary mode!).  */
!       output_char (cr_character);
! #endif
!       output_char (newline_character);
!     }
  
    /* Write out the last block. */
    if (oc > 0)
      {
        int nwritten = full_write (output_fd, obuf, oc);
*************** copy_with_block (unsigned char *buf, int
*** 725,734 ****
--- 744,779 ----
  {
    register int i;
  
    for (i = nread; i; i--, buf++)
      {
+ #ifdef MSDOS
+       /* Output the CR left from the previous buffer, if the first
+ 	 character of this buffer isn't a newline.  */
+       if (i == nread && pending_cr && *buf != newline_character)
+ 	{
+ 	  output_char (cr_character);
+ 	  pending_cr = 0;
+ 	  col++;
+ 	}
+ 
+       /* If we have CR-LF pair, lose the CR character too.  */
+       if (*buf == cr_character)
+ 	{
+ 	  if (i == 1)	/* last char, defer decision until next BUF */
+ 	    {
+ 	      pending_cr = 1;
+ 	      continue;
+ 	    }
+ 	  else if (buf[1] == newline_character)
+ 	    {
+ 	      buf++;
+ 	      i--;
+ 	      pending_cr = 0;
+ 	    }
+ 	}
+ #endif /* MSDOS */
        if (*buf == newline_character)
  	{
  	  int pending_spaces = max (0, conversion_blocksize - col);
  	  while (pending_spaces)
  	    {
*************** copy_with_unblock (unsigned char *buf, i
*** 765,774 ****
--- 810,823 ----
  
        if (col++ >= conversion_blocksize)
  	{
  	  col = pending_spaces = 0; /* Wipe out any pending spaces.  */
  	  i--;			/* Push the char back; get it later. */
+ #ifdef MSDOS
+ 	  /* Make DOS-style text file (we do BINARY I/O!).  */
+ 	  output_char (cr_character);
+ #endif
  	  output_char (newline_character);
  	}
        else if (c == space_character)
  	pending_spaces++;
        else
*************** only one conv in {ascii,ebcdic,ibm}, {lc
*** 999,1014 ****
--- 1048,1065 ----
  
    if (conversions_mask & C_EBCDIC)
      {
        translate_charset (ascii_to_ebcdic);
        newline_character = ascii_to_ebcdic['\n'];
+       cr_character = ascii_to_ebcdic['\r'];
        space_character = ascii_to_ebcdic[' '];
      }
    else if (conversions_mask & C_IBM)
      {
        translate_charset (ascii_to_ibm);
        newline_character = ascii_to_ibm['\n'];
+       cr_character = ascii_to_ebcdic['\r'];
        space_character = ascii_to_ibm[' '];
      }
  }
  
  static void
diff -acrpNC5 fileutils-3.16.orig/src/df.c fileutils-3.16.djgpp/src/df.c
*** fileutils-3.16.orig/src/df.c	Tue Dec 10 00:05:38 1996
--- fileutils-3.16.djgpp/src/df.c	Mon May 22 19:05:26 2000
*************** show_dev (const char *disk, const char *
*** 252,271 ****
--- 252,292 ----
    long blocks_used;
    long blocks_percent_used;
    long inodes_used;
    long inodes_percent_used;
    const char *stat_file;
+ #ifdef __DJGPP__
+   char real_drive_name[4];
+ #endif
  
    if (!selected_fstype (fstype) || excluded_fstype (fstype))
      return;
  
    /* If MOUNT_POINT is NULL, then the filesystem is not mounted, and this
       program reports on the filesystem that the special file is on.
       It would be better to report on the unmounted filesystem,
       but statfs doesn't do that on most systems.  */
    stat_file = mount_point ? mount_point : disk;
  
+ #ifdef __DJGPP__
+   /* JOINed disks seem like a directory on another disk.
+      We want to see the info about the real drive.  */
+   if (fstype && strcmp (fstype, "join") == 0)
+     {
+       struct stat real_drive_stats;
+ 
+       if (stat (stat_file, &real_drive_stats))
+         {
+           error (0, errno, "%s", stat_file);
+           exit_status = 1;
+           return;
+         }
+       sprintf (real_drive_name, "%c:/", real_drive_stats.st_dev + 'A');
+       stat_file = real_drive_name;
+     }
+ #endif
+ 
    if (get_fs_usage (stat_file, disk, &fsu))
      {
        error (0, errno, "%s", stat_file);
        exit_status = 1;
        return;
diff -acrpNC5 fileutils-3.16.orig/src/dircolors.c fileutils-3.16.djgpp/src/dircolors.c
*** fileutils-3.16.orig/src/dircolors.c	Sun Jan 26 05:54:16 1997
--- fileutils-3.16.djgpp/src/dircolors.c	Mon May 22 15:13:48 2000
*************** dc_parse_stream (FILE *fp, const char *f
*** 259,268 ****
--- 259,272 ----
  
    state = ST_GLOBAL;
  
    /* Get terminal type */
    term = getenv ("TERM");
+ #ifdef __DJGPP__
+   /* DJGPP port can always colorize, but TERM is not usually defined there.  */
+   term = "console";
+ #endif
    if (term == NULL || *term == '\0')
      term = "none";
  
    while (1)
      {
diff -acrpNC5 fileutils-3.16.orig/src/djstart.c fileutils-3.16.djgpp/src/djstart.c
*** fileutils-3.16.orig/src/djstart.c	Thu Jan  1 00:00:00 1970
--- fileutils-3.16.djgpp/src/djstart.c	Mon May 22 15:13:48 2000
***************
*** 0 ****
--- 1,189 ----
+ /* dj_startup -- Start-up code for GNU Fileutils under MS-DOS/DJGPP
+ 
+    Written by Eli Zaretskii <eliz@is.elta.co.il>
+ 
+    This code may be freely distributed, provided that this
+    copyright notice is left intact.  There is no warranty on
+    this code.
+ 
+    Commentary:
+    ----------
+ 
+    GNU Fileutils deal with files, and are notorious (as most other
+    Unix file-related utilities) for hardcoded assumptions about
+    filenames, especially regarding the slash character and the
+    insistance on knowing the fact that a filename that begins with
+    anything other than a slash is a relative filename (what about
+    DOS d:/file pathnames?).  To make these programs work on MSDOS,
+    it makes sense to convert all the filename arguments to the
+    forward-slash Unix-style notation at start-up.  This would
+    eliminate multiple #ifdef's in the programs' code.  The only
+    thing to take care of is to leave the options alone.
+ 
+    This module is supplied to do this kind of automagic, by using the
+    static constructor hooks provided in DJGPP v2.0 and above.  It
+    should be linked with every program from this package and will be
+    called automatically by the DJGPP start-up code (on crt1.c) just
+    before the `main' function is called.
+ 
+    There are a few other small services that this module does, while
+    at that:
+ 
+    * It sets the default file open mode to BINARY, which is
+      appropriate for file I/O in this package and removes another
+      reason for #ifdef's in the main code;
+ 
+    * It sets the flag bits for the `stat' and `fstat' functions so
+      as to avoid computing fields of `struct stat' that are expensive,
+      unless that program really needs these fields.
+ 
+    WARNING WARNING WARNING!!!
+ 
+    This code relies heavily on the assumption that it will be called
+    for a single command-line only once during the entire life of the
+    program!  Thus all the flag variables are static.
+ 
+    Also note that some of the code below relies on the program name
+    in argv[0] and will break if you rename the program executable file!
+ 
+    You HAVE been warned!
+ 
+    WARNING WARNING WARNING!!!
+ */
+ 
+ #ifdef __DJGPP__
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <io.h>
+ #include <crt0.h>
+ 
+ int _crt0_startup_flags = _CRT0_FLAG_DROP_EXE_SUFFIX;
+ 
+ #ifndef _POSIX_SOURCE
+ /* Let's punish the user as little as we can by requesting
+    the fastest possible version of `stat' for each program.
+    Note that `ls' is not here because it sets the bits at
+    run time, given the options on its command line.  */
+ #define  DEFAULT_STAT_BITS  (_STAT_WRITEBIT   | \
+ 			     _STAT_ROOT_TIME  | \
+ 			     _STAT_DIRSIZE    | \
+ 			     _STAT_EXEC_MAGIC | \
+ 			     _STAT_EXEC_EXT)
+ 
+ static struct {
+   char *name;
+   unsigned short stat_bits;
+ } prog_bits[] = {
+     {"chmod",   ~(_STAT_DIRSIZE | _STAT_EXEC_EXT | _STAT_EXEC_MAGIC)},
+     {"chown",   ~_STAT_DIRSIZE},
+     {"cp",      ~(_STAT_DIRSIZE | _STAT_EXEC_EXT)},
+     {"ln",      ~_STAT_EXEC_EXT},
+     {"mv",	~(_STAT_DIRSIZE | _STAT_EXEC_EXT)},
+     {"rm",	~(_STAT_DIRSIZE | _STAT_EXEC_EXT)},
+     {"touch",	~_STAT_ROOT_TIME}
+ };
+ #endif
+ 
+ static void
+ init_stat_bits (const char *prog_name)
+ {
+ #ifndef _POSIX_SOURCE
+   int i;
+ 
+   _djstat_flags = DEFAULT_STAT_BITS;
+ 
+   for (i = 0; i < sizeof (prog_bits) / sizeof (prog_bits[0]); i++)
+     if (strcasecmp (prog_name, prog_bits[i].name) == 0)
+       {
+ 	_djstat_flags &= prog_bits[i].stat_bits;
+ 	break;
+       }
+ #endif
+ }
+ 
+ static void
+ init_file_io (const char *prog_name)
+ {
+   _fmode = O_BINARY;
+ 
+   /* Only `dd' needs to switch standard streams to binary.  */
+   if (strcasecmp (prog_name, "dd") == 0)
+     {
+       if (!isatty (fileno (stdin)))
+ 	setmode (fileno (stdin), O_BINARY);
+       if (!isatty (fileno (stdout)))
+ 	setmode (fileno (stdout), O_BINARY);
+     }
+ }
+ 
+ static int options_first;       /* options preceed non-options */
+ static int no_more_options = 0; /* did we see all of the options yet? */
+ 
+ extern int    __crt0_argc;	/* defined by the DJGPP startup code */
+ extern char **__crt0_argv;
+ 
+ static void __attribute__((constructor))
+ djgpp_fileutils_startup (void)
+ {
+   char *  argv0base, *dot;
+   char ** arg_walker = __crt0_argv;
+   int     arg_count  = __crt0_argc;
+ 
+   /* Convert all non-option ARGV[] elements to forward slashes.  */
+   if (!options_first)
+     options_first = getenv("POSIXLY_CORRECT") != (char *)0;
+ 
+   while (arg_count--)
+     {
+       char *p = *arg_walker++;
+ 
+       if (no_more_options == 0)
+ 	{
+ 	  if (p[0] == '-')
+ 	    {
+ 	      if (p[1] == '-' && p[2] == '\0')
+ 		no_more_options = 1;
+ 	      continue;
+ 	    }
+ 	  else if (options_first)
+ 	    no_more_options = 1;
+ 	}
+       while (*p)
+ 	{
+ 	  if (*p == '\\')
+ 	    *p = '/';
+ 	  p++;
+ 	}
+     }
+ 
+   /* Find out what's the name of the program.  */
+   argv0base = strrchr (*__crt0_argv, '/');
+   if (!argv0base)
+     argv0base = strrchr (*__crt0_argv, ':');
+   if (argv0base)
+     argv0base++;
+   else
+     argv0base = *__crt0_argv;
+ 
+   /* When we are called by another DJGPP program, the
+      _CRT0_FLAG_DROP_EXE_SUFFIX bit does not always work.  */
+   if ((dot = strchr (argv0base, '.')))
+     *dot = '\0';
+ 
+   init_stat_bits (argv0base);
+   init_file_io (argv0base);
+ }
+ 
+ /* DJGPP doesn't have `lstat', since MS-DOS doesn't
+    support links.  Here's a trivial substitute that will do.  */
+ int lstat (const char *fname, struct stat *st_buf)
+ {
+   return stat (fname, st_buf);
+ }
+ 
+ #endif /* __DJGPP__ */
diff -acrpNC5 fileutils-3.16.orig/src/du.c fileutils-3.16.djgpp/src/du.c
*** fileutils-3.16.orig/src/du.c	Sun Jan 19 03:53:02 1997
--- fileutils-3.16.djgpp/src/du.c	Mon May 22 15:13:48 2000
***************
*** 52,62 ****
  
  #include "system.h"
  #include "save-cwd.h"
  #include "error.h"
  
! #undef	convert_blocks
  #define	convert_blocks(b, size) (size == size_kilobytes ? ((b) + 1) / 2 : \
      size == size_megabytes ? ((b) + 1024) / 2048 : (b))
  
  /* Initial number of entries in each hash table entry's table of inodes.  */
  #define INITIAL_HASH_MODULE 100
--- 52,67 ----
  
  #include "system.h"
  #include "save-cwd.h"
  #include "error.h"
  
! #ifdef MSDOS
! #include <signal.h>
! static struct saved_cwd start_cwd;
! static RETSIGTYPE interrupt_handler ();
! #endif
! 
  #define	convert_blocks(b, size) (size == size_kilobytes ? ((b) + 1) / 2 : \
      size == size_megabytes ? ((b) + 1024) / 2048 : (b))
  
  /* Initial number of entries in each hash table entry's table of inodes.  */
  #define INITIAL_HASH_MODULE 100
*************** du_files (char **files)
*** 430,448 ****
--- 435,472 ----
    if (stat (".", &stat_buf))
      error (1, errno, _("current directory"));
    initial_ino = stat_buf.st_ino;
    initial_dev = stat_buf.st_dev;
  
+ #ifdef MSDOS
+   /* We need to install a signal handler to make sure we return to
+      the original directory even if we are aborted.  */
+   signal (SIGINT, interrupt_handler);
+   save_cwd (&start_cwd);
+ #endif
+ 
    for (i = 0; files[i]; i++)
      {
        char *arg;
        int s;
  
        arg = files[i];
  
        /* Delete final slash in the argument, unless the slash is alone.  */
        s = strlen (arg) - 1;
+ #ifdef MSDOS
+       if (s == 1 && arg[1] == ':')
+ 	{
+ 	  /* Make "d:" explicit so we don't have to handle it specially.  */
+ 	  char full_path[FILENAME_MAX+5];
+ 	  FIXPATH (arg, full_path);
+ 	  str_copyc (path, full_path);
+ 	}
+       else if (s == 2 && arg[2] == '/')
+ 	str_copyc (path, arg);	/* leave alone the slash in "d:/" */
+       else
+ #endif
        if (s != 0)
  	{
  	  if (arg[s] == '/')
  	    arg[s] = 0;
  
*************** du_files (char **files)
*** 476,487 ****
  	  printf("%s\ttotal\n", human_readable (tot_size, buf,
  						LONGEST_HUMAN_READABLE + 1));
  	}
        else
  	{
! 	  printf (_("%ld\ttotal\n"), output_size == size_bytes ? tot_size
! 		  : convert_blocks (tot_size, output_size == size_kilobytes));
  	}
        fflush (stdout);
      }
  
    free_cwd (&cwd);
--- 500,510 ----
  	  printf("%s\ttotal\n", human_readable (tot_size, buf,
  						LONGEST_HUMAN_READABLE + 1));
  	}
        else
  	{
! 	  printf (_("%ld\ttotal\n"), convert_blocks (tot_size, output_size));
  	}
        fflush (stdout);
      }
  
    free_cwd (&cwd);
*************** count_entry (char *ent, int top, dev_t l
*** 534,553 ****
--- 557,609 ----
  	return 0;		/* Don't enter a new file system.  */
  
  #ifndef S_ISDIR
  # define S_ISDIR(s) 0
  #endif
+ 
+ #ifdef MSDOS
+       /* Every drive has its own ``working directory''.  If we're about
+ 	 to change drive, we need to save and restore that directory to
+ 	 prevent side-effects.  To this end, we will first chdir to the
+ 	 working directory on that drive so it is remembered by save_cwd.  */
+       if (ent[1] == ':')
+ 	{
+ 	  char work_dir[4];
+ 
+ 	  work_dir[0] = ent[0];
+ 	  work_dir[1] = ':';
+ 	  work_dir[2] = '.';
+ 	  work_dir[3] = '\0';
+ 	  if (chdir (work_dir) < 0)
+ 	    {
+ 	      error (0, errno, _("cannot change to directory %s"), work_dir);
+ 	      exit_status = 1;
+ 	      return 0;
+ 	    }
+ 
+ 	  /* This will return us to work_dir after every chdir, so the
+ 	     working directory is indeed preserved.  */
+ 	  through_symlink = 1;
+ 	}
+ 
+       if (save_cwd (&cwd))
+ 	exit (1);
+ 
+ #else  /* !MSDOS */
+ 
        /* If we're dereferencing symlinks and we're about to chdir through
  	 a symlink, remember the current directory so we can return to it
  	 later.  In other cases, chdir ("..") works fine.  */
        through_symlink = (xstat == stat
  			 && lstat (ent, &e_buf) == 0
  			 && S_ISLNK (e_buf.st_mode));
        if (through_symlink)
  	if (save_cwd (&cwd))
  	  exit (1);
  
+ #endif /* !MSDOS */
+ 
        if (chdir (ent) < 0)
  	{
  	  error (0, errno, _("cannot change to directory %s"), path->text);
  	  exit_status = 1;
  	  return 0;
*************** count_entry (char *ent, int top, dev_t l
*** 576,585 ****
--- 632,646 ----
  	    error (1, 0, _("virtual memory exhausted"));
  	}
  
        /* Remember the current path.  */
  
+ #ifdef MSDOS
+       /* Avoid adding extra slash in the case of a root directory.  */
+       if (path->text[path->length-2] != ':'
+ 	  || path->text[path->length-1] != '/')
+ #endif
        str_concatc (path, "/");
        pathlen = path->length;
  
        namep = name_space;
        while (*namep != 0)
*************** count_entry (char *ent, int top, dev_t l
*** 599,608 ****
--- 660,673 ----
  	}
        else if (chdir ("..") < 0)
          error (1, errno,
  	       _("cannot change to `..' from directory %s"), path->text);
  
+ #ifdef MSDOS
+       /* Avoid printing excess slash in the case of a root directory.  */
+       if (path->text[pathlen-2] != ':')
+ #endif
        str_trunc (path, pathlen - 1); /* Remove the "/" we added.  */
        if (!opt_summarize_only || top)
  	{
  	  if (opt_human_readable)
  	    {
*************** count_entry (char *ent, int top, dev_t l
*** 611,623 ****
  		     human_readable (size, buf, LONGEST_HUMAN_READABLE + 1),
  		     path->length > 0 ? path->text : "/");
  	    }
  	  else
  	    {
! 	      printf ("%ld\t%s\n", (output_size == size_bytes
! 				    ? size
! 				    : convert_blocks (size, output_size)),
  		      path->length > 0 ? path->text : "/");
  	    }
  	  fflush (stdout);
  	}
        return opt_separate_dirs ? 0 : size;
--- 676,686 ----
  		     human_readable (size, buf, LONGEST_HUMAN_READABLE + 1),
  		     path->length > 0 ? path->text : "/");
  	    }
  	  else
  	    {
! 	      printf ("%ld\t%s\n", convert_blocks (size, output_size),
  		      path->length > 0 ? path->text : "/");
  	    }
  	  fflush (stdout);
  	}
        return opt_separate_dirs ? 0 : size;
*************** count_entry (char *ent, int top, dev_t l
*** 635,646 ****
  		     human_readable (size, buf, LONGEST_HUMAN_READABLE + 1),
  		     path->length > 0 ? path->text : "/");
  	    }
  	  else
  	    {
! 	      printf ("%ld\t%s\n", output_size == size_bytes ? size
! 		      : convert_blocks (size, output_size),
  		      path->text);
  	    }
  	  fflush (stdout);
  	}
      }
--- 698,708 ----
  		     human_readable (size, buf, LONGEST_HUMAN_READABLE + 1),
  		     path->length > 0 ? path->text : "/");
  	    }
  	  else
  	    {
! 	      printf ("%ld\t%s\n", convert_blocks (size, output_size),
  		      path->text);
  	    }
  	  fflush (stdout);
  	}
      }
*************** str_trunc (string s1, unsigned int lengt
*** 852,856 ****
--- 914,927 ----
      {
        s1->text[length] = 0;
        s1->length = length;
      }
  }
+ 
+ #ifdef MSDOS
+ static RETSIGTYPE
+ interrupt_handler (void)
+ {
+   restore_cwd (&start_cwd, _("starting directory"), NULL);
+   exit (1);
+ }
+ #endif
diff -acrpNC5 fileutils-3.16.orig/src/install.c fileutils-3.16.djgpp/src/install.c
*** fileutils-3.16.orig/src/install.c	Wed Dec 11 04:24:44 1996
--- fileutils-3.16.djgpp/src/install.c	Wed May 24 01:15:16 2000
***************
*** 61,70 ****
--- 61,74 ----
  #include <getopt.h>
  #include <sys/types.h>
  #include <pwd.h>
  #include <grp.h>
  
+ #ifdef __DJGPP__
+ # include <process.h>
+ #endif
+ 
  #include "system.h"
  #include "backupfile.h"
  #include "modechange.h"
  #include "makepath.h"
  #include "error.h"
*************** static int
*** 315,324 ****
--- 319,367 ----
  install_file_in_file (char *from, char *to)
  {
    int to_created;
    int no_need_to_chown;
  
+ #ifdef __DJGPP__
+   char *dot = from + strlen (from) - 4;
+   static char STUBIFY[] = "stubify.exe";
+ 
+   /* If FROM is a COFF executable, make a DOS program on the fly.
+      This makes Unix-born Makefiles happy.  */
+   if (!STREQ (dot, ".exe") && !STREQ (dot, ".com"))
+     {
+       char *new_from, *new_to;
+       unsigned short magic;
+       int status, fd = open (from, O_RDONLY | O_BINARY);
+ 
+       if (read (fd, &magic, 2) == 2
+     && (magic == 0x010b || magic == 0x014c || magic == 0x5a4d)
+     && close (fd) == 0)
+   {
+     if (magic == 0x010b || magic == 0x014c)
+       {
+         new_from = alloca (strlen (from) + 1 + 4);
+         stpcpy (stpcpy (new_from, from), ".exe");
+         /* Don't overwrite a stubified .exe if it already exists
+            (it may have been stubedited to change default stub info).  */
+         if (!__file_exists (new_from))
+         {
+           status = spawnlp (P_WAIT, STUBIFY, STUBIFY, from, (char *) NULL);
+           if (status == -1)
+             error (1, errno, _("cannot run stubify"));
+         }
+         from = new_from;
+       }
+     new_to = alloca (strlen (to) + 1 + 4);
+     stpcpy (stpcpy (new_to, to), ".exe");
+     to = new_to;
+   }
+       else if (fd != -1)
+     close (fd);
+     }
+ #endif
+ 
    if (copy_file (from, to, &to_created))
      return 1;
    if (strip_files)
      strip (to);
    no_need_to_chown = (to_created
*************** install_file_in_dir (char *from, char *t
*** 338,347 ****
--- 381,396 ----
    char *to;
    int ret;
  
    from_base = basename (from);
    to = xmalloc ((unsigned) (strlen (to_dir) + strlen (from_base) + 2));
+ #ifdef MSDOS
+   /* If we get "d:" in FROM, make "d:to_dir", not "d:/to_dir".  */
+   if (strlen (to_dir) == 2 && to_dir[1] == ':')
+     stpcpy (stpcpy (to, to_dir), from_base);
+   else
+ #endif
    stpcpy (stpcpy (stpcpy (to, to_dir), "/"), from_base);
    ret = install_file_in_file (from, to);
    free (to);
    return ret;
  }
*************** change_attributes (char *path, int no_ne
*** 512,521 ****
--- 561,572 ----
     We could dig the magic number out of the file first to
     determine whether to strip it, but the header files and
     magic numbers vary so much from system to system that making
     it portable would be very difficult.  Not worth the effort. */
  
+ #ifndef MSDOS
+ 
  static void
  strip (char *path)
  {
    int pid, status;
  
*************** strip (char *path)
*** 535,544 ****
--- 586,619 ----
  	/* Do nothing. */ ;
        break;
      }
  }
  
+ #else  /* MSDOS */
+ #ifdef __DJGPP__
+ 
+ static char STRIP[]   = "strip.exe";
+ 
+ static void
+ strip (char *path)
+ {
+   int status = spawnlp (P_WAIT, STRIP, STRIP, path, (char *) NULL);
+ 
+   if (status == -1)
+     error (1, errno, _("cannot run strip"));
+ }
+ 
+ #else  /* not __DJGPP__ */
+ 
+ static void
+ strip (char *path)
+ {
+ }
+ 
+ #endif /* __DJGPP__ */
+ #endif /* MSDOS */
+ 
  /* Initialize the user and group ownership of the files to install. */
  
  static void
  get_ids (void)
  {
*************** get_ids (void)
*** 551,561 ****
--- 626,641 ----
        if (pw == NULL)
  	{
  	  long int tmp_long;
  	  if (xstrtol (owner_name, NULL, 0, &tmp_long, NULL) != LONGINT_OK
  	      || tmp_long < 0 || tmp_long > UID_T_MAX)
+ #ifdef  MSDOS
+             /* Under MS-DOS, allow any owner name, since it's meaningless. */
+             owner_id = 2*getuid ();  /* Why twice, you ask?  Why not?? */
+ #else
  	    error (1, 0, _("invalid user `%s'"), owner_name);
+ #endif
  	  owner_id = (uid_t) tmp_long;
  	}
        else
  	owner_id = pw->pw_uid;
        endpwent ();
*************** get_ids (void)
*** 569,579 ****
--- 649,664 ----
        if (gr == NULL)
  	{
  	  long int tmp_long;
  	  if (xstrtol (group_name, NULL, 0, &tmp_long, NULL) != LONGINT_OK
  	      || tmp_long < 0 || tmp_long > (long) GID_T_MAX)
+ #ifdef  MSDOS
+             /* Under MS-DOS, allow any group name. */
+             group_id = 2*getgid ();
+ #else
  	    error (1, 0, _("invalid group `%s'"), group_name);
+ #endif
  	  group_id = (gid_t) tmp_long;
  	}
        else
  	group_id = gr->gr_gid;
        endgrent ();
diff -acrpNC5 fileutils-3.16.orig/src/ln.c fileutils-3.16.djgpp/src/ln.c
*** fileutils-3.16.orig/src/ln.c	Sat Nov 23 22:11:10 1996
--- fileutils-3.16.djgpp/src/ln.c	Mon May 22 15:13:48 2000
***************
*** 28,37 ****
--- 28,47 ----
  
  #include "system.h"
  #include "backupfile.h"
  #include "error.h"
  
+ #ifdef  __DJGPP__
+ /* DJGPP doesn't have S_ISLNK defined, because MS-DOS doesn't support links.
+    However, DJGPP's `link' simulates hard links by copying, and we can
+    have ``symbolic links'' for DJGPP .EXE programs.  Therefore, just
+    for the purpose of this program, it makes sense to define S_ISLNK
+    so we could have working `ln'.  */
+ 
+ #define S_ISLNK(x)  (0)     /* defined, but no file is a link */
+ #endif
+ 
  int link ();			/* Some systems don't declare this anywhere. */
  
  #ifdef S_ISLNK
  int symlink ();
  #endif
diff -acrpNC5 fileutils-3.16.orig/src/ls-msdos.c fileutils-3.16.djgpp/src/ls-msdos.c
*** fileutils-3.16.orig/src/ls-msdos.c	Thu Jan  1 00:00:00 1970
--- fileutils-3.16.djgpp/src/ls-msdos.c	Mon May 22 15:13:48 2000
***************
*** 0 ****
--- 1,334 ----
+ /* MSDOS-specific functions for `ls'.
+ 
+    Written by Eli Zaretskii <eliz@is.elta.co.il>  */
+ 
+ #ifdef MSDOS
+ 
+ #include <string.h>
+ 
+ /*  dos_mode_string -- convert MS-DOS file attribute bits into a character
+     string.  The characters stored in STR are:
+ 
+     0   'r'  if file is read-only, '-' otherwise.
+     1   'h'  if file is hidden, '-' otherwise.
+     2   's'  if file has its system bit set, '-' otherwise.
+     3   'v'  if file is a volume label, '-' otherwise.
+     4   'd'  if file is a directory, '-' otherwise.
+     5   'm'  if file was modified since last backup, '-' otherwise.
+     
+     For instance, for a write-protected, hidden file the function
+     will return a string "rh----".  */
+ 
+ void
+ dos_mode_string (bits, str)
+     int bits;
+     char *str;
+ {
+   unsigned mask = 1 << 5;
+   
+   strcpy(str, "rhsvdm");          /* assume all bits set */
+   for (str += 5; mask; mask >>= 1, --str)
+     if ((bits & mask) == 0)
+       *str = '-';                 /* put hyphen instead of unused bit */
+ }
+ 
+ #ifdef __DJGPP__
+ 
+ /* What follows won't work with anything but DJGPP.  */
+ 
+ #include <sys/stat.h>
+ #include <dirent.h>
+ 
+ static int colorization_required;
+ 
+ /* Ls is a heavy user of `stat' whose full emulation on MS-DOS is
+    sometimes very expensive.  Let's punish the user as little as we
+    can by requesting the fastest possible version of `stat'.
+ 
+    The default bits, suitable for just displaying the names of the files
+    are defined on `djstart.c'; below are the bits required by various
+    Ls options. */
+ void set_stat_bits_for_ls (int need_time, int need_size,
+ 			   int need_long_format, int msdos_long_format,
+ 			   int indicate_type, int use_color, int show_hidden)
+ {
+ #ifndef _POSIX_SOURCE
+   if (need_time)
+     _djstat_flags &= ~_STAT_ROOT_TIME;
+   if (need_size)
+     _djstat_flags &= ~_STAT_DIRSIZE;
+   if (need_long_format)
+     {
+       _djstat_flags &= ~(_STAT_ROOT_TIME
+ 			 | _STAT_DIRSIZE);
+       if (msdos_long_format)
+ 	_djstat_flags &= ~_STAT_EXEC_EXT;
+       else
+ 	_djstat_flags &= ~(_STAT_EXEC_MAGIC
+ 			   | _STAT_EXEC_EXT);
+     }
+   if (indicate_type)
+     _djstat_flags &= ~(_STAT_EXEC_EXT
+ 		       | _STAT_EXEC_MAGIC);
+   if (use_color)
+     _djstat_flags &= ~_STAT_EXEC_EXT;
+ 
+   /* Find hidden files only if user specified -a.  */
+   if (show_hidden)
+     {
+       __opendir_flags |= __OPENDIR_FIND_HIDDEN;
+       /* Find volume labels only if user specified both -a and -g.  */
+       if (msdos_long_format)
+ 	__opendir_flags |= __OPENDIR_FIND_LABEL;
+     }
+ 
+ #endif /* _POSIX_SOURCE */
+ 
+   /* Our screen redirector (below) wants to know if
+      colorization was actually required.  */
+   if (use_color)
+     colorization_required = 1;
+   else
+     colorization_required = 0;
+ }
+ 
+ /*  Screen write redirector.  We need this to support colorization
+     without requiring ANSI.SYS driver (or its work-alike) to be loaded.
+ 
+     This function uses the DJGPP filesystem extensions mechanism.  It is
+     installed as a handler for handle-based functions (read/write/close)
+     for the standard output (but actually only handles writes, only if
+     the standard output is connected to the terminal, and only if user
+     asked for colorization).  When a buffer is written to the screen by
+     low-level functions of the DJGPP C library, our handler will be
+     called.  For any request that doesn't require colored screen writes
+     we return a zero to the caller, in which case the caller will handle
+     the output in the usual way (by eventually calling DOS).
+ 
+     When colorization *is* required, the buffer is written directly to
+     the screen while converting the ANSI escape sequences into calls to
+     DJGPP conio functions which change text attributes.  A non-zero value is
+     then returned to the caller to signal that the output has been handled.
+ 
+     Warning: this function relies on the fact that `ls' disables the use
+     of TAB characters when colorization is required, and therefore it
+     does NOT expand TABs!  It also doesn't check for NULL characters in
+     the buffer, and might end the output prematurely if there are NULLs.  */
+ 
+ #include <stdio.h>
+ #include <stdarg.h>
+ #include <errno.h>
+ #include <unistd.h>
+ #include <conio.h>
+ #include <sys/fsext.h>
+ #include <go32.h>	/* for `_dos_ds' */
+ #include <sys/farptr.h>
+ 
+ static int norm_blink = -1, cur_blink = -1;
+ static unsigned char norm_attr = 0, cur_attr = 0;
+ static int isatty_stdout = -1;
+ 
+ /* Restore the BIOS blinking bit to its original value.  Called at exit.  */
+ static void
+ restore_blink_bit (void)
+ {
+   if (cur_blink != norm_blink)
+     {
+       if (norm_blink > 0)
+ 	blinkvideo ();
+       else
+ 	intensevideo ();
+     }
+ }
+ 
+ #define ESC '\033'
+ 
+ static int
+ msdos_screen_write (__FSEXT_Fnumber func, int *retval, va_list rest_args)
+ {
+   static char *cbuf = 0;
+   static size_t cbuf_len = 0;
+   /* Only dark colors mentioned here, so that bold has visible effect.  */
+   static enum COLORS screen_color[] = {BLACK, RED, GREEN, BROWN,
+ 				       BLUE, MAGENTA, CYAN, LIGHTGRAY};
+   char *anchor, *p_next;
+   unsigned char fg, bg;
+ 
+   int handle;
+   char *buf;
+   size_t buflen;
+ 
+   /* Avoid direct screen writes unless colorization was actually requested.
+      Otherwise, we will break programs that catch I/O from their children.  */
+   handle = va_arg (rest_args, int);
+   if (!colorization_required || func != __FSEXT_write
+       || !(handle == STDOUT_FILENO ? isatty_stdout : isatty (handle)))
+     return 0;
+ 
+   buf = va_arg (rest_args, char *);
+   if (!buf)
+     {
+       errno = EINVAL;
+       *retval = -1;
+       return 1;
+     }
+ 
+   /* Allocate a sufficiently large buffer to hold the output.  */
+   buflen = va_arg (rest_args, size_t);
+   if (!cbuf)
+     {
+       struct text_info txtinfo;
+ 
+       cbuf_len = buflen + 1;
+       cbuf = (char *)xmalloc (cbuf_len);
+       gettextinfo (&txtinfo);
+       norm_attr = txtinfo.attribute; /* save the original text attribute */
+       cur_attr = norm_attr;
+       /* Does it normally blink when bg has its 3rd bit set?  */
+       norm_blink = (_farpeekb (_dos_ds, 0x465) & 0x20) ? 1 : 0;
+       cur_blink = norm_blink;
+     }
+   else if (buflen >= cbuf_len)
+     {
+       cbuf_len = buflen + 1;
+       cbuf = (char *)xrealloc (cbuf, cbuf_len);
+     }
+   memcpy (cbuf, buf, buflen);
+   cbuf[buflen] = '\0';
+ 
+   /* Current text attributes are used as baseline.  */
+   fg = cur_attr & 15;
+   bg = (cur_attr >> 4) & 15;
+ 
+   /* Walk the buffer, writing text directly to video RAM,
+      changing color attributes when an escape sequence is seen.  */
+   for (anchor = p_next = cbuf;
+        (p_next = memchr (p_next, ESC, buflen - (p_next - cbuf))) != 0; )
+     {
+       char *p = p_next;
+ 
+       if (p[1] == '[')	/* "Esc-[" sequence */
+ 	{
+ 	  /* If some chars seen since the last escape sequence,
+ 	     write it out to the screen using current text attributes.  */
+ 	  if (p > anchor)
+ 	    {
+ 	      *p = '\0';	/* `cputs' needs ASCIIZ string */
+ 	      cputs (anchor);
+ 	      *p = ESC;		/* restore the ESC character */
+ 	      anchor = p;
+ 	    }
+ 	  p += 2;		/* get past "Esc-[" sequence */
+ 	  p_next = p;
+ 	  while (*p != 'm')	/* `m' ends the escape sequence */
+ 	    {
+ 	      char *q;
+ 	      long code = strtol (p, &q, 10);
+ 
+ 	      /* Sanity checks:
+ 
+ 		   q > p unless p doesn't point to a number;
+ 		   ANSI codes are between 0 and 47;
+ 		   Each ANSI code ends with a `;' or an `m'.
+ 
+ 		 If any of the above is violated, we just ignore the bogon. */
+ 	      if (q == p || code > 47 || code < 0 || (*q != 'm' && *q != ';'))
+ 		{
+ 		  p_next = q;
+ 		  break;
+ 		}
+ 	      if (*q == ';')	/* more codes to follow */
+ 		q++;
+ 
+ 	      /* Convert ANSI codes to color fore- and background.  */
+ 	      switch (code)
+ 		{
+ 		  case 0:	/* all attributes off */
+ 		    fg = norm_attr & 15;
+ 		    bg = (norm_attr >> 4) & 15;
+ 		    break;
+ 		  case 1:	/* intensity on */
+ 		    fg |= 8;
+ 		    break;
+ 		  case 4:	/* underline on */
+ 		    fg |= 8;	/* we can't, so make it bold instead */
+ 		    break;
+ 		  case 5:	/* blink */
+ 		    if (cur_blink != 1)
+ 		      {
+ 			blinkvideo (); /* ensure we are'nt in bright bg mode */
+ 			cur_blink = 1;
+ 		      }
+ 		    bg |= 8;
+ 		    break;
+ 		  case 7:	/* reverse video */
+ 		    {
+ 		      unsigned char t = fg;
+ 		      fg = bg;
+ 		      bg = t;
+ 
+ 		      /* If it was blinking before, let it blink after.  */
+ 		      if (fg & 8)
+ 			bg |= 8;
+ 
+ 		      /* If the fg was bold, let the background be bold.  */
+ 		      if ((t & 8) && cur_blink != 0)
+ 			{
+ 			  intensevideo ();
+ 			  cur_blink = 0;
+ 			}
+ 		    }
+ 		    break;
+ 		  case 8:	/* concealed on */ 
+ 		    fg = (bg & 7) | 8;	/* make fg be like bg, only bright */
+ 		    break;
+ 		  case 30: case 31: case 32: case 33: /* foreground color */
+ 		  case 34: case 35: case 36: case 37:
+ 		    fg = (fg & 8) | (screen_color[code - 30] & 15);
+ 		    break;
+ 		  case 40: case 41: case 42: case 43: /* background color */
+ 		  case 44: case 45: case 46: case 47:
+ 		    bg = (bg & 8) | (screen_color[code - 40] & 15);
+ 		    break;
+ 		  default:
+ 		    p_next = q;	/* ignore unknown codes */
+ 		    break;
+ 		}
+ 	      p = q;
+ 	    }
+ 	  if (*p == 'm' && p > p_next)
+ 	    {
+ 	      /* They don't *really* want it invisible, do they?  */
+ 	      if (fg == (bg & 7))
+ 		fg |= 8;	/* make it concealed instead */
+ 
+ 	      /* Construct the text attribute and set it.  */
+ 	      cur_attr = (bg << 4) | fg;
+ 	      textattr (cur_attr);
+ 	      p_next = anchor = p + 1;
+ 	    }
+ 	  else
+ 	    break;
+ 	}
+       else
+ 	p_next++;
+     }
+ 
+   /* Output what's left in the buffer.  */
+   cputs (anchor);
+   *retval = buflen;
+   return 1;
+ }
+ 
+ /* This is called before `main' to install our STDOUT redirector.  */
+ 
+ static void __attribute__((constructor))
+ djgpp_ls_startup (void)
+ {
+   __FSEXT_set_function (STDOUT_FILENO, msdos_screen_write);
+   isatty_stdout = isatty (STDOUT_FILENO);
+   atexit (restore_blink_bit);
+ }
+ 
+ #endif  /* __DJGPP__ */
+ #endif  /* MSDOS */
diff -acrpNC5 fileutils-3.16.orig/src/ls.c fileutils-3.16.djgpp/src/ls.c
*** fileutils-3.16.orig/src/ls.c	Sun Jan 26 05:56:10 1997
--- fileutils-3.16.djgpp/src/ls.c	Mon May 22 15:13:48 2000
***************
*** 45,54 ****
--- 45,57 ----
  
  #include <termios.h>
  #ifdef GWINSZ_IN_SYS_IOCTL
  # include <sys/ioctl.h>
  #endif
+ #ifdef __DJGPP__
+ # include <pc.h>
+ #endif
  
  #include <stdio.h>
  #include <grp.h>
  #include <pwd.h>
  #include <getopt.h>
***************
*** 81,90 ****
--- 84,97 ----
  # define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b) ? 1 : 0)
  #else
  # define longdiff(a, b) ((a) - (b))
  #endif
  
+ /* Convert B 512-byte blocks to kilobytes if K is nonzero,
+    otherwise return it unchanged. */
+ #define convert_blocks(b, k) ((k) ? ((b) + 1) / 2 : (b))
+ 
  /* The maximum number of digits required to print an inode number
     in an unsigned format.  */
  #ifndef INODE_DIGITS
  # define INODE_DIGITS 7
  #endif
*************** struct fileinfo
*** 114,123 ****
--- 121,134 ----
      /* For symbolic link and color printing, 1 if linked-to file
         exists, otherwise 0.  */
      int linkok;
  
      enum filetype filetype;
+ #ifdef  MSDOS
+     /* On MS-DOS we also get DOS-specific file attribute bits. */
+     int msdos_attribs;
+ #endif
    };
  
  #define LEN_STR_PAIR(s) sizeof (s) - 1, s
  
  /* Null is a valid character in a color indicator (think about Epson
*************** char *getgroup ();
*** 143,152 ****
--- 154,168 ----
  char *getuser ();
  char *xmalloc ();
  char *xrealloc ();
  void invalid_arg ();
  
+ #ifdef  MSDOS
+ void dos_mode_string __P ((int, char *));
+ #endif
+ 
+ 
  static char *make_link_path __P ((const char *path, const char *linkname));
  static int compare_atime __P ((const struct fileinfo *file1,
  			       const struct fileinfo *file2));
  static int rev_cmp_atime __P ((const struct fileinfo *file2,
  			       const struct fileinfo *file1));
*************** enum color_type
*** 358,373 ****
  
  enum indicator_no
    {
      C_LEFT, C_RIGHT, C_END, C_NORM, C_FILE, C_DIR, C_LINK, C_FIFO, C_SOCK,
      C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC
    };
  
  static const char *const indicator_name[]=
    {
      "lc", "rc", "ec", "no", "fi", "di", "ln", "pi", "so",
!     "bd", "cd", "mi", "or", "ex", NULL
    };
  
  struct col_ext_type
    {
      struct bin_str ext;		/* The extension we're looking for */
--- 374,396 ----
  
  enum indicator_no
    {
      C_LEFT, C_RIGHT, C_END, C_NORM, C_FILE, C_DIR, C_LINK, C_FIFO, C_SOCK,
      C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC
+ #ifdef MSDOS
+     , C_LABEL			/* MSDOS volume label */
+ #endif
    };
  
  static const char *const indicator_name[]=
    {
      "lc", "rc", "ec", "no", "fi", "di", "ln", "pi", "so",
!     "bd", "cd", "mi", "or", "ex"
! #ifdef MSDOS
!     , "lb"			/* MSDOS volume label */
! #endif
!     , NULL
    };
  
  struct col_ext_type
    {
      struct bin_str ext;		/* The extension we're looking for */
*************** static struct bin_str color_indicator[] 
*** 389,398 ****
--- 412,424 ----
      { LEN_STR_PAIR ("01;33") },		/* bd: Block device: bright yellow */
      { LEN_STR_PAIR ("01;33") },		/* cd: Char device: bright yellow */
      { 0, NULL },			/* mi: Missing file: undefined */
      { 0, NULL },			/* or: Orphanned symlink: undefined */
      { LEN_STR_PAIR ("01;32") }		/* ex: Executable: bright green */
+ #ifdef MSDOS
+     , { LEN_STR_PAIR ("37;07") }	/* lb: Volume Label: black on white */
+ #endif
    };
  
  /* FIXME: comment  */
  struct col_ext_type *col_ext_list = NULL;
  
*************** static int exit_status;
*** 488,497 ****
--- 514,529 ----
  static int show_help;
  
  /* If nonzero, print the version on standard output and exit.  */
  static int show_version;
  
+ #ifdef  MSDOS
+ /* If non-zero, use DOS-style permission mode, and don't show UID and GID
+    in long format. */
+ static int msdos_long_format;
+ #endif
+ 
  static struct option const long_options[] =
  {
    {"all", no_argument, 0, 'a'},
    {"escape", no_argument, 0, 'b'},
    {"directory", no_argument, 0, 'd'},
*************** static struct option const long_options[
*** 516,525 ****
--- 548,560 ----
    {"recursive", no_argument, 0, 'R'},
    {"format", required_argument, 0, 12},
    {"sort", required_argument, 0, 10},
    {"tabsize", required_argument, 0, 'T'},
    {"time", required_argument, 0, 11},
+ #ifdef MSDOS
+   {"msdos-long-format", no_argument, 0, 'g'},
+ #endif
    {"help", no_argument, &show_help, 1},
    {"version", no_argument, &show_version, 1},
    {"color", optional_argument, 0, 13},
    {NULL, 0, NULL, 0}
  };
*************** main (int argc, char **argv)
*** 681,690 ****
--- 716,737 ----
    format_needs_stat = sort_type == sort_time || sort_type == sort_size
      || format == long_format
      || trace_links || trace_dirs || indicator_style != none
      || print_block_size || print_inode || print_with_color;
  
+ #if defined(__DJGPP__) && !defined(_POSIX_SOURCE)
+   /* Some members of `struct stat' are very expensive to compute on
+      MSDOS.  This requests the fastest `stat' operation for given
+      combination of options; see `ls-msdos.c'.    */
+   if (format_needs_stat)
+     set_stat_bits_for_ls (sort_type == sort_time,
+ 			  sort_type == sort_size || print_block_size,
+ 			  format == long_format, msdos_long_format,
+ 			  indicator_style == all, print_with_color,
+ 			  all_files);
+ #endif  /* __DJGPP__ && !_POSIX_SOURCE */
+ 
    if (dired && format == long_format)
      {
        obstack_init (&dired_obstack);
        obstack_init (&subdired_obstack);
      }
*************** decode_switches (int argc, char **argv)
*** 844,853 ****
--- 891,904 ----
      if (ioctl (1, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
        line_length = ws.ws_col;
    }
  #endif
  
+ #ifdef __DJGPP__
+   line_length = ScreenCols ();
+ #endif
+ 
    /* Using the TABSIZE environment variable is not POSIX-approved.
       Ignore it when POSIXLY_CORRECT is set.  */
    tabsize = 8;
    if (!getenv ("POSIXLY_CORRECT") && (p = getenv ("TABSIZE")))
      {
*************** decode_switches (int argc, char **argv)
*** 903,912 ****
--- 954,966 ----
  	  print_block_size = 0;	/* disable -s */
  	  print_with_color = 0;	/* disable --color */
  	  break;
  
  	case 'g':
+ #ifdef  MSDOS
+           msdos_long_format = 1;
+ #endif
  	  /* No effect.  For BSD compatibility. */
  	  break;
  
  	case 'i':
  	  print_inode = 1;
*************** parse_ls_color (void)
*** 1324,1335 ****
    int ind_no;			/* Indicator number */
    char label[3];		/* Indicator label */
    struct col_ext_type *ext;	/* Extension we are working on */
    struct col_ext_type *ext2;	/* Extra pointer */
  
!   if ((p = getenv ("LS_COLORS")) == NULL || *p == '\0')
      return;
  
    ext = NULL;
    strcpy (label, "??");
  
    /* This is an overly conservative estimate, but any possible
--- 1378,1394 ----
    int ind_no;			/* Indicator number */
    char label[3];		/* Indicator label */
    struct col_ext_type *ext;	/* Extension we are working on */
    struct col_ext_type *ext2;	/* Extra pointer */
  
!   if ((p = getenv ("LS_COLORS")) == NULL)
      return;
+   if (*p == '\0')
+     {
+       print_with_color = 0;
+       return;
+     }
  
    ext = NULL;
    strcpy (label, "??");
  
    /* This is an overly conservative estimate, but any possible
*************** gobble_file (const char *name, int expli
*** 1611,1620 ****
--- 1670,1686 ----
  
    if (explicit_arg || format_needs_stat)
      {
        /* `path' is the absolute pathname of this file. */
  
+ #ifdef MSDOS
+       /* Any filename with a drive specification should be
+ 	 treated as an absolute pathname on MS-DOS.  */
+       if (name[1] == ':')
+ 	path = (char *)name;
+       else
+ #endif
        if (name[0] == '/' || dirname[0] == 0)
  	path = (char *) name;
        else
  	{
  	  path = (char *) alloca (strlen (name) + strlen (dirname) + 2);
*************** gobble_file (const char *name, int expli
*** 1636,1645 ****
--- 1702,1732 ----
  	  error (0, errno, "%s", path);
  	  exit_status = 1;
  	  return 0;
  	}
  
+ #ifdef MSDOS
+       /* Get the MS-DOS attribute bits if they requested them.  */
+       if (msdos_long_format && format == long_format)
+ 	{
+ 	  if (S_ISCHR (files[files_index].stat.st_mode))
+ 	    files[files_index].msdos_attribs = 0x20; /* Modified only */
+ 	  else if (S_ISLABEL (files[files_index].stat.st_mode))
+ 	    /* Argh!  `_chmod' fails for volume labels!!  */
+ 	    files[files_index].msdos_attribs = 0x28;
+ 	  else
+ 	    {
+ 	      char fullpath[PATH_MAX];
+ 
+ 	      FIXPATH (path, fullpath);
+ 	      files[files_index].msdos_attribs = _chmod (fullpath, 0, 0);
+ 	      if (files[files_index].msdos_attribs == -1)
+ 		files[files_index].msdos_attribs = 0x20;
+ 	    }
+ 	}
+ #endif /* MSDOS */
+ 
  #ifdef S_ISLNK
        if (S_ISLNK (files[files_index].stat.st_mode)
  	  && (explicit_arg || format == long_format || print_with_color))
  	{
  	  char *linkpath;
*************** extract_dirs_from_files (const char *dir
*** 1798,1807 ****
--- 1885,1900 ----
       order.  */
    for (i = files_index - 1; i >= 0; i--)
      if ((files[i].filetype == directory || files[i].filetype == arg_directory)
  	&& (!recursive || is_not_dot_or_dotdot (files[i].name)))
        {
+ #ifdef MSDOS
+ 	/* DOS-specific case of absolute pathnames.  */
+ 	if (files[i].name[1] == ':')
+ 	  queue_directory (files[i].name, files[i].linkname);
+ 	else
+ #endif
  	if (files[i].name[0] == '/' || dirname[0] == 0)
  	  {
  	    queue_directory (files[i].name, files[i].linkname);
  	  }
  	else
*************** static int
*** 1831,1840 ****
--- 1924,1938 ----
  is_not_dot_or_dotdot (const char *name)
  {
    char *t;
  
    t = strrchr (name, '/');
+ #ifdef MSDOS
+   /* We can have "d:." or "d:.."  */
+   if (!t && name[1] == ':')
+     t = (char *)(name + 1);
+ #endif
    if (t)
      name = t + 1;
  
    if (name[0] == '.'
        && (name[1] == '\0'
*************** print_long_format (const struct fileinfo
*** 2047,2056 ****
--- 2145,2159 ----
    size_t s;
    char *p;
    time_t when;
    const char *fmt;
  
+ #ifdef MSDOS
+   if (msdos_long_format)
+     dos_mode_string (f->msdos_attribs, modebuf);
+   else
+ #endif  /* MSDOS */
  #ifdef HAVE_ST_DM_MODE
    mode_string (f->stat.st_dm_mode, modebuf);
  #else
    mode_string (f->stat.st_mode, modebuf);
  #endif
*************** print_long_format (const struct fileinfo
*** 2107,2121 ****
--- 2210,2233 ----
  	       (unsigned) convert_blocks (ST_NBLOCKS (f->stat),
  					  kilobyte_blocks));
        p += strlen (p);
      }
  
+ #ifdef MSDOS
+   if (msdos_long_format)
+     sprintf (p, "%s  ", modebuf);
+   else
+ #endif
    /* The space between the mode and the number of links is the POSIX
       "optional alternate access method flag". */
    sprintf (p, "%s %3u ", modebuf, (unsigned int) f->stat.st_nlink);
    p += strlen (p);
  
+ #ifdef MSDOS
+   if (!msdos_long_format)
+     {
+ #endif
    if (numeric_users)
      sprintf (p, "%-8u ", (unsigned int) f->stat.st_uid);
    else
      sprintf (p, "%-8.8s ", getuser (f->stat.st_uid));
    p += strlen (p);
*************** print_long_format (const struct fileinfo
*** 2126,2135 ****
--- 2238,2250 ----
  	sprintf (p, "%-8u ", (unsigned int) f->stat.st_gid);
        else
  	sprintf (p, "%-8.8s ", getgroup (f->stat.st_gid));
        p += strlen (p);
      }
+ #ifdef MSDOS
+     }
+ #endif
  
    if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))
      sprintf (p, "%3u, %3u ", (unsigned) major (f->stat.st_rdev),
  	     (unsigned) minor (f->stat.st_rdev));
    else
*************** print_long_format (const struct fileinfo
*** 2137,2147 ****
    p += strlen (p);
  
    /* Use strftime rather than ctime, because the former can produce
       locale-dependent names for the weekday (%a) and month (%b).  */
  
!   while (! (s = strftime (p, buf + bufsize - p, fmt, localtime (&when))))
      {
        char *newbuf = (char *) alloca (bufsize *= 2);
        memcpy (newbuf, buf, p - buf);
        p = newbuf + (p - buf);
        buf = newbuf;
--- 2252,2262 ----
    p += strlen (p);
  
    /* Use strftime rather than ctime, because the former can produce
       locale-dependent names for the weekday (%a) and month (%b).  */
  
!   while (! (s = strftime (p, buf + bufsize - p - 1, fmt, localtime (&when))))
      {
        char *newbuf = (char *) alloca (bufsize *= 2);
        memcpy (newbuf, buf, p - buf);
        p = newbuf + (p - buf);
        buf = newbuf;
*************** quote_filename (register const char *p, 
*** 2203,2213 ****
  	    case '\b':
  	    case '\r':
  	    case '\t':
  	    case '\f':
  	    case ' ':
- 	    case '"':
  	      found_quotable = 1;
  	      break;
  
  	    default:
  	      if (!ISGRAPH (c))
--- 2318,2327 ----
*************** quote_filename (register const char *p, 
*** 2229,2239 ****
        *quoted_length = p - p0;
        return NULL;
      }
  
    p = p0;
!   quoted = xmalloc (4 * strlen (p) + 1);
    q = quoted;
  
  #define SAVECHAR(c) *q++ = (c)
  #define SAVE_2_CHARS(c12) \
      do { *q++ = ((c12)[0]); \
--- 2343,2353 ----
        *quoted_length = p - p0;
        return NULL;
      }
  
    p = p0;
!   quoted = xmalloc (4 * strlen (p) + 3);
    q = quoted;
  
  #define SAVECHAR(c) *q++ = (c)
  #define SAVE_2_CHARS(c12) \
      do { *q++ = ((c12)[0]); \
*************** print_type_indicator (unsigned int mode)
*** 2383,2392 ****
--- 2497,2513 ----
  #ifdef S_ISSOCK
    if (S_ISSOCK (mode))
      PUTCHAR ('=');
  #endif
  
+ #ifdef MSDOS
+ #ifdef S_ISLABEL     /* MS-DOS Volume label */
+   if (S_ISLABEL (mode))
+     PUTCHAR ('+');
+ #endif
+ #endif
+ 
    if (S_ISREG (mode) && indicator_style == all
        && (mode & S_IXUGO))
      PUTCHAR ('*');
  }
  
*************** print_color_indicator (const char *name,
*** 2433,2442 ****
--- 2554,2569 ----
  #ifdef S_ISCHR
        else if (S_ISCHR (mode))
  	type = C_CHR;
  #endif
  
+ #ifdef MSDOS
+ #ifdef S_ISLABEL     /* MS-DOS Volume label */
+ 	  else if (S_ISLABEL (mode))
+ 	    type = C_LABEL;
+ #endif
+ #endif
        if (type == C_FILE && (mode & S_IXUGO) != 0)
  	type = C_EXEC;
  
        /* Check the file's suffix only if still classified as C_FILE.  */
        ext = NULL;
*************** print_color_indicator (const char *name,
*** 2447,2458 ****
  	  len = strlen (name);
  	  name += len;		/* Pointer to final \0.  */
  	  for (ext = col_ext_list; ext != NULL; ext = ext->next)
  	    {
  	      if (ext->ext.len <= len
! 		  && strncmp (name - ext->ext.len, ext->ext.string,
! 			      ext->ext.len) == 0)
  		break;
  	    }
  	}
      }
  
--- 2574,2590 ----
  	  len = strlen (name);
  	  name += len;		/* Pointer to final \0.  */
  	  for (ext = col_ext_list; ext != NULL; ext = ext->next)
  	    {
  	      if (ext->ext.len <= len
! #ifdef MSDOS
! 	    /* Don't let the letter case affect the colorization on MSDOS.  */
! 	    && strncasecmp (name - ext->ext.len, ext->ext.string,
! #else
! 	    && strncmp (name - ext->ext.len, ext->ext.string,
! #endif
! 			ext->ext.len) == 0)
  		break;
  	    }
  	}
      }
  
*************** length_of_file_name_and_frills (const st
*** 2542,2551 ****
--- 2674,2688 ----
  	       || S_ISFIFO (filetype)
  #endif
  #ifdef S_ISSOCK
  	       || S_ISSOCK (filetype)
  #endif
+ #ifdef MSDOS
+ #ifdef S_ISLABEL
+ 	       || S_ISLABEL (filetype)
+ #endif
+ #endif
  	)
  	len += 1;
      }
  
    return len;
*************** attach (char *dest, const char *dirname,
*** 2719,2728 ****
--- 2856,2870 ----
    /* Copy dirname if it is not ".". */
    if (dirname[0] != '.' || dirname[1] != 0)
      {
        while (*dirnamep)
  	*dest++ = *dirnamep++;
+ #ifdef  MSDOS
+       /* "d:" does NOT mean "d:/"  */
+       if (dirnamep <= dirname + 1
+ 	  || dirname[1] != ':' || dirname[2] != '\0')
+ #endif
        /* Add '/' if `dirname' doesn't already end with it. */
        if (dirnamep > dirname && dirnamep[-1] != '/')
  	*dest++ = '/';
      }
    while (*name)
diff -acrpNC5 fileutils-3.16.orig/src/mv.c fileutils-3.16.djgpp/src/mv.c
*** fileutils-3.16.orig/src/mv.c	Sat Nov 23 22:11:12 1996
--- fileutils-3.16.djgpp/src/mv.c	Mon May 22 15:13:48 2000
*************** do_move (const char *source, const char 
*** 345,354 ****
--- 345,364 ----
     Return 0 if successful, 1 if an error occurred.  */
  
  static int
  movefile (const char *source, const char *dest)
  {
+ #ifdef MSDOS
+   /* Make sure the directory is explicit in SOURCE.  */
+   if (source[1] == ':' && source[2] != '/')
+     {
+       char *newsource = alloca (PATH_MAX + 1);
+ 
+       FIXPATH (source, newsource);
+       source = newsource;
+     }
+ #endif
    strip_trailing_slashes (source);
  
    if ((dest[strlen (dest) - 1] == '/' && !is_real_dir (source))
        || isdir (dest))
      {
*************** main (int argc, char **argv)
*** 490,499 ****
--- 500,529 ----
  
    if (argc > optind + 2 && !isdir (argv[argc - 1]))
      error (1, 0,
  	   _("when moving multiple files, last argument must be a directory"));
  
+ #ifdef MSDOS
+     /* Destination = "d:path" is relative to current dir on drive d:  */
+   if (argv[argc - 1][1] == ':' && argv[argc - 1][2] != '/')
+     {
+       char *newname   = alloca (PATH_MAX + 1);
+       char *dest      = argv[argc - 1];
+       /* Make sure "d:" is treated as "d:./".  It doesn't make sense not
+ 	 to, since you cannot remove the current directory on another
+ 	 drive, so we will get an error any other way.  */
+       int   add_slash = dest[strlen (dest) - 1] == '/' || dest[2] == '\0';
+ 
+       /* Convert "d:" into an absolute pathname.  */
+       FIXPATH (dest, newname);
+       if (add_slash		/* dest/ has a special meaning in `mv' */
+ 	  && newname[strlen (newname) - 1] != '/')
+ 	strcat (newname, "/");
+       argv[argc - 1] = newname;
+     }
+ #endif
+ 
    /* Move each arg but the last onto the last. */
    for (; optind < argc - 1; ++optind)
      errors |= movefile (argv[optind], argv[argc - 1]);
  
    exit (errors);
diff -acrpNC5 fileutils-3.16.orig/src/rm.c fileutils-3.16.djgpp/src/rm.c
*** fileutils-3.16.orig/src/rm.c	Sat Nov 23 22:11:12 1996
--- fileutils-3.16.djgpp/src/rm.c	Mon May 22 15:13:48 2000
*************** main (int argc, char **argv)
*** 153,162 ****
--- 153,169 ----
  	default:
  	  usage (1);
  	}
      }
  
+ #ifdef __DJGPP__
+   /* If they said `rm -r', let us find hidden files also,
+      otherwise we cannot remove directories with such files.  */
+   if (recursive)
+     __opendir_flags |= __OPENDIR_FIND_HIDDEN;
+ #endif
+ 
    if (show_version)
      {
        printf ("rm (%s) %s\n", GNU_PACKAGE, VERSION);
        exit (0);
      }
*************** main (int argc, char **argv)
*** 190,199 ****
--- 197,222 ----
  	  free (pathname);
  	  pnsize = 2 * (len + 1);
  	  pathname = xmalloc (pnsize);
  	}
        strcpy (pathname, argv[optind]);
+ #ifdef MSDOS
+   /* pathname = "d:" means current dir on drive d:  */
+       if (pathname[0] && pathname[1] == ':' && pathname[2] == '\0')
+ 	{
+ 	  char fullname[PATH_MAX + 1];
+ 
+ 	  FIXPATH (pathname, fullname);	/* convert into an absolute pathname */
+ 	  if ((len = strlen (fullname)) + 1 > pnsize)
+ 	    {
+ 	      free (pathname);
+ 	      pnsize = 2 * (len + 1);
+ 	      pathname = xmalloc (pnsize);
+ 	    }
+ 	  memcpy (pathname, fullname, len + 1);
+ 	}
+ #endif
        err += rm ();
      }
  
    exit (err > 0);
  }
*************** clear_directory (struct stat *statp)
*** 455,473 ****
--- 478,507 ----
  
  	  /* Append '/' and the filename to current pathname, take care of
  	     the file (which could result in recursive calls), and take
  	     the filename back off.  */
  
+ #ifdef MSDOS
+ 	  /* Don't generate ugly double slashes after a drive letter.  */
+ 	  if (pathstack->pathp[-1] == '/')
+ 	    pathstack->pathp--;
+ #endif
  	  *pathstack->pathp = '/';
  	  strcpy (pathstack->pathp + 1, namep);
  
  	  /* If the i-number has already appeared, there's an error.  */
  	  if (duplicate_entry (pathstack->next, pathstack->inum))
  	    err++;
  	  else if (rm ())
  	    err++;
  
+ #ifdef MSDOS
+           /* Don't delete a slash, if it is preceded by the drive
+              specifier (meaning we're in a root directory).  */
+           if (pathstack->pathp[-1] == ':')
+             pathstack->pathp++;
+ #endif
  	  *pathstack->pathp = '\0';
  	  pathstack = pathstack->next;	/* Pop the stack.  */
  	}
      }
    /* Keep trying while there are still files to remove.  */
diff -acrpNC5 fileutils-3.16.orig/src/sync.c fileutils-3.16.djgpp/src/sync.c
*** fileutils-3.16.orig/src/sync.c	Sat Nov  2 23:42:12 1996
--- fileutils-3.16.djgpp/src/sync.c	Mon May 22 15:13:48 2000
***************
*** 19,28 ****
--- 19,32 ----
  
  #include <config.h>
  #include <stdio.h>
  #include <sys/types.h>
  
+ #ifdef __DJGPP__
+ #include <io.h>
+ #endif
+ 
  #include "system.h"
  #include "long-options.h"
  #include "error.h"
  
  /* The name this program was run with. */
*************** main (int argc, char **argv)
*** 60,66 ****
--- 64,74 ----
  
    if (argc != 1)
      error (0, 0, _("ignoring all arguments"));
  
    sync ();
+ #ifdef __DJGPP__
+   /* Try to cause write-back caches to flush their buffers.  */
+   _flush_disk_cache ();
+ #endif
    exit (0);
  }
diff -acrpNC5 fileutils-3.16.orig/src/system.h fileutils-3.16.djgpp/src/system.h
*** fileutils-3.16.orig/src/system.h	Wed Dec 18 03:19:24 1996
--- fileutils-3.16.djgpp/src/system.h	Mon May 22 15:13:48 2000
*************** char *getenv ();
*** 247,257 ****
  /* Extract or fake data from a `struct stat'.
     ST_BLKSIZE: Optimal I/O blocksize for the file, in bytes.
     ST_NBLOCKS: Number of 512-byte blocks in the file
     (including indirect blocks). */
  #ifndef HAVE_ST_BLOCKS
! # define ST_BLKSIZE(statbuf) DEV_BSIZE
  # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE.  */
  #  define ST_NBLOCKS(statbuf) (((statbuf).st_size + 512 - 1) / 512)
  # else /* !_POSIX_SOURCE && BSIZE */
  #  define ST_NBLOCKS(statbuf) (st_blocks ((statbuf).st_size))
  # endif /* !_POSIX_SOURCE && BSIZE */
--- 247,262 ----
  /* Extract or fake data from a `struct stat'.
     ST_BLKSIZE: Optimal I/O blocksize for the file, in bytes.
     ST_NBLOCKS: Number of 512-byte blocks in the file
     (including indirect blocks). */
  #ifndef HAVE_ST_BLOCKS
! # ifdef MSDOS
! #  define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
! 			        ? (statbuf).st_blksize : DEV_BSIZE)
! # else /* !MSDOS */
! #  define ST_BLKSIZE(statbuf) DEV_BSIZE
! #endif /* !MSDOS */
  # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE.  */
  #  define ST_NBLOCKS(statbuf) (((statbuf).st_size + 512 - 1) / 512)
  # else /* !_POSIX_SOURCE && BSIZE */
  #  define ST_NBLOCKS(statbuf) (st_blocks ((statbuf).st_size))
  # endif /* !_POSIX_SOURCE && BSIZE */
*************** char *getenv ();
*** 275,288 ****
  #   endif /* not _CRAY */
  #  endif /* not AIX PS/2 */
  # endif /* !hpux */
  #endif /* HAVE_ST_BLOCKS */
  
- /* Convert B 512-byte blocks to kilobytes if K is nonzero,
-    otherwise return it unchanged. */
- #define convert_blocks(b, k) ((k) ? ((b) + 1) / 2 : (b))
- 
  #ifndef RETSIGTYPE
  #define RETSIGTYPE void
  #endif
  
  #ifdef __GNUC__
--- 280,289 ----
*************** char *alloca ();
*** 384,389 ****
  # undef textdomain
  # define textdomain(Domain) /* empty */
  # define _(Text) Text
  #endif
  
! #define STREQ(a,b) (strcmp((a), (b)) == 0)
--- 385,405 ----
  # undef textdomain
  # define textdomain(Domain) /* empty */
  # define _(Text) Text
  #endif
  
! #ifdef MSDOS
! /* MSDOS and compatible systems are case-insensitive in filenames.  */
! # define STREQ(a,b) (strcasecmp((a), (b)) == 0)
! /* Define a way to convert a pathname into absolute form.
!    Examples:
!                file		-> d:/dir/subdir/file
! 	       d:path		-> d:/curdir/path
! 	       /dir/subdir	-> x:/dir/subdir              */
! # ifdef __DJGPP__
! #  define FIXPATH(x,y)  _fixpath(x,y)
! # else  /* !__DJGPP__ */
! #  error FIXPATH macro not defined on MSDOS!
! # endif /* !__DJGPP__ */
! #else  /* !MSDOS */
! # define STREQ(a,b) (strcmp((a), (b)) == 0)
! #endif /* !MSDOS */
diff -acrpNC5 fileutils-3.16.orig/src/touch.c fileutils-3.16.djgpp/src/touch.c
*** fileutils-3.16.orig/src/touch.c	Mon Nov 18 02:52:48 1996
--- fileutils-3.16.djgpp/src/touch.c	Mon May 22 15:13:48 2000
*************** touch (char *file)
*** 192,202 ****
  
        if (!(change_times & CH_ATIME))
  	utb.actime = sbuf.st_atime;
  
        if (!(change_times & CH_MTIME))
! 	utb.modtime = sbuf.st_mtime;
  
        status = utime (file, &utb);
      }
  
    if (status)
--- 192,216 ----
  
        if (!(change_times & CH_ATIME))
  	utb.actime = sbuf.st_atime;
  
        if (!(change_times & CH_MTIME))
! 	{
! 	  utb.modtime = sbuf.st_mtime;
! #ifdef MSDOS
! #ifdef __DJGPP__
! 	  /* DJGPP supports long filename API on Windows 9x, which does
! 	     allow to set all the 3 timestamps.  This support is only
! 	     switched on at run time, and only if the filesystem where
! 	     FILE belongs supports that API.  */
! 	  if (!_use_lfn (file))
! #endif
! 	  /* Plain MS-DOS has only 1 timestamp for files.
! 	     Use the modtime field for that.  */
! 	  utb.modtime = utb.actime;
! #endif
! 	}
  
        status = utime (file, &utb);
      }
  
    if (status)
