delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1996/11/03/10:03:50

Date: Sun, 3 Nov 1996 17:00:20 +0200 (IST)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
To: djgpp-workers AT delorie DOT com
Subject: /dev/null support by `stat' and `_truename'
Message-Id: <Pine.SUN.3.91.961103165635.28604B-100000@is>
Mime-Version: 1.0

`_truename' didn't use `putpath' and therefore didn't support the /dev/
style of standard devices.  `stat' also failed on devices in some cases.  
(I think this is the cause of bash failing on redirection to /dev/null.) 
Here's the patch: 

*** src/libc/posix/sys/stat/stat.c~1	Fri Nov  1 11:06:52 1996
--- src/libc/posix/sys/stat/stat.c	Sat Nov  2 15:05:56 1996
*************** stat_assist(const char *path, struct sta
*** 391,396 ****
--- 391,397 ----
  {
    struct   ffblk ff_blk;
    char     canon_path[MAX_TRUE_NAME];
+   char     pathname[MAX_TRUE_NAME];
    short    drv_no;
    unsigned dos_ftime;
  
*************** stat_assist(const char *path, struct sta
*** 407,420 ****
    statbuf->st_blksize = _go32_info_block.size_of_transfer_buffer;
  #endif
  
    /* Get the drive number.  It is always explicit, since we
       called `_fixpath' on the original pathname.  */
!   drv_no = toupper(*path) - 'A';
  
    /* Produce canonical pathname, with all the defaults resolved and
       all redundant parts removed.  This calls undocumented DOS
       function 60h.  */
