From: Martin Str|mberg Message-Id: <200006101303.PAA17488@father.ludd.luth.se> Subject: LONG: fat32 diff in cvs (second try) To: djgpp-workers AT delorie DOT com (DJGPP-WORKERS) Date: Sat, 10 Jun 2000 15:03:27 +0200 (MET DST) X-Mailer: ELM [version 2.4ME+ PL54 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Reply-To: djgpp-workers AT delorie DOT com Ok-dokey! I think I have fixed all Eli's comments, including adding some more text to the description of _get_fat_size() and _get_fs_type(). Right, MartinS Index: djgpp/include/dos.h =================================================================== RCS file: /cvs/djgpp/djgpp/include/dos.h,v retrieving revision 1.5 diff -p -3 -r1.5 dos.h *** dos.h 1999/06/03 17:22:28 1.5 --- dos.h 2000/06/10 12:51:09 *************** extern int _doserrno; *** 135,140 **** --- 135,146 ---- unsigned short _get_dos_version(int); + int _get_fat_size(const int drive); + int _get_fs_type(const int drive, char *const result_str); + int _is_cdrom_drive(const int drive); + int _is_fat32(const int drive); + int _is_ram_drive(const int drive); + int _media_type(const int drive); int int86(int ivec, union REGS *in, union REGS *out); int int86x(int ivec, union REGS *in, union REGS *out, struct SREGS *seg); Index: djgpp/include/unistd.h =================================================================== RCS file: /cvs/djgpp/djgpp/include/unistd.h,v retrieving revision 1.5 diff -p -3 -r1.5 unistd.h *** unistd.h 1999/12/24 22:08:40 1.5 --- unistd.h 2000/06/10 12:51:09 *************** pid_t getppid(void); *** 102,107 **** --- 102,108 ---- uid_t getuid(void); int isatty(int _fildes); int link(const char *_existing, const char *_new); + offset_t llseek(int _fildes, offset_t _offset, int _whence); off_t lseek(int _fildes, off_t _offset, int _whence); long pathconf(const char *_path, int _name); int pause(void); Index: djgpp/include/sys/djtypes.h =================================================================== RCS file: /cvs/djgpp/djgpp/include/sys/djtypes.h,v retrieving revision 1.4 diff -p -3 -r1.4 djtypes.h *** djtypes.h 1999/12/14 11:57:45 1.4 --- djtypes.h 2000/06/10 12:51:10 *************** *** 7,12 **** --- 7,13 ---- #define __DJ_clock_t typedef int clock_t; #define __DJ_gid_t typedef int gid_t; #define __DJ_off_t typedef int off_t; + #define __DJ_offset_t typedef long long offset_t; #define __DJ_pid_t typedef int pid_t; #define __DJ_size_t typedef long unsigned int size_t; #define __DJ_ssize_t typedef int ssize_t; Index: djgpp/include/sys/fsext.h =================================================================== RCS file: /cvs/djgpp/djgpp/include/sys/fsext.h,v retrieving revision 1.3 diff -p -3 -r1.3 fsext.h *** fsext.h 1998/06/28 21:17:44 1.3 --- fsext.h 2000/06/10 12:51:10 *************** typedef enum { *** 31,37 **** __FSEXT_dup, __FSEXT_dup2, __FSEXT_fstat, ! __FSEXT_stat } __FSEXT_Fnumber; /* _ready gets passed a fd and should return a mask of these, --- 31,38 ---- __FSEXT_dup, __FSEXT_dup2, __FSEXT_fstat, ! __FSEXT_stat, ! __FSEXT_llseek } __FSEXT_Fnumber; /* _ready gets passed a fd and should return a mask of these, Index: djgpp/include/sys/types.h =================================================================== RCS file: /cvs/djgpp/djgpp/include/sys/types.h,v retrieving revision 1.4 diff -p -3 -r1.4 types.h *** types.h 1999/06/03 17:22:29 1.4 --- types.h 2000/06/10 12:51:10 *************** __DJ_gid_t *** 25,30 **** --- 25,33 ---- __DJ_off_t #undef __DJ_off_t #define __DJ_off_t + __DJ_offset_t + #undef __DJ_offset_t + #define __DJ_offset_t __DJ_pid_t #undef __DJ_pid_t #define __DJ_pid_t Index: djgpp/src/docs/kb/wc204.txi =================================================================== RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v retrieving revision 1.1 diff -p -3 -r1.1 wc204.txi *** wc204.txi 2000/05/30 18:07:38 1.1 --- wc204.txi 2000/06/10 12:51:11 *************** *** 1,7 **** @node Changes in 2.04, , Changes in 2.03, What Changed @section Changes in 2.04 ! Here is a list of changes from DJGPP V2.03 to V2.04. @findex uname AT r{, CPU type detection} ! Ability to report the exact CPU type in @code{uname}. --- 1,40 ---- @node Changes in 2.04, , Changes in 2.03, What Changed @section Changes in 2.04 ! Here is a list of changes from DJGPP V2.03 to V2.04. @findex uname AT r{, CPU type detection} ! Ability to report the exact CPU type in @code{uname}. ! ! @findex _creat AT r{, and FAT32} ! @findex _creatnew AT r{, and FAT32} ! @findex _open AT r{, and FAT32} ! The functions @code{_creat}, @code{_creatnew} and @code{_open} now set ! extended size flag in DOS calls to be able to create files with size up ! to 2^32-1, supported on FAT32 volumes. ! ! @findex llseek AT r{, and FAT32} ! The function @code{llseek} added with type @code{offset_t} to support ! file seeks up to 2^32-2. ! ! @findex statfs AT r{, and FAT32} ! The function @code{statfs} have been made to report correct values > ! 2^31 on FAT32 partitions. ! ! @findex _invent_inode AT r{, and FAT32} ! The function @code{_invent_inode} has been changed to start numbering ! invented inodes from @code{USHRT_MAX+1} to @code{2^28+1}. ! ! @findex _is_cdrom_drive ! @findex _is_ram_drive ! @findex _media_type ! Functions @code{_is_cdrom_drive}, @code{_is_ram_drive} and ! @code{_media_type} has been taken out of @file{mntent.c} and made ! externally callable. ! ! @findex _get_fat_size ! @findex _get_fs_type ! @findex _is_fat32 ! New functions @code{_get_fat_size}, @code{_get_fs_type} and ! @code{_is_fat32} added. ! Index: djgpp/src/libc/compat/mntent/mntent.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/compat/mntent/mntent.c,v retrieving revision 1.5 diff -p -3 -r1.5 mntent.c *** mntent.c 1999/04/19 09:53:30 1.5 --- mntent.c 2000/06/10 12:51:21 *************** get_netredir_entry(int drive_num) *** 368,393 **** } /* - * Return 1 if this drive is a CD-ROM drive, 0 otherwise. Works - * with MSCDEX 2.x, but what about other CD-ROM device drivers? - */ - static int - is_cdrom_drive(int drive_num) - { - __dpmi_regs r; - - r.x.ax = 0x150b; /* CD-ROM Drive Check function */ - r.x.cx = drive_num - 1; /* 0 = A: */ - __dpmi_int(0x2f, &r); - - /* If MSCDEX installed, BX will hold ADADh; AX will be non-zero - if this drive is supported by MSCDEX. */ - if (r.x.bx == 0xadad && r.x.ax != 0) - return 1; - return 0; - } - - /* * 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. */ --- 368,373 ---- *************** cdrom_drive_ready(int drive_num) *** 445,495 **** return 0; } - /* - * Detect a RAM disk. We do this by checking if the number of FAT - * copies (in the Device Parameter Block) is 1, which is typical of - * RAM disks. [This doesn't _have_ to be so, but if it's good - * enough for Andrew Schulman et al (Undocumented DOS, 2nd edition), - * we can use this as well.] - */ - static int - is_ram_drive(int drive_num) - { - __dpmi_regs r; - - r.h.ah = 0x32; /* Get Device Parameter Block function */ - r.h.dl = drive_num; - __dpmi_int(0x21, &r); - - if (r.h.al == 0) - { - /* The pointer to DPB is in DS:BX. The number of FAT copies is at - offset 8 in the DPB. */ - char fat_copies = _farpeekb(dos_mem_base, MK_FOFF(r.x.ds, r.x.bx) + 8); - - return fat_copies == 1; - } - return 0; - } - - /* - * Check if the media in this disk drive is fixed or removable. - * Should only be called after we're sure this ain't CD-ROM or - * RAM disk, since these might fool you with this call. - */ - static int - media_type(int drive_num) - { - __dpmi_regs r; - - r.x.ax = 0x4408; - r.h.bl = drive_num; - __dpmi_int(0x21, &r); - - if (r.x.flags & 1) - return -1; - return r.x.ax; /* returns 1 for fixed disks, 0 for removable */ - } /* Exported library functions. */ --- 425,430 ---- *************** getmntent(FILE *filep) *** 700,710 **** */ if (mnt_type[0] == '?') { ! int disk_type = media_type(drive_number); ! 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. */ --- 635,645 ---- */ if (mnt_type[0] == '?') { ! int disk_type = _media_type(drive_number); ! 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. */ Index: djgpp/src/libc/compat/sys/vfs/statfs.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/compat/sys/vfs/statfs.c,v retrieving revision 1.4 diff -p -3 -r1.4 statfs.c *** statfs.c 1999/08/04 19:58:23 1.4 --- statfs.c 2000/06/10 12:51:21 *************** *** 6,11 **** --- 6,12 ---- #include #include #include + #include #include #include #include *************** *** 13,25 **** #include #include int statfs(const char *path, struct statfs *buf) { __dpmi_regs regs; int drive_number; int cdrom_calls_used = 0; ! int blocks = 0; /* Get the drive number, including the case of magic names like /dev/c/foo. */ --- 14,32 ---- #include #include + #if 0 + #include + #endif + int statfs(const char *path, struct statfs *buf) { __dpmi_regs regs; int drive_number; int cdrom_calls_used = 0; ! long blocks = 0; ! long free = 0; ! long bsize = 0; /* Get the drive number, including the case of magic names like /dev/c/foo. */ *************** statfs(const char *path, struct statfs * *** 46,52 **** if ((regs.x.flags & 1) == 0 && regs.x.bx == 0xadad && regs.x.ax != 0) { unsigned char request_header[0x14]; ! int status, i = 2, bsize = 0; /* Construct the request header for the CD-ROM device driver. */ memset (request_header, 0, sizeof request_header); --- 53,59 ---- 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); *************** statfs(const char *path, struct statfs * *** 91,99 **** if (_farpeekw (_dos_ds, __tb + 8) == 0x100 && _farpeekw (_dos_ds, __tb + 5 + 0x12) == 5) { ! regs.x.ax = 1; /* fake: sectors per cluster */ ! regs.x.cx = bsize; ! regs.x.bx = 0; /* no free space: cannot add data to CD-ROM */ blocks = _farpeekl (_dos_ds, __tb + 1); cdrom_calls_used = 1; } --- 98,105 ---- 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; } *************** statfs(const char *path, struct statfs * *** 113,127 **** errno = ENODEV; return -1; } blocks = regs.x.dx; } /* Fill in the structure */ ! buf->f_bavail = regs.x.bx; ! buf->f_bfree = regs.x.bx; buf->f_blocks = blocks; ! buf->f_bsize = regs.x.cx * regs.x.ax; ! buf->f_ffree = regs.x.bx; buf->f_files = blocks; buf->f_type = 0; buf->f_fsid[0] = drive_number; --- 119,190 ---- errno = ENODEV; return -1; } + bsize = regs.x.cx * regs.x.ax; + free = regs.x.bx; blocks = regs.x.dx; + #if 0 + printf("First: bsize = %ld, free = %ld, blocks = %ld.\n" + , bsize + , free + , blocks + ); + #endif + + if( 7 <= (_get_dos_version(1) >> 8) /* Is FAT32 supported? */ + && _is_fat32(drive_number + 1) /* Is it a FAT32 drive? */ + ) + { + /* 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 ) + { + errno = ENODEV; + return( -1 ); + } + + /* We trust previous int21 call more if free hasn't maxed out. */ + if( free < blocks ) + { + /* Previous bsize is a multiple of this bsize, so the multiplication + and division here is really a rescaling of the previous free + value. */ + free *= bsize; + bsize = _farpeekw (_dos_ds, __tb + 0x2 + 0x2) * + ( _farpeekb (_dos_ds, __tb + 0x2 + 0x4) + 1 ); + free /= bsize; + } + else + { + free = _farpeekw (_dos_ds, __tb + 0x2 + 0x1f) + + 65536 * _farpeekw (_dos_ds, __tb + 0x2 + 0x21); + bsize = _farpeekw (_dos_ds, __tb + 0x2 + 0x2) * + ( _farpeekb (_dos_ds, __tb + 0x2 + 0x4) + 1 ); + } + + blocks = _farpeekl( _dos_ds, __tb + 0x2 + 0x2d); + #if 0 + printf("Second: bsize = %ld, free = %ld, blocks = %ld.\n" + , bsize + , free + , blocks + ); + #endif + } } /* 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; Index: djgpp/src/libc/compat/unistd/llseek.c =================================================================== RCS file: llseek.c diff -N llseek.c *** /dev/null Tue May 5 16:32:27 1998 --- llseek.c Sat Jun 10 08:51:22 2000 *************** *** 0 **** --- 1,47 ---- + /* + * File llseek.c. + * + * Copyright (C) 2000 Martin Strömberg . + * + * This software may be used freely so long as this copyright notice is + * left intact. There is no warranty on this software. + * + */ + + #include + #include + #include + #include + #include + #include + + + offset_t + llseek( int handle, offset_t offset, int whence ) + { + __dpmi_regs r; + + __FSEXT_Function *func = __FSEXT_get_function(handle); + if( func ) + { + int rv; + if( func(__FSEXT_llseek, &rv, &handle) ) + { + return rv; + } + } + + r.h.ah = 0x42; + r.h.al = whence; + r.x.bx = handle; + r.x.cx = offset >> 16; + r.x.dx = offset & 0xffff; + __dpmi_int(0x21, &r); + if( r.x.flags & 1 ) + { + errno = __doserr_to_errno(r.x.ax); + return -1; + } + return( ( ( (unsigned)r.x.dx ) << 16) + r.x.ax ); + } + Index: djgpp/src/libc/compat/unistd/llseek.txh =================================================================== RCS file: llseek.txh diff -N llseek.txh *** /dev/null Tue May 5 16:32:27 1998 --- llseek.txh Sat Jun 10 08:51:22 2000 *************** *** 0 **** --- 1,66 ---- + @ignore + * File llseek.txh. + * + * Copyright (C) 2000 Martin Strömberg . + * + * This software may be used freely so long as this copyright notice is + * left intact. There is no warranty on this software. + * + @end ignore + + @node llseek, io + @subheading Syntax + + @example + #include + + offset_t llseek(int fd, offset_t offset, int whence); + @end example + + @subheading Description + + This function moves the file pointer for @var{fd} according to + @var{whence}: + + @table @code + + @item SEEK_SET + + The file pointer is moved to the offset specified. + + @item SEEK_CUR + + The file pointer is moved relative to its current position. + + @item SEEK_END + + The file pointer is moved to a position @var{offset} bytes from the end + of the file. The offset is usually nonpositive in this case. + + @end table + + @var{offset} is of type long long, thus enabling you to seek with + offsets as large as ~2^63 (FAT16 limits this to ~2^31; FAT32 limits + this to 2^32-2). + + @subheading Return Value + + The new offset is returned. Note that due to limitations in the + underlying DOS implementation the offset wraps around to 0 at offset + 2^32. -1 means the call failed. + + @subheading Portability + + @portability !ansi, !posix + + @subheading Example + + @example + long long ret; + + ret = llseek(fd, (1<<32), SEEK_SET); /* Now ret equals 0 (unfortunately). */ + ret = llseek(fd, -1, SEEK_CUR); /* Now ret equals 2^32-1 (good!). */ + ret = llseek(fd, 0, SEEK_SET); /* Now ret equals 0 (good!). */ + ret = llseek(fd, -1, SEEK_CUR); /* Now ret equals 2^32-1 (bad). */ + @end example + Index: djgpp/src/libc/compat/unistd/makefile =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/compat/unistd/makefile,v retrieving revision 1.2 diff -p -3 -r1.2 makefile *** makefile 1998/06/28 21:53:24 1.2 --- makefile 2000/06/10 12:51:22 *************** SRC += getdtabl.c *** 10,15 **** --- 10,16 ---- SRC += gethostn.c SRC += getpages.c SRC += getwd.c + SRC += llseek.c SRC += nice.c SRC += sync.c SRC += truncate.c Index: djgpp/src/libc/dos/dos/getfatsz.c =================================================================== RCS file: getfatsz.c diff -N getfatsz.c *** /dev/null Tue May 5 16:32:27 1998 --- getfatsz.c Sat Jun 10 08:51:23 2000 *************** *** 0 **** --- 1,133 ---- + /* + * File getfatsz.c. + * + * Copyright (C) 2000 Martin Strömberg . + * + * 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 . + * + */ + + #include + #include + #include + #include + #include + + /* Returns number of bits in FAT; -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; + char file_system_string[9]; + + /* First check that we have a FAT file system. */ + if( _get_fs_type( drive, file_system_string ) + || file_system_string[0] != 'F' + || file_system_string[1] != 'A' + || file_system_string[2] != 'T' ) + { + errno = ENOSYS; + return( -1 ); + } + + 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); + } + } + + /* +7 is offset in RBIL, the changing number is offset according to + Microsnoft's document and -11 is a corrective offset (the Microsnoft + document starts its offset counting 11 to early, freely mixing in the + boot sector). */ + 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 ) + { + size = 16; + } + else + { + size = 32; + } + + #if 0 + #include + 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 ); + + } + Index: djgpp/src/libc/dos/dos/getfatsz.txh =================================================================== RCS file: getfatsz.txh diff -N getfatsz.txh *** /dev/null Tue May 5 16:32:27 1998 --- getfatsz.txh Sat Jun 10 08:51:24 2000 *************** *** 0 **** --- 1,64 ---- + @ignore + * Copyright (C) 2000 Martin Strömberg . + * + * This software may be used freely so long as this copyright notice is + * left intact. There is no warranty on this software. + * + @end ignore + + @node _get_fat_size, file system + @subheading Syntax + + @example + #include + + int _get_fat_size( const int drive ); + @end example + + @subheading Description + + This function tries to determine the number bits used to enumerate the + clusters by the FAT on drive number @var{drive}. 1 == A:, 2 == B:, + etc., 0 == default drive. + + This function will not succeed on DOS version < 4, setting + @code{errno} to @code{ENOSYS}. It is also known to have trouble + detecting the file system type of disks formatted with a later version + of DOS than the version it is run on. E. g. floppies with LFN + entries can cause this function to fail or detect the fat size as 16 + if used in plain DOS. + + If you are looking for a function that is able to detect other file + systems, perhaps the function @xref{_get_fs_type} can be of use. + + @subheading Return Value + + The number of bits used by the FAT (12, 16 or 32). 0 if the drive was + formatted with FAT but of unknown size (NT reports that on FAT16). + -1 on error. + + + @subheading Portability + + @portability !ansi, !posix + + @subheading Example + + @example + #include + #include + + int main(void) + @{ + int size; + + size = _get_fat_size( 'C' - 'A' + 1 ); + if( 0 <= size ) + @{ + printf("The size of FAT on C: is %d bits.\n", size); + @} + + exit(0); + @} + + @end example Index: djgpp/src/libc/dos/dos/getfstyp.c =================================================================== RCS file: getfstyp.c diff -N getfstyp.c *** /dev/null Tue May 5 16:32:27 1998 --- getfstyp.c Sat Jun 10 08:51:24 2000 *************** *** 0 **** --- 1,62 ---- + /* + * File getfstyp.c. + * + * Copyright (C) 2000 Martin Strömberg . + * + * This software may be used freely so long as this copyright notice is + * left intact. There is no warranty on this software. + * + */ + + #include + #include + #include + #include + #include + #include + + /* 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 chars 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 ); + + } Index: djgpp/src/libc/dos/dos/getfstyp.txh =================================================================== RCS file: getfstyp.txh diff -N getfstyp.txh *** /dev/null Tue May 5 16:32:27 1998 --- getfstyp.txh Sat Jun 10 08:51:24 2000 *************** *** 0 **** --- 1,69 ---- + @ignore + * Copyright (C) 2000 Martin Strömberg . + * + * This software may be used freely so long as this copyright notice is + * left intact. There is no warranty on this software. + * + @end ignore + + @node _get_fs_type, file system + @subheading Syntax + + @example + #include + + int _get_fs_type( const int drive, + char *const result_str ); + @end example + + @subheading Description + + This function tries to extract the file system type of the drive + number @var{drive}, 1 == A:, 2 == B:, etc., 0 == default drive. It + does this by calling INT21, AX=0x6900, Get Disk Serial Number (sic!), + which returns, among other things, an eight character field which is + set while formatting the drive. Now, this field can be set to whatever + the formatting program wishes, but so far every FAT formatted drive + has returned a string starting with "FAT". + + If successful the result is put in @var{result_str} which must be at + least 9 characters long. If unsuccessful @code{errno} is set. + + This function will not succeed on DOS version < 4, setting + @code{errno} to @code{ENOSYS}. It is also known to have trouble + detecting the file system type of disks formatted with a later version + of DOS than the version it is run on. E. g. floppies with LFN + entries can cause this function to fail or detect the floppy as + FAT16 if used in plain DOS. + + If you are interested in which kind of FAT file system that is in use + try the function @xref{_get_fat_size} which will reliably detect the + right kind of FAT file system. + + @subheading Return Value + + 0 if the file system type was extracted successfully; otherwise -1. + + @subheading Portability + + @portability !ansi, !posix + + @subheading Example + + @example + #include + #include + + int main(void) + @{ + char buffer[9]; + + if( ! _get_fs_type( 3, buffer ) ) + @{ + printf("The file system on C: is '%s'.\n", buffer); + @} + + exit(0); + @} + + @end example Index: djgpp/src/libc/dos/dos/iscdrom.c =================================================================== RCS file: iscdrom.c diff -N iscdrom.c *** /dev/null Tue May 5 16:32:27 1998 --- iscdrom.c Sat Jun 10 08:51:24 2000 *************** *** 0 **** --- 1,20 ---- + /* Copyright (c) 1995-98 Eli Zaretskii */ + + #include + #include + + int + _is_cdrom_drive(int drive_num) + { + __dpmi_regs r; + + r.x.ax = 0x150b; /* CD-ROM Drive Check function */ + r.x.cx = drive_num - 1; /* 0 = A: */ + __dpmi_int(0x2f, &r); + + /* If MSCDEX installed, BX will hold ADADh; AX will be non-zero + if this drive is supported by MSCDEX. */ + if (r.x.bx == 0xadad && r.x.ax != 0) + return 1; + return 0; + } Index: djgpp/src/libc/dos/dos/iscdrom.txh =================================================================== RCS file: iscdrom.txh diff -N iscdrom.txh *** /dev/null Tue May 5 16:32:27 1998 --- iscdrom.txh Sat Jun 10 08:51:24 2000 *************** *** 0 **** --- 1,45 ---- + @node _is_cdrom_drive, file system + @subheading Syntax + + @example + #include + + int _is_cdrom_drive( const int drive ); + @end example + + @subheading Description + + This function checks if drive number @var{drive} (1 == A:, 2 == B:, + etc.) is a CD-ROM drive. It works with MSCDEX 2.x and Windows 9X + built-in CDFS support. + + @subheading Return Value + + 1 if the drive is a CDROM drive, otherwise 0. + + @subheading Portability + + @portability !ansi, !posix + + @subheading Example + + @example + #include + #include + + int main(void) + @{ + + if( _is_cdrom_drive( 'R' - 'A' + 1 ) ) + @{ + printf("C: is a CDROM drive.\n"); + @} + else + @{ + printf("C: is not a CDROM drive.\n"); + @} + + exit(0); + @} + + @end example Index: djgpp/src/libc/dos/dos/isfat32.c =================================================================== RCS file: isfat32.c diff -N isfat32.c *** /dev/null Tue May 5 16:32:27 1998 --- isfat32.c Sat Jun 10 08:51:24 2000 *************** *** 0 **** --- 1,29 ---- + /* + * This is the file isfat32.c. + * + * Copyright (C) 2000 Martin Strömberg . + * + * This software may be used freely so long as this copyright notice is + * left intact. There is no warranty on this software. + * + */ + + #include + #include + + /* Returns 1 if the drive is formatted with FAT32; 0 otherwise. */ + int + _is_fat32( const int drive /* drive number (1=A:). */ + ) + { + /* Check input. */ + if( 0 <= drive + && drive <= 32 + ) + { + return( _get_fat_size( drive ) == 32 ); + } + + /* Drives that don't exist can't be FAT32. */ + return( 0 ); + } Index: djgpp/src/libc/dos/dos/isfat32.txh =================================================================== RCS file: isfat32.txh diff -N isfat32.txh *** /dev/null Tue May 5 16:32:27 1998 --- isfat32.txh Sat Jun 10 08:51:24 2000 *************** *** 0 **** --- 1,55 ---- + @ignore + * Copyright (C) 2000 Martin Strömberg . + * + * This software may be used freely so long as this copyright notice is + * left intact. There is no warranty on this software. + * + @end ignore + + @node _is_fat32, file system + @subheading Syntax + + @example + #include + + int _is_fat32( const int drive ); + @end example + + @subheading Description + + This function checks if drive number @var{drive} (1 == A:, 2 == B:, + etc.) is formatted with FAT32. + + For performance reasons the result is cached, hence if a drive is + reformatted either from or to FAT32 a DJGPP program must be restarted. + + @subheading Return Value + + 1 if the drive is formatted with FAT32, otherwise 0. + + @subheading Portability + + @portability !ansi, !posix + + @subheading Example + + @example + #include + #include + + int main(void) + @{ + + if( _is_fat32( 'C' - 'A' + 1 ) ) + @{ + printf("C: is a FAT32 drive.\n"); + @} + else + @{ + printf("C: is not a FAT32 drive.\n"); + @} + + exit(0); + @} + + @end example Index: djgpp/src/libc/dos/dos/isramdri.c =================================================================== RCS file: isramdri.c diff -N isramdri.c *** /dev/null Tue May 5 16:32:27 1998 --- isramdri.c Sat Jun 10 08:51:25 2000 *************** *** 0 **** --- 1,46 ---- + /* Copyright (c) 1995-98 Eli Zaretskii */ + + #include + #include + #include + #include + + /* Macro to convert a segment and an offset to a "far offset" suitable + for _farxxx() functions of DJGPP. */ + #ifndef MK_FOFF + #define MK_FOFF(s,o) ((int)((((unsigned long)(unsigned short)(s)) << 4) + \ + (unsigned short)(o))) + #endif + + /* + Description: + + This function checks if drive number @var{drive} (1 == A:, 2 == B:, + etc.) is a RAM disk. It is done by checking if the number of FAT + copies (in the Device Parameter Block) is 1, which is typical of + RAM disks. This doesn't @emph{have} to be so, but if it's good + enough for Andrew Schulman et al (@cite{Undocumented DOS, 2nd + edition}), we can use this as well. + + Return Value: + 1 if the drive is a RAM drive, otherwise 0. + */ + int + _is_ram_drive(int drive_num) + { + __dpmi_regs r; + + r.h.ah = 0x32; /* Get Device Parameter Block function */ + r.h.dl = drive_num; + __dpmi_int(0x21, &r); + + if (r.h.al == 0) + { + /* The pointer to DPB is in DS:BX. The number of FAT copies is at + offset 8 in the DPB. */ + char fat_copies = _farpeekb(_dos_ds, MK_FOFF(r.x.ds, r.x.bx) + 8); + + return fat_copies == 1; + } + return 0; + } Index: djgpp/src/libc/dos/dos/isramdri.txh =================================================================== RCS file: isramdri.txh diff -N isramdri.txh *** /dev/null Tue May 5 16:32:27 1998 --- isramdri.txh Sat Jun 10 08:51:25 2000 *************** *** 0 **** --- 1,37 ---- + @node _is_ram_drive, file system + @subheading Syntax + + @example + #include + + int _is_ram_drive( const int drive ); + @end example + + @subheading Description + + This function checks if drive number @var{drive} (1 == A:, 2 == B:, + etc.) is a RAM disk. It is done by checking if the number of FAT + copies (in the Device Parameter Block) is 1, which is typical of + RAM disks. This doesn't @emph{have} to be so, but if it's good + enough for Andrew Schulman et al (@cite{Undocumented DOS, 2nd + edition}), we can use this as well. + + @subheading Return Value + + 1 if the drive is a RAM drive, otherwise 0. + + @subheading Portability + + @portability !ansi, !posix + + @subheading Example + + @example + #include + #include + + int i = 4; + + printf("%c: is a RAM drive: %d.\n", 'A' - 1 + i, _is_ram_drive( i ) ) + + @end example Index: djgpp/src/libc/dos/dos/makefile =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/dos/dos/makefile,v retrieving revision 1.1 diff -p -3 -r1.1 makefile *** makefile 1995/06/18 05:50:38 1.1 --- makefile 2000/06/10 12:51:25 *************** SRC += getdate.c *** 10,15 **** --- 10,17 ---- SRC += getdfree.c SRC += getdinfo.c SRC += getdos_v.c + SRC += getfatsz.c + SRC += getfstyp.c SRC += getftime.c SRC += gettime.c SRC += gettimeo.c *************** SRC += int86.c *** 17,22 **** --- 19,28 ---- SRC += int86x.S SRC += intdos.c SRC += intdosx.c + SRC += iscdrom.c + SRC += isfat32.c + SRC += isramdri.c + SRC += mediatyp.c SRC += osflavor.c SRC += osmajor.c SRC += osminor.c Index: djgpp/src/libc/dos/dos/mediatyp.c =================================================================== RCS file: mediatyp.c diff -N mediatyp.c *** /dev/null Tue May 5 16:32:27 1998 --- mediatyp.c Sat Jun 10 08:51:25 2000 *************** *** 0 **** --- 1,18 ---- + /* Copyright (c) 1995-98 Eli Zaretskii */ + + #include + #include + + int + _media_type(int drive_num) + { + __dpmi_regs r; + + r.x.ax = 0x4408; + r.h.bl = drive_num; + __dpmi_int(0x21, &r); + + if (r.x.flags & 1) + return -1; + return r.x.ax; /* returns 1 for fixed disks, 0 for removable */ + } Index: djgpp/src/libc/dos/dos/mediatyp.txh =================================================================== RCS file: mediatyp.txh diff -N mediatyp.txh *** /dev/null Tue May 5 16:32:27 1998 --- mediatyp.txh Sat Jun 10 08:51:25 2000 *************** *** 0 **** --- 1,48 ---- + @node _media_type, file system + @subheading Syntax + + @example + #include + + int _media_type( const int drive ); + @end example + + @subheading Description + + This function checks if drive number @var{drive} (1 == A:, 2 == B:, + etc., 0 == default drive) is fixed or removable. + + @code{_media_type} should only be called after you are sure the drive + isn't a CD-ROM or a RAM disk, since these might fool you with this + call. + + @subheading Return Value + + 1 if the drive is a fixed disk, 0 if it is removable. -1 on error. + + @subheading Portability + + @portability !ansi, !posix + + @subheading Example + + @example + #include + #include + + int main(void) + @{ + + if( _media_type( 'C' - 'A' + 1 ) ) + @{ + printf("C: is (probably) a hard drive.\n"); + @} + else + @{ + printf("C: is (probably) a removable drive.\n"); + @} + + exit(0); + @} + + @end example Index: djgpp/src/libc/dos/io/_creat.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/dos/io/_creat.c,v retrieving revision 1.3 diff -p -3 -r1.3 _creat.c *** _creat.c 1996/08/31 22:09:32 1.3 --- _creat.c 2000/06/10 12:51:26 *************** *** 6,11 **** --- 6,12 ---- #include #include #include + #include #include #include *************** _creat(const char* filename, int attrib) *** 25,42 **** if (__FSEXT_call_open_handlers(__FSEXT_creat, &rv, &filename)) return rv; - _put_path(filename); if(use_lfn) { r.x.ax = 0x716c; ! r.x.bx = 0x0002; /* open r/w */ r.x.dx = 0x0012; /* Create, truncate if exists */ r.x.si = __tb_offset; } else { r.h.ah = 0x3c; r.x.dx = __tb_offset; } r.x.cx = attrib; r.x.ds = __tb_segment; __dpmi_int(0x21, &r); if(r.x.flags & 1) { --- 26,51 ---- if (__FSEXT_call_open_handlers(__FSEXT_creat, &rv, &filename)) return rv; if(use_lfn) { r.x.ax = 0x716c; ! r.x.bx = 0x1002; /* Open r/w with extended size. */ r.x.dx = 0x0012; /* Create, truncate if exists */ r.x.si = __tb_offset; + } else if(7 <= (_get_dos_version(1) >> 8)) { + r.x.ax = 0x6c00; + r.x.bx = 0x1002; /* Open r/w with FAT32 extended size. */ + /* FAT32 extended size flag doesn't help on WINDOZE 4.1 (98). It + seems it has a bug which only lets you create these big files + if LFN is enabled. */ + r.x.dx = 0x0012; /* Create, truncate if exists */ + r.x.si = __tb_offset; } else { r.h.ah = 0x3c; r.x.dx = __tb_offset; } r.x.cx = attrib; r.x.ds = __tb_segment; + _put_path(filename); __dpmi_int(0x21, &r); if(r.x.flags & 1) { Index: djgpp/src/libc/dos/io/_creat.txh =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/dos/io/_creat.txh,v retrieving revision 1.3 diff -p -3 -r1.3 _creat.txh *** _creat.txh 1999/06/20 08:53:34 1.3 --- _creat.txh 2000/06/10 12:51:26 *************** int _creat(const char *path, int attrib) *** 10,23 **** @subheading Description This is a direct connection to the MS-DOS creat function call, int 0x21, ! %ah = 0x3c. The file is set to binary mode. This function can be ! hooked by the @dfn{File System Extensions}, see @ref{File System ! Extensions}. If you don't want this, you should use @code{_dos_creat} ! (@pxref{_dos_creat}) or @code{_dos_creatnew} (@pxref{_dos_creatnew}). On platforms where the LFN API (@pxref{_use_lfn, LFN}) is available, @code{_creat} calls function 0x716C of Interrupt 21h, to support long file names. @subheading Return Value --- 10,32 ---- @subheading Description This is a direct connection to the MS-DOS creat function call, int 0x21, ! %ah = 0x3c, on versions of DOS earlier than 7.0. On DOS version ! 7.0 or later @code{_creat} calls function int 0x21, %ax = 0x6c00 On platforms where the LFN API (@pxref{_use_lfn, LFN}) is available, @code{_creat} calls function 0x716C of Interrupt 21h, to support long file names. + + On FAT32 file systems file sizes up to 2^32-2 are supported. Note + that WINDOWS 98 has a bug which only lets you create these big files + if LFN is enabled. In plain DOS mode it plainly works. + + The file is set to binary mode. + + This function can be hooked by the @dfn{File System Extensions}, see + @ref{File System Extensions}. If you don't want this, you should use + @code{_dos_creat} (@pxref{_dos_creat}) or @code{_dos_creatnew} + (@pxref{_dos_creatnew}). @subheading Return Value Index: djgpp/src/libc/dos/io/_creat_n.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/dos/io/_creat_n.c,v retrieving revision 1.1 diff -p -3 -r1.1 _creat_n.c *** _creat_n.c 1998/06/28 22:42:16 1.1 --- _creat_n.c 2000/06/10 12:51:26 *************** _creatnew(const char* filename, int attr *** 27,32 **** --- 27,36 ---- _put_path(filename); r.x.bx = + 0x1000 | /* FAT32 extended size. */ + /* FAT32 extended size flag doesn't help on WINDOZE 4.1 (98). It + seems it has a bug which only lets you create these big files + if LFN is enabled. */ 0x2002 | (flags & 0xfff0); /* r/w, no Int 24h, use caller-defined flags */ r.x.dx = 0x0010; /* Create, fail if exists */ r.x.si = __tb_offset; Index: djgpp/src/libc/dos/io/_open.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/dos/io/_open.c,v retrieving revision 1.2 diff -p -3 -r1.2 _open.c *** _open.c 1996/08/31 21:09:32 1.2 --- _open.c 2000/06/10 12:51:26 *************** *** 7,12 **** --- 7,13 ---- #include #include #include + #include #include #include *************** _open(const char* filename, int oflag) *** 26,37 **** if (__FSEXT_call_open_handlers(__FSEXT_open, &rv, &filename)) return rv; - _put_path(filename); if(use_lfn) { r.x.ax = 0x716c; ! r.x.bx = oflag & 0xff; r.x.dx = 1; /* Open existing file */ r.x.si = __tb_offset; } else { r.h.ah = 0x3d; r.h.al = oflag; --- 27,45 ---- if (__FSEXT_call_open_handlers(__FSEXT_open, &rv, &filename)) return rv; if(use_lfn) { r.x.ax = 0x716c; ! r.x.bx = (oflag & 0xff) | 0x1000; /* 0x1000 is FAT32 extended size. */ r.x.dx = 1; /* Open existing file */ r.x.si = __tb_offset; + } else if(7 <= (_get_dos_version(1) >> 8)) { + r.x.ax = 0x6c00; + r.x.bx = (oflag & 0xff) | 0x1000; /* 0x1000 is FAT32 extended size. */ + /* FAT32 extended size flag doesn't help on WINDOZE 4.1 (98). It + seems it has a bug which only lets you create these big files + if LFN is enabled. */ + r.x.dx = 1; /* Open existing file */ + r.x.si = __tb_offset; } else { r.h.ah = 0x3d; r.h.al = oflag; *************** _open(const char* filename, int oflag) *** 39,44 **** --- 47,53 ---- } r.x.cx = 0; r.x.ds = __tb_segment; + _put_path(filename); __dpmi_int(0x21, &r); if(r.x.flags & 1) { Index: djgpp/src/libc/dos/io/_open.txh =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/dos/io/_open.txh,v retrieving revision 1.3 diff -p -3 -r1.3 _open.txh *** _open.txh 1999/06/20 08:53:34 1.3 --- _open.txh 2000/06/10 12:51:26 *************** int _open(const char *path, int attrib); *** 10,17 **** @subheading Description This is a direct connection to the MS-DOS open function call, int 0x21, ! %ah = 0x3d. (When long file names are supported, @code{_open} calls ! function 0x716c of Int 0x21.) The file is set to binary mode. This function can be hooked by the @dfn{File System Extensions} (@pxref{File System Extensions}). If you don't want this, you should --- 10,25 ---- @subheading Description This is a direct connection to the MS-DOS open function call, int 0x21, ! %ah = 0x3d, on versions of DOS earlier than 7.0. On DOS version 7.0 or ! later @code{_open} calls function int 0x21, %ax = 0x6c00. When long ! file names are supported, @code{_open} calls function 0x716c of Int ! 0x21. ! ! On FAT32 file systems file sizes up to 2^32-2 are supported. Note ! that WINDOWS 98 has a bug which only lets you create these big files ! if LFN is enabled. In plain DOS mode it plainly works. ! ! The file is set to binary mode. This function can be hooked by the @dfn{File System Extensions} (@pxref{File System Extensions}). If you don't want this, you should Index: djgpp/src/libc/posix/sys/stat/xstat.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/xstat.c,v retrieving revision 1.1 diff -p -3 -r1.1 xstat.c *** xstat.c 1996/01/24 03:30:20 1.1 --- xstat.c 2000/06/10 12:51:29 *************** _invent_inode(const char *name, unsigned *** 159,183 **** { static struct name_list *name_list[256]; ! /* If the st_inode is wider than a short int, we will count up ! * from USHRT_MAX+1 and thus ensure there will be no clashes with ! * actual cluster numbers. ! * Otherwise, we must count downward from USHRT_MAX, which could ! * yield two files with identical inode numbers: one from actual ! * DOS cluster number, and another from this function. In the ! * latter case, we still have at least 80 inode numbers before ! * we step into potentially used numbers, because some FAT entries ! * are reserved to mean EOF, unused entry and other special codes, ! * and the FAT itself uses up some clusters which aren't counted. */ ! static int dir = (sizeof(ino_t) > 2 ? 1 : -1); /* INODE_COUNT is declared LONG and not ino_t, because some DOS-based * compilers use short or unsigned short for ino_t. */ ! static long inode_count = (sizeof(ino_t) > 2 ! ? (long)USHRT_MAX + 1L ! : USHRT_MAX); struct name_list *name_ptr, *prev_ptr; const char *p; --- 159,174 ---- { static struct name_list *name_list[256]; ! /* We count upwards from 2^28+1, which can't yield two files with ! * identical inode numbers: FAT16 uses maximum ~2^16 and FAT32 uses ! * maximum ~2^28. */ ! #define INVENTED_INODE_START ( (1 << 28) + 1 ) /* INODE_COUNT is declared LONG and not ino_t, because some DOS-based * compilers use short or unsigned short for ino_t. */ ! static long inode_count = INVENTED_INODE_START; struct name_list *name_ptr, *prev_ptr; const char *p; *************** _invent_inode(const char *name, unsigned *** 187,193 **** if (xstat_count != __bss_count) { xstat_count = __bss_count; ! inode_count = (sizeof(ino_t) > 2 ? (long)USHRT_MAX + 1L : USHRT_MAX); memset (name_list, 0, sizeof name_list); } --- 178,184 ---- if (xstat_count != __bss_count) { xstat_count = __bss_count; ! inode_count = INVENTED_INODE_START; memset (name_list, 0, sizeof name_list); } *************** _invent_inode(const char *name, unsigned *** 219,225 **** { ino_t retval = inode_count; ! inode_count += dir; return retval; } --- 210,216 ---- { ino_t retval = inode_count; ! inode_count++; return retval; } *************** _invent_inode(const char *name, unsigned *** 270,276 **** else name_list[hash] = name_ptr; retval = inode_count; ! inode_count += dir; /* increment or decrement as appropriate */ return retval; } --- 261,267 ---- else name_list[hash] = name_ptr; retval = inode_count; ! inode_count++; /* Increment for next call. */ return retval; } Index: djgpp/tests/libc/dos/dos/getfatsz.c =================================================================== RCS file: getfatsz.c diff -N getfatsz.c *** /dev/null Tue May 5 16:32:27 1998 --- getfatsz.c Sat Jun 10 08:51:37 2000 *************** *** 0 **** --- 1,35 ---- + /* + * File getfatsz.c. + * + * Copyright (C) 2000 Martin Strömberg . + * + * This software may be used freely so long as this copyright notice is + * left intact. There is no warranty on this software. + * + */ + + #include + #include + + 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); + } + + } Index: djgpp/tests/libc/dos/dos/makefile =================================================================== RCS file: /cvs/djgpp/djgpp/tests/libc/dos/dos/makefile,v retrieving revision 1.1 diff -p -3 -r1.1 makefile *** makefile 1995/11/18 21:33:04 1.1 --- makefile 2000/06/10 12:51:37 *************** *** 1,5 **** --- 1,6 ---- TOP=../.. + SRC += getfatsz.c SRC += i86.c SRC += srchpath.c SRC += tn.c