Mail Archives: djgpp-workers/1996/11/03/10:03:50
`_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 -