delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/12/30/13:45:22

X-Originating-IP: [200.42.4.138]
From: "Norberto Alfredo Bensa" <nbensa AT hotmail DOT com>
To: "Martin Str|mberg" <ams AT ludd DOT luth DOT se>
Cc: <djgpp-workers AT delorie DOT com>
References: <200012301550 DOT QAA14245 AT father DOT ludd DOT luth DOT se>
Subject: Re: Fw: Patch for statfs.c
Date: Sat, 30 Dec 2000 15:38:49 -0300
Organization: nBens@ Computers
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 5.50.4522.1200
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4522.1200
Message-ID: <OE579mxShok1Cuj9uho0000255b@hotmail.com>
X-OriginalArrivalTime: 30 Dec 2000 18:45:16.0837 (UTC) FILETIME=[A6F5FD50:01C07290]
Reply-To: djgpp-workers AT delorie DOT com

From: "Martin Str|mberg" <ams AT ludd DOT luth DOT se>
> According to Norberto Alfredo Bensa:
> > Now the patch...
> >
> > ------CUT---------8<---------CUT------------
> > --- src/libc/compat/sys/vfs/statfs.c.~ Mon Jun 19 19:00:56 2000
> > +++ src/libc/compat/sys/vfs/statfs.c Sat Dec 30 02:41:26 2000
> > @@ -108,73 +108,116 @@
> >
> >    if (!cdrom_calls_used)
> >    {
> > -    /* Get free space info from DOS.  */
> > -    regs.h.ah = 0x36;  /* DOS Get Free Disk Space call */
>
> Alas the patch only looked right. It won't apply for me. Are you
> diffing against the cvs version?

Yes, statfs.c from CVS dated 6/19/2000.

>
> Perhaps you could just send the whole statfs.c file as the patch is
> about as large as the file itself.
>

Here it goes...but first, I've made some last-minute changes:

1st. I've realised that this new version of statfs will fail on the very first
Windows 95 version (4.00.950), as that version doesn't support
FAT32 drives. Free space reporting on those Windows releases is
limited to ~2GB, even on network drives.

2nd. I've removed completely rescaling. It doesn't make any sense
now that I've changed the order in which the services are called.

3rd. I've removed every '#if 0..#endif' in the code...

One more thing, reporting for network drives, is only totally functional
if running under Windows. Other environments may be limited to
~2GB (I'm guessing here)

Best regards,
Norberto

------cut--------8<------cut--------
/* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <libc/stubs.h>
#include <string.h>
#include <dpmi.h>
#include <go32.h>
#include <dos.h>
#include <libc/farptrgs.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/vfs.h>
#include <libc/dosio.h>

int
statfs(const char *path, struct statfs *buf)
{
  __dpmi_regs regs;
  int drive_number;
  int cdrom_calls_used = 0;
  int one_more_try = 0;
  long blocks = 0;
  long free = 0;
  long bsize = 0;

  /* Get the drive number, including the case of magic
     names like /dev/c/foo.  */
  _put_path(path);
  drive_number = (_farpeekb(_dos_ds, __tb) & 0x1f) - 1;
  if (_farpeekb(_dos_ds, __tb + 1) != ':' || drive_number == -1)
  {
    regs.h.ah = 0x19;
    __dpmi_int(0x21, &regs);
    drive_number = regs.h.al;
  }

  /* For a CD-ROM drive, 213600 gives incorrect info.
     Use CD-ROM-specific calls if they are available.

     Int 2Fh/AX=1510h gives us a way of doing IOCTL with the
     CD-ROM device driver without knowing the name of the
     device (which is defined by the CONFIG.SYS line that
     installs the driver and can therefore be arbitrary).  */

  regs.x.ax = 0x150b; /* is this drive supported by CD-ROM driver? */
  regs.x.cx = drive_number;
  __dpmi_int(0x2f, &regs);
  if ((regs.x.flags & 1) == 0 && regs.x.bx == 0xadad && regs.x.ax != 0)
  {
    unsigned char request_header[0x14];
    int status, i = 2;

    /* 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] = 4; /* number of bytes to transfer */

    /* When the disk was just changed, we need to try twice.  */
    do {
      /* Put control block into the transfer buffer.  */
      _farpokeb (_dos_ds, __tb, 7); /* read sector size */
      _farpokeb (_dos_ds, __tb + 1, 0); /* cooked mode */
      _farpokew (_dos_ds, __tb + 2, 0); /* zero out the result field */

      /* Put request header into the transfer buffer and call the driver.  */
      dosmemput (request_header, sizeof (request_header), __tb + 4);
      regs.x.ax = 0x1510;
      regs.x.cx = drive_number;
      regs.x.es = __tb_segment;
      regs.x.bx = __tb_offset + 4;
      __dpmi_int (0x2f, &regs);
      status = _farpeekw (_dos_ds, __tb + 7);
      bsize  = _farpeekw (_dos_ds, __tb + 2);
    } while (--i && (status & 0x800f) == 0x800f); /* disk changed */

    if (status == 0x100 && _farpeekw (_dos_ds, __tb + 4 + 0x12) == 4)
    {
      request_header[0x12] = 5; /* number of bytes to transfer */
      /* Put control block into the transfer buffer.  */
      _farpokeb (_dos_ds, __tb, 8); /* read volume size */
      _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);
      regs.x.ax = 0x1510;
      regs.x.cx = drive_number;
      regs.x.es = __tb_segment;
      regs.x.bx = __tb_offset + 5;
      __dpmi_int (0x2f, &regs);
      if (_farpeekw (_dos_ds, __tb + 8) == 0x100
   && _farpeekw (_dos_ds, __tb + 5 + 0x12) == 5)
      {
 /* bsize has been set some lines above. */
 free = 0;  /* no free space: cannot add data to CD-ROM */
 blocks = _farpeekl (_dos_ds, __tb + 1);
 cdrom_calls_used = 1;
      }
    }
  }

  if (!cdrom_calls_used)
  {
    if( 7 <= (_get_dos_version(1) >> 8)) /* Is FAT32 supported? */
    {
      /* 217303 - Win9x - Get Extended Free Drive Space:
         Extended Drive Paramenter Block, seams to report the largest
         block of free clusters when running under Windows (this info
         is not confirmed), so I'm using this service here. BTW, it
         expects a path on DS:DX and should be not an empty string or
         the sevice will fail */
      if (path && !*path)
 _put_path ("/");
      else
 _put_path (path);

      regs.x.ax = 0x7303;
      regs.x.ds = regs.x.es = __tb_segment;
      regs.x.dx = regs.x.di = __tb_offset;
      regs.x.cx = 0x100; /* Buffer lenght. Actually ~70 bytes would be enough */
      __dpmi_int (0x21, &regs);

      /* On plain DOS, 217303 fails (?), so here comes the old code.
         Under DOS, ExtDPB returns "accurate" info (!?) */
      if (regs.x.flags & 1)
      {
 /* Get free space info from Extended Drive Parameter Block. */
 regs.x.ax = 0x7302;
 regs.h.dl = drive_number + 1;
 regs.x.es = __tb_segment;
 regs.x.di = __tb_offset;
 regs.x.cx = 0x100; /* 256 bytes should be enough (RBIL says 0x3f). */
 __dpmi_int(0x21, &regs);

 /* Errors? */
 if( regs.x.flags & 1 )
   one_more_try = 1;
 else
 {
   free = _farpeekl (_dos_ds, __tb + 0x2 + 0x1f);
   bsize = _farpeekw (_dos_ds, __tb + 0x2 + 0x2) *
     ( _farpeekb (_dos_ds, __tb + 0x2 + 0x4) + 1 );

   /* -1, because it was reporting 1 more cluster than CHKDSK,
             again, this information is not confirmed */
   blocks = _farpeekl( _dos_ds, __tb + 0x2 + 0x2d) - 1;
 }
      }
      else /* Use information from service 217303 */
      {
 free   = _farpeekl (_dos_ds, __tb + 0x0c);
 bsize  = _farpeekl (_dos_ds, __tb + 0x08)
  * _farpeekl (_dos_ds, __tb + 0x04);
 blocks = _farpeekl (_dos_ds, __tb + 0x10);
      }
    }
    else
      one_more_try = 1;

    /* DOS version is < 7  or this particular Windows version
       doesn't support FAT32 services */
    if (one_more_try)
    {
      /* Get free space info from DOS.  */
      regs.h.ah = 0x36;  /* DOS Get Free Disk Space call */
      regs.h.dl = drive_number + 1;
      __dpmi_int(0x21, &regs);

      /* Check for errors */
      if ((regs.x.ax & 0xffff) == 0xffff)
      {
 errno = ENODEV;
 return -1;
      }
      bsize = regs.x.cx * regs.x.ax;
      free = regs.x.bx;
      blocks = regs.x.dx;
    }
  }

  /* Fill in the structure */
  buf->f_bavail = free;
  buf->f_bfree = free;
  buf->f_blocks = blocks;
  buf->f_bsize = bsize;
  buf->f_ffree = free;
  buf->f_files = blocks;
  buf->f_type = 0;
  buf->f_fsid[0] = drive_number;
  buf->f_fsid[1] = MOUNT_UFS;
  buf->f_magic = FS_MAGIC;

  return 0;
}

#ifdef TEST

#include <stdio.h>
#include <errno.h>

int main (int argc, char *argv[])
{
  char *path = ".";
  struct statfs fsbuf;

  if (argc > 1)
    path = argv[1];
  errno = 0;

  if (statfs (path, &fsbuf) == 0)
    printf ("Results for `%s\':\n\nTotal blocks: %ld\nAvailable blocks: %ld\nBlock size: %ld\n",
     path, fsbuf.f_blocks, fsbuf.f_bfree, fsbuf.f_bsize);
  if (errno)
    perror (path);
  return 0;
}

#endif
------cut--------8<------cut--------





- Raw text -


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