X-Originating-IP: [200.42.4.138] From: "Norberto Alfredo Bensa" To: "Martin Str|mberg" Cc: References: <200101051844 DOT TAA15180 AT father DOT ludd DOT luth DOT se> Subject: Re: Fw: Patch for statfs.c Date: Fri, 5 Jan 2001 21:48:08 -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: X-OriginalArrivalTime: 06 Jan 2001 01:09:52.0361 (UTC) FILETIME=[5F860590:01C0777D] Reply-To: djgpp-workers AT delorie DOT com Martin, I've moved the CD-ROM calls down to the "one_more_try" part of the code, just before 213600. Can you please test if this now works with DVDs too? Best regards, Norberto /* 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 #include #include #include #include #include #include #include #include #include #include int statfs(const char *path, struct statfs *buf) { __dpmi_regs regs; int drive_number; long blocks = 0; long free = 0; long bsize = 0; int one_more_try = 0; int dos_version = _get_dos_version(1) >> 8; /* 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, ®s); drive_number = regs.h.al; } if (0x07 <= dos_version /* Is FAT32 supported? */ && 0x0a != dos_version) /* OS/2 doesn't support FAT32 */ { /* 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, ®s); /* 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, ®s); /* 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) { /* 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). */ int cdrom_calls_used = 0; regs.x.ax = 0x150b; /* is this drive supported by CD-ROM driver? */ regs.x.cx = drive_number; __dpmi_int(0x2f, ®s); 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, ®s); 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, ®s); 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) { /* 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, ®s); /* 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 #include 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