Mail Archives: djgpp-workers/1997/09/14/14:54:09
A patch for `mntent' that clears some bugs which only show on NT:
diff -c src/libc/compat/mntent/mntent.c~0 src/libc/compat/mntent/mntent.c
*** src/libc/compat/mntent/mntent.c~0 Tue Aug 13 03:14:46 1996
--- src/libc/compat/mntent/mntent.c Sat Apr 12 12:21:06 1997
***************
*** 1,9 ****
/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
/*
* This is implementation of getmntent() and friends for DJGPP v2.x.
*
! * Copyright (c) 1995-96 Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
*
* This software may be used freely so long as this copyright notice is
* left intact. There is no warranty on this software.
--- 1,10 ----
+ /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
/*
* This is implementation of getmntent() and friends for DJGPP v2.x.
*
! * Copyright (c) 1995-97 Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
*
* This software may be used freely so long as this copyright notice is
* left intact. There is no warranty on this software.
***************
*** 41,47 ****
#include <go32.h>
#include <libc/farptrgs.h>
#include <sys/movedata.h>
! #include <libc/unconst.h>
/* Macro to convert a segment and an offset to a "far offset" suitable
for _farxxx() functions of DJGPP. */
--- 42,48 ----
#include <go32.h>
#include <libc/farptrgs.h>
#include <sys/movedata.h>
! #include <libc/dosio.h>
/* Macro to convert a segment and an offset to a "far offset" suitable
for _farxxx() functions of DJGPP. */
***************
*** 114,121 ****
our_mem_base, (unsigned int)currdir, 0x43);
/* The drive attribute word is at the offset 43h, right after the
! current directory string. */
! return _farpeekw(dos_mem_base, cds_entry_address + 0x43);
}
/*
--- 115,123 ----
our_mem_base, (unsigned int)currdir, 0x43);
/* The drive attribute word is at the offset 43h, right after the
! current directory string. NT doesn't support this. */
! return
! cds_elsize == 0x47 ? 0 : _farpeekw(dos_mem_base, cds_entry_address + 0x43);
}
/*
***************
*** 368,398 ****
}
/*
! * Return 1 if a CD-ROM drive DRIVE_NUM is ready, i.e. there is a
! * disk in the drive and that disk is a data (not AUDIO) disk.
*/
static int
cdrom_drive_ready(int drive_num)
{
__dpmi_regs r;
- int i = 2;
! /* Int 2Fh/AX=1505h (Read Volume Table Of Contents) will return
! with error for empty drives or if the disk is an AUDIO disk. */
! r.x.es = __tb >> 4;
! r.x.bx = __tb & 15;
! r.x.cx = drive_num - 1; /* 0 = A: */
! r.x.dx = 0; /* get the 1st descriptor (usually, the only one) */
!
! /* First time after the door is closed the call might fail.
! Therefore try twice before giving up. */
! do
! {
! r.x.ax = 0x1505;
! __dpmi_int(0x2f, &r);
! } while (--i && (r.x.flags & 1));
!
! if ((r.x.flags & 1) == 0 && (r.x.ax == 0 || r.x.ax == 1))
return 1;
return 0;
}
--- 370,428 ----
}
/*
! * Return 1 if a CD-ROM drive DRIVE_NUM is ready, i.e. there
! * is a disk in the drive and the tray door is closed.
*/
static int
cdrom_drive_ready(int drive_num)
{
__dpmi_regs r;
! /* We need to avoid reading any information off the CD-ROM,
! because then the driver will dupe MSCDEX into thinking the
! disk isn't ever changed, and DOS calls get stale info after
! you change the disk. (We cannot use DOS calls *before* this
! function, because QDPMI will crash the program if we issue
! a DOS call that hits the disk when the drive is empty or the
! disk is an audio disk.)
!
! So we use the Read Device Status command and look for the
! door open and drive empty bits (seems like door locked bit
! is not universally supported). This still leaves an unsolved
! problem: an audio disk will be reported as a ready drive, and
! under QDPMI will crash the program when we access the drive.
! I don't see any way out of this mess (anybody?). Well, at
! least with data disks we don't screw up DOS operations anymore.
!
! Gosh, why is it always so tricky with Microsoft software?? */
!
! unsigned char request_header[0x14];
! int status;
! unsigned dev_status;
!
! /* Construct the request header for the CD-ROM device driver. */
! memset(request_header, 0, sizeof request_header);
! request_header[0] = sizeof request_header;
! request_header[2] = 3; /* IOCTL READ command */
! *(unsigned short *)&request_header[0xe] = __tb_offset;
! *(unsigned short *)&request_header[0x10] = __tb_segment;
! request_header[0x12] = 5; /* number of bytes to transfer */
!
! /* Put control block into the transfer buffer. */
! _farpokeb(_dos_ds, __tb, 6); /* read device status */
! _farpokel(_dos_ds, __tb + 1, 0); /* zero out the result field */
!
! /* Put request header into the transfer buffer and call the driver. */
! dosmemput(request_header, sizeof (request_header), __tb + 5);
! r.x.ax = 0x1510;
! r.x.cx = drive_num - 1;
! r.x.es = __tb_segment;
! r.x.bx = __tb_offset + 5;
! __dpmi_int(0x2f, &r);
! status = _farpeekw(_dos_ds, __tb + 5 + 3);
! dev_status = _farpeekl(_dos_ds, __tb + 1);
! if (status == 0x100 && _farpeekw (_dos_ds, __tb + 5 + 0x12) == 5
! && (dev_status & 0x801) == 0) /* door open and drive empty bits */
return 1;
return 0;
}
***************
*** 473,478 ****
--- 503,513 ----
cds_address_offset = 0x17;
cds_elsize = 0x51;
}
+ else if (true_dos_version == 0x0332) /* NT */
+ {
+ cds_address_offset = 0x16;
+ cds_elsize = 0x47;
+ }
else
{
cds_address_offset = 0x16;
***************
*** 597,609 ****
These are used in the above order. */
/* See what 2160 can tell us. If it fails, there ain't no such
! drive, as far as DOS is concerned. */
truename_result = _truename(drive_string, mnt_fsname);
/* Get some info from the DOS Current Directory Structure (CDS).
! We've already hit the disk with _truename(), so CDS now
! contains valid and up to date data. */
! if (drive_number <= cds_drives)
cds_flags = get_cds_entry(drive_number, cds_path);
if (truename_result != NULL)
--- 632,651 ----
These are used in the above order. */
/* See what 2160 can tell us. If it fails, there ain't no such
! drive, as far as DOS is concerned. Some DOS clones, like NT,
! don't always upcase the drive letter, so we must do that here. */
truename_result = _truename(drive_string, mnt_fsname);
+ if (truename_result && mnt_fsname[0]
+ && mnt_fsname[1] == ':' && islower(mnt_fsname[0]))
+ mnt_fsname[0] = toupper(mnt_fsname[0]);
/* Get some info from the DOS Current Directory Structure (CDS).
! We've already hit the disk with _truename(), so CDS now
! contains valid and up to date data. Don't look at the CDS
! for remote drives: they can't be JOINed anyway, and some
! DOS clones, such as NT, don't put them into the CDS. */
! if (drive_number <= cds_drives
! && !_is_remote_drive (drive_number - 1))
cds_flags = get_cds_entry(drive_number, cds_path);
if (truename_result != NULL)
***************
*** 631,644 ****
if (is_ram_drive(drive_number))
mnt_type = NAME_ram;
else if (is_cdrom_drive(drive_number))
! {
! /* Empty CD-ROM drives do NOT fail _truename(),
! so we must see if there is a disk in the drive. */
! if (cdrom_drive_ready(drive_number))
! mnt_type = NAME_cdrom;
! else
! continue; /* don't report this drive */
! }
/* _is_remote_drive() needs zero-based disk number */
else if (_is_remote_drive(drive_number - 1) == 1)
mnt_type = NAME_net;
--- 673,686 ----
if (is_ram_drive(drive_number))
mnt_type = NAME_ram;
else if (is_cdrom_drive(drive_number))
! {
! /* Empty CD-ROM drives do NOT fail _truename(),
! so we must see if there is a disk in the drive. */
! if (cdrom_drive_ready(drive_number))
! mnt_type = NAME_cdrom;
! else
! continue;
! }
/* _is_remote_drive() needs zero-based disk number */
else if (_is_remote_drive(drive_number - 1) == 1)
mnt_type = NAME_net;
***************
*** 696,706 ****
/* Some network redirectors don't set a UNC path to be
returned by _truename(). See if 215F02 can help. */
! if ((!got_fsname || mnt_fsname[0] != '\\') &&
! strcmp(mnt_type, "net") == 0)
if (get_netredir_entry(drive_number))
got_fsname = 1;
! if (!got_fsname || strcmp(mnt_type, "cdrom") == 0)
{
/* Look for the volume label. */
int e = errno;
--- 738,749 ----
/* Some network redirectors don't set a UNC path to be
returned by _truename(). See if 215F02 can help. */
! if ((!got_fsname || mnt_fsname[0] != '\\') && mnt_type == NAME_net)
if (get_netredir_entry(drive_number))
got_fsname = 1;
! /* MSCDEX makes `_truename' return a dull "\\X.\A.", so
! try to get the label anyway. */
! if (!got_fsname || mnt_type == NAME_cdrom)
{
/* Look for the volume label. */
int e = errno;
***************
*** 724,732 ****
got_fsname = 1;
}
!
else if (errno == ENMFILE || errno == ENOENT)
{
/* Valid drive, but no label. Construct default
filesystem name. If drive A: is mapped to B:,
call it ``Drive A:''. */
--- 767,795 ----
got_fsname = 1;
}
! /* CD-ROM without a label is taken as an empty CD drive or an
! audio disk, and not reported. This is because MSCDEX doesn't
! fail `_truename' for these cases and some DOS clones, such as
! NT, don't even emulate the drive empty bit reliably.
! I have never seen a CD-ROM without a label. Anybody? */
! else if (mnt_type == NAME_cdrom)
! got_fsname = 0;
else if (errno == ENMFILE || errno == ENOENT)
{
+ /* Some device drivers for removable media (like JAZ on NT DOS
+ box) pass all above tests when the drive is empty. Force
+ them to hit the disk with DOS Get Free Disk Space function,
+ and if that fails, treat that drive as non-existing. */
+ if (mnt_type == NAME_fd)
+ {
+ __dpmi_regs r;
+
+ r.h.ah = 0x36;
+ r.h.dl = drive_number;
+ __dpmi_int(0x21, &r);
+ if ( (r.x.ax & 0xffff) == 0xffff ) /* aha! an impostor! */
+ continue;
+ }
/* Valid drive, but no label. Construct default
filesystem name. If drive A: is mapped to B:,
call it ``Drive A:''. */
***************
*** 763,776 ****
mntent.mnt_opts = dev_opts;
/* Make CD-ROM drives read-only, others read-write. */
! if (strcmp(mnt_type, "cdrom") == 0)
dev_opts[1] = 'o';
else
dev_opts[1] = 'w';
/* Include "dev=XX" in the mnt_opts field, where XX should
be consistent with what stat() returns in st_dev. */
! sprintf(xdrive, "%02x", strcmp(mnt_type, "subst")
? drive_number - 1
: mnt_fsname[0] - 'A');
dev_opts[7] = xdrive[0];
--- 826,839 ----
mntent.mnt_opts = dev_opts;
/* Make CD-ROM drives read-only, others read-write. */
! if (mnt_type == NAME_cdrom)
dev_opts[1] = 'o';
else
dev_opts[1] = 'w';
/* Include "dev=XX" in the mnt_opts field, where XX should
be consistent with what stat() returns in st_dev. */
! sprintf(xdrive, "%02x", mnt_type != NAME_subst
? drive_number - 1
: mnt_fsname[0] - 'A');
dev_opts[7] = xdrive[0];
- Raw text -