!   if (_truename(path, canon_path))
      {
        /* Detect character device names which must be treated specially.
           We could simply call FindFirst and test the 6th bit, but some
--- 408,428 ----
    statbuf->st_blksize = _go32_info_block.size_of_transfer_buffer;
  #endif
  
+   /* Make the path explicit.  This makes the rest of our job much
+      easier by getting rid of some constructs which, if present,
+      confuse `_truename' and/or `findfirst'.  In particular, it
+      deletes trailing slashes, makes "d:" explicit, and allows us
+      to make an illusion of having a ".." entry in root directories.  */
+   _fixpath (path, pathname);
+ 
    /* Get the drive number.  It is always explicit, since we
       called `_fixpath' on the original pathname.  */
!   drv_no = toupper(pathname[0]) - 'A';
  
    /* Produce canonical pathname, with all the defaults resolved and
       all redundant parts removed.  This calls undocumented DOS
       function 60h.  */
!   if (_truename(path, canon_path) || _truename(pathname, canon_path))
      {
        /* Detect character device names which must be treated specially.
           We could simply call FindFirst and test the 6th bit, but some
*************** stat_assist(const char *path, struct sta
*** 485,491 ****
        /* _truename() failed.  (This really shouldn't happen, but who knows?)
           At least uppercase all letters, convert forward slashes to backward
           ones, and pray... */
!       register const char *src = path;
        register       char *dst = canon_path;
  
        while ( (*dst = (*src > 'a' && *src < 'z'
--- 493,499 ----
        /* _truename() failed.  (This really shouldn't happen, but who knows?)
           At least uppercase all letters, convert forward slashes to backward
           ones, and pray... */
!       register const char *src = pathname;
        register       char *dst = canon_path;
  
        while ( (*dst = (*src > 'a' && *src < 'z'
*************** stat_assist(const char *path, struct sta
*** 501,507 ****
      }
  
    /* Call DOS FindFirst function, which will bring us most of the info.  */
!   if (!__findfirst(path, &ff_blk, ALL_FILES))
      {
        /* Time fields. */
        dos_ftime =
--- 509,515 ----
      }
  
    /* Call DOS FindFirst function, which will bring us most of the info.  */
!   if (!__findfirst(pathname, &ff_blk, ALL_FILES))
      {
        /* Time fields. */
        dos_ftime =
*************** stat_assist(const char *path, struct sta
*** 532,538 ****
                statbuf->st_ino =
                  _invent_inode(canon_path, dos_ftime, ff_blk.ff_fsize);
              }
! 	  else if (toupper (canon_path[0]) != toupper (path[0])
  		   && canon_path[1] == ':'
  		   && canon_path[2] == '\\'
  		   && canon_path[3] == '\0')
--- 540,546 ----
                statbuf->st_ino =
                  _invent_inode(canon_path, dos_ftime, ff_blk.ff_fsize);
              }
! 	  else if (toupper (canon_path[0]) != toupper (pathname[0])
  		   && canon_path[1] == ':'
  		   && canon_path[2] == '\\'
  		   && canon_path[3] == '\0')
*************** stat_assist(const char *path, struct sta
*** 569,575 ****
                   first 2 bytes. */
                if (extension)
                  extension++;    /* get past the dot */
!               if (_is_executable(path, -1, extension))
                  statbuf->st_mode |= EXEC_ACCESS;
              }
          }
--- 577,583 ----
                   first 2 bytes. */
                if (extension)
                  extension++;    /* get past the dot */
!               if (_is_executable(pathname, -1, extension))
                  statbuf->st_mode |= EXEC_ACCESS;
              }
          }
*************** stat_assist(const char *path, struct sta
*** 582,594 ****
  	errno = ENODEV;
        return -1;
      }
!   else if (path[3] == '\0')
      {
        /* Detect root directories.  These are special because, unlike
! 	 subdirectories, FindFirst fails for them.  We look at PATH
  	 because a network redirector could tweak what `_truename'
! 	 returns to be utterly unrecognizable as root directory.
! 	 PATH always begins with "d:/", so it is root if PATH[3] = 0.  */
  
        /* Mode bits. */
        statbuf->st_mode |= (S_IFDIR|READ_ACCESS|WRITE_ACCESS|EXEC_ACCESS);
--- 590,602 ----
  	errno = ENODEV;
        return -1;
      }
!   else if (pathname[3] == '\0')
      {
        /* Detect root directories.  These are special because, unlike
! 	 subdirectories, FindFirst fails for them.  We look at PATHNAME
  	 because a network redirector could tweak what `_truename'
! 	 returns to be utterly unrecognizable as root directory.  PATHNAME
! 	 always begins with "d:/", so it is root if PATHNAME[3] = 0.  */
  
        /* Mode bits. */
        statbuf->st_mode |= (S_IFDIR|READ_ACCESS|WRITE_ACCESS|EXEC_ACCESS);
*************** stat_assist(const char *path, struct sta
*** 610,616 ****
  	{
  	  char buf[7];
  
! 	  strcpy(buf, path);
  	  strcat(buf, "*.*");
  	  if (!__findfirst(buf, &ff_blk, FA_LABEL))
  	    dos_ftime = ( (unsigned)ff_blk.ff_fdate << 16 ) + ff_blk.ff_ftime;
--- 618,624 ----
  	{
  	  char buf[7];
  
! 	  strcpy(buf, pathname);
  	  strcat(buf, "*.*");
  	  if (!__findfirst(buf, &ff_blk, FA_LABEL))
  	    dos_ftime = ( (unsigned)ff_blk.ff_fdate << 16 ) + ff_blk.ff_ftime;
*************** stat_assist(const char *path, struct sta
*** 621,649 ****
    else
      {
        int i = 0;
!       int j = strlen (path) - 1;
  
        /* Check for volume labels.  We did not mix FA_LABEL with
  	 other attributes in the call to `__findfirst' above,
  	 because some environments will return bogus info in
  	 that case.  For instance, Win95 and WinNT seem to
! 	 ignore `path' and return the volume label even if it
! 	 doesn't fit the name in `path'.  This fools us to
  	 think that a non-existent file exists and is a volume
! 	 label.  Hence we test the returned name to be PATH.  */
!       if (!__findfirst(path, &ff_blk, FA_LABEL))
  	{
  	  i = strlen (ff_blk.ff_name) - 1;
  
  	  if (j >= i)
  	    {
  	      for ( ; i >= 0 && j >= 0; i--, j--)
! 		if (toupper (ff_blk.ff_name[i]) != toupper (path[j]))
  		  break;
  	    }
  	}
  
!       if (i < 0 && path[j] == '/')
  	{
  	  /* Indeed a label.  */
  	  statbuf->st_mode = READ_ACCESS;
--- 629,657 ----
    else
      {
        int i = 0;
!       int j = strlen (pathname) - 1;
  
        /* Check for volume labels.  We did not mix FA_LABEL with
  	 other attributes in the call to `__findfirst' above,
  	 because some environments will return bogus info in
  	 that case.  For instance, Win95 and WinNT seem to
! 	 ignore `pathname' and return the volume label even if it
! 	 doesn't fit the name in `pathname'.  This fools us to
  	 think that a non-existent file exists and is a volume
! 	 label.  Hence we test the returned name to be PATHNAME.  */
!       if (!__findfirst(pathname, &ff_blk, FA_LABEL))
  	{
  	  i = strlen (ff_blk.ff_name) - 1;
  
  	  if (j >= i)
  	    {
  	      for ( ; i >= 0 && j >= 0; i--, j--)
! 		if (toupper (ff_blk.ff_name[i]) != toupper (pathname[j]))
  		  break;
  	    }
  	}
  
!       if (i < 0 && pathname[j] == '/')
  	{
  	  /* Indeed a label.  */
  	  statbuf->st_mode = READ_ACCESS;
*************** stat_assist(const char *path, struct sta
*** 712,725 ****
           even at performance cost, because it's more robust for
           networked drives.  */
  
!       size_t pathlen = strlen (path);
!       char   lastc   = path[pathlen - 1];
        char  *search_spec = (char *)alloca (pathlen + 10); /* need only +5 */
        int nfiles = 0, nsubdirs = 0, done;
        size_t extra = 0;
        int add_extra = 0;
  
!       strcpy(search_spec, path);
        if (lastc == '/')
          strcat(search_spec, "*.*");
        else
--- 720,733 ----
           even at performance cost, because it's more robust for
           networked drives.  */
  
!       size_t pathlen = strlen (pathname);
!       char   lastc   = pathname[pathlen - 1];
        char  *search_spec = (char *)alloca (pathlen + 10); /* need only +5 */
        int nfiles = 0, nsubdirs = 0, done;
        size_t extra = 0;
        int add_extra = 0;
  
!       strcpy(search_spec, pathname);
        if (lastc == '/')
          strcat(search_spec, "*.*");
        else
*************** stat_assist(const char *path, struct sta
*** 731,737 ****
  	     store the long filenames.  */
  	  char fstype[40];
  
! 	  if ((_get_volume_info(path, 0, 0, fstype) & _FILESYS_LFN_SUPPORTED)
  	      && strncmp(fstype, "FAT", 4) == 0)
  	    add_extra = 1;
  	}
--- 739,745 ----
  	     store the long filenames.  */
  	  char fstype[40];
  
! 	  if ((_get_volume_info(pathname,0,0,fstype) & _FILESYS_LFN_SUPPORTED)
  	      && strncmp(fstype, "FAT", 4) == 0)
  	    add_extra = 1;
  	}
*************** int
*** 777,783 ****
  stat(const char *path, struct stat *statbuf)
  {
    int  e = errno;
-   char pathname[MAX_TRUE_NAME];
    int  pathlen;
  
    if (!path || !statbuf)
--- 785,790 ----
*************** stat(const char *path, struct stat *stat
*** 799,812 ****
        return -1;
      }
  
!   /* Make the path explicit.  This makes the rest of our job much
!      easier by getting rid of some constructs which, if present,
!      confuse `_truename' and/or `findfirst'.  In particular, it
!      deletes trailing slashes, makes "d:" explicit, and allows us
!      to make an illusion of having a ".." entry in root directories.  */
!   _fixpath (path, pathname);
! 
!   if (stat_assist(pathname, statbuf) == -1)
      {
        return -1;      /* errno set by stat_assist() */
      }
--- 806,812 ----
        return -1;
      }
  
!   if (stat_assist(path, statbuf) == -1)
      {
        return -1;      /* errno set by stat_assist() */
      }
*** src/libc/dos/dos/truename.c~0	Sun Sep  1 01:09:32 1996
--- src/libc/dos/dos/truename.c	Sat Nov  2 15:14:40 1996
*************** _truename(const char *file, char *buf)
*** 99,106 ****
        name_start[3] = '.';
        name_start[4] = '\0';
      }
!   movedata(our_mem_selector, (unsigned int)name_start,
!            dos_mem_selector, __tb, strlen(name_start) + 1);
  
    /* Call DOS INT 21H undocumented function 60h. */
    if(use_lfn) {
--- 99,105 ----
        name_start[3] = '.';
        name_start[4] = '\0';
      }
!   _put_path(name_start);
  
    /* Call DOS INT 21H undocumented function 60h. */
    if(use_lfn) {
*** src/libc/dos/io/putpath.c~0	Sat Nov  2 15:15:42 1996
--- src/libc/dos/io/putpath.c	Sat Nov  2 15:28:32 1996
***************
*** 1,4 ****
--- 1,5 ----
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+ #include <libc/stubs.h>
  #include <libc/dosio.h>
  #include <libc/farptrgs.h>
  #include <go32.h>
*************** void
*** 16,21 ****
--- 17,23 ----
  _put_path2(const char *path, int offset)
  {
    int o, space = _go32_info_block.size_of_transfer_buffer - offset;
+   const char *p = path;
  
    if (path == 0)
    {
*************** _put_path2(const char *path, int offset)
*** 23,32 ****
      abort();
    }
  
!   if (strcmp(path, "/dev/null") == 0)
      path = "nul";
!   if (strcmp(path, "/dev/tty") == 0)
      path = "con";
  
    _farsetsel(_dos_ds);
  
--- 25,38 ----
      abort();
    }
  
!   if (p[0] && p[1] == ':')
!     p += 2;
!   if (strcmp(p, "/dev/null") == 0)
      path = "nul";
!   else if (strcmp(p, "/dev/tty") == 0)
      path = "con";
+   else if (strncmp(p, "/dev/", 5) == 0 && p[5] != 0)
+     path = p + 5;
  
    _farsetsel(_dos_ds);
  

- Raw text -


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