Mail Archives: djgpp-workers/1999/09/22/12:54:13
According to Eli Zaretskii:
> I don't remember, it was a long time ago. Perhaps you could post an
> augmented source, and I will then test.
Ok, here it is.
Right,
MartinS
/*
* File getfatsz.c.
*
* Copyright (C) 1999 Martin Str<94>mberg <ams AT ludd DOT luth DOT se>.
*
* This software may be used freely so long as this copyright notice is
* left intact. There is no warranty on this software.
*
* FAT size algorithm according to "Hardware White Paper, FAT: General
* Overwiew of On-Disk Format" version 1.02, May 5, 1999, Microsoft
* Corporation. Downloadable from <http://www.microsoft.com/hwdev/>.
*
*/
#include <dpmi.h>
#include <go32.h>
#include <errno.h>
#include <sys/farptr.h>
#include <stdio.h>
#include <dos.h>
#include <errno.h>
#include <go32.h>
#include <dpmi.h>
#include <libc/dosio.h>
#include <sys/farptr.h>
/* Returns: -1 == error; 0 == result_str filled in. */
int
_get_fs_type( const int drive /* drive number (1=A:). */
, char *const result_str /* String to put result in. At least 9 cha
rs long. */
)
{
int n;
__dpmi_regs r;
/* Check DOZE version and return -1 if too low. */
if( ( _get_dos_version(1) >> 8) < 4 )
{
errno = ENOSYS;
return( -1 );
}
/* Call INT21, ax==0x6900 i.e. Get Disk Serial Number (sic!). */
r.x.ax = 0x6900;
r.h.bl = drive;
r.h.bh = 0;
r.x.ds = __tb >> 4;
r.x.dx = __tb & 0x0f;
__dpmi_int(0x21, &r);
if( (r.x.flags & 1) == 0 )
{
/* Get the file system type. */
for(n = 0; n < 8; n++)
{
result_str[n] = _farpeekb( _dos_ds, __tb + 0x11 + n);
}
result_str[8] = 0;
/* Remove terminating spaces. */
for(n = 7; n && result_str[n] == ' '; n-- )
{
result_str[n] = 0;
}
return( 0 );
}
errno = __doserr_to_errno(r.x.ax);
return( -1 );
}
/* Returns number of bits in FAT; 0 == FAT of unknown size; -1 == error. */
int
_get_fat_size( const int drive /* drive number (1=A:). */
)
{
__dpmi_regs r = {{0}};
int size;
unsigned long bytes_per_sector, sectors_per_cluster, reserved_sectors;
unsigned long number_of_fats, root_entries, fat16_size, fat32_size;
unsigned long total16_sectors, total32_sectors;
unsigned long root_sectors, fat_size, total_sectors, data_sectors;
unsigned long number_of_clusters;
r.x.ax = 0x440d;
r.h.bl = drive;
r.h.ch = 0x48; /* First we try a FAT32 disk drive. */
r.h.cl = 0x60;
r.x.ds = r.x.si = __tb >>4;
r.x.dx = r.x.di = __tb & 0x0f;
__dpmi_int(0x21, &r);
if( r.x.flags & 0x01 )
{
/* Hmmpf! That didn't work; fall back to disk drive. */
r.x.ax = 0x440d;
r.h.bl = drive;
r.h.ch = 0x08; /* Disk drive. */
r.h.cl = 0x60;
r.x.ds = r.x.si = __tb >>4;
r.x.dx = r.x.di = __tb & 0x0f;
__dpmi_int(0x21, &r);
if( r.x.flags & 0x01 )
{
errno = ENOSYS;
return(-1);
}
}
bytes_per_sector = _farpeekw(_dos_ds, __tb+7+11-11);
sectors_per_cluster = _farpeekb(_dos_ds, __tb+7+13-11);
reserved_sectors = _farpeekw(_dos_ds, __tb+7+14-11);
number_of_fats = _farpeekb(_dos_ds, __tb+7+16-11);
root_entries = _farpeekw(_dos_ds, __tb+7+17-11);
fat16_size = _farpeekw(_dos_ds, __tb+7+22-11);
fat32_size = _farpeekl(_dos_ds, __tb+7+36-11);
total16_sectors = _farpeekw(_dos_ds, __tb+7+19-11);
total32_sectors = _farpeekl(_dos_ds, __tb+7+32-11);
/* Check sectors_per_cluster, which might be zero. */
if( sectors_per_cluster == 0 )
{
errno = ENOSYS;
return( -1 );
}
/* Do the calculations. */
root_sectors = ( (root_entries * 32)
+ (bytes_per_sector - 1)
) / bytes_per_sector;
fat_size = fat16_size ? fat16_size : fat32_size;
total_sectors = total16_sectors ? total16_sectors : total32_sectors;
data_sectors = total_sectors - reserved_sectors - number_of_fats*fat_size
- root_sectors;
number_of_clusters = data_sectors / sectors_per_cluster;
if( number_of_clusters < 4085 )
{
size = 12;
}
else if( number_of_clusters < 65525 )
{
/* The algorithm misdetects NTFS as FAT16, so lets check if it's NTFS. */
char tmp[9];
if( !_get_fs_type( drive, tmp ) && tmp[0] == 'N' && tmp[1] == 'T' )
{
errno = ENOSYS;
return( -1 );
}
size = 16;
}
else
{
size = 32;
}
#if 0
fprintf(stderr, "bytes_per_sector = %ld.\n", bytes_per_sector);
fprintf(stderr, "sectors_per_cluster = %ld.\n", sectors_per_cluster);
fprintf(stderr, "reserved_sectors = %ld.\n", reserved_sectors);
fprintf(stderr, "number_of_fats = %ld.\n", number_of_fats);
fprintf(stderr, "root_entries = %ld.\n", root_entries);
fprintf(stderr, "fat16_size = %ld.\n", fat16_size);
fprintf(stderr, "fat32_size = %ld.\n", fat32_size);
fprintf(stderr, "total16_sectors = %ld.\n", total16_sectors);
fprintf(stderr, "total32_sectors = %ld.\n", total32_sectors);
fprintf(stderr, "root_sectors = %ld.\n", root_sectors);
fprintf(stderr, "data_sectors = %ld.\n", data_sectors);
fprintf(stderr, "number_of_clusters = %ld.\n", number_of_clusters);
#endif
return( size );
}
#if 1
int main(int argc, char *argv[])
{
int ret;
if( argc == 2
&& 'A' <= argv[1][0]
&& argv[1][0] <= 'Z' )
{
ret = _get_fat_size(argv[1][0] - 'A' + 1);
fprintf(stderr, "_get_fat_size returned %d.\n", ret);
return(0);
}
else
{
fprintf(stderr, "%s: run like this '%s C'.\n", argv[0], argv[0]);
return(1);
}
}
#endif
- Raw text -