When compiling a 32-bit version of dosfstools on an x86_64 machine,

the resulting applications report strange errors on "large" (> 2 GiB)
partitions:

  Seek to -2118967808:Invalid argument

  Warning: Filesystem is FAT32 according to fat_length and fat32_length fields,
  but has only 8613 clusters, less than the required minimum of 65525.
  This may lead to problems on some systems.

This appears to be due to compilation with a 32-bit off_t and lseek() library
function.

Use lseek64 for positioning, and change some suspect uses of off_t to loff_t.

Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
This commit is contained in:
Steven J. Magnani 2010-01-21 16:58:11 +01:00 committed by Daniel Baumann
parent bbb25bf11a
commit a5961d7344
4 changed files with 21 additions and 15 deletions

View File

@ -167,7 +167,7 @@ static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss)
fs->backupboot_start = bbs*lss;
b->backup_boot = CT_LE_W(bbs);
fs_write(fs->backupboot_start,sizeof(*b),b);
fs_write((off_t)offsetof(struct boot_sector,backup_boot),
fs_write((loff_t)offsetof(struct boot_sector,backup_boot),
sizeof(b->backup_boot),&b->backup_boot);
printf( "Created backup of boot sector in sector %d\n", bbs );
return;
@ -242,9 +242,9 @@ static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss)
if (s != CF_LE_W(b->backup_boot)) break;
if (s > 0 && s < CF_LE_W(b->reserved)) {
init_fsinfo(&i);
fs_write((off_t)s*lss,sizeof(i),&i);
fs_write((loff_t)s*lss,sizeof(i),&i);
b->info_sector = CT_LE_W(s);
fs_write((off_t)offsetof(struct boot_sector,info_sector),
fs_write((loff_t)offsetof(struct boot_sector,info_sector),
sizeof(b->info_sector),&b->info_sector);
if (fs->backupboot_start)
fs_write(fs->backupboot_start+
@ -299,7 +299,7 @@ void read_boot(DOS_FS *fs)
unsigned total_sectors;
unsigned short logical_sector_size, sectors;
unsigned fat_length;
off_t data_size;
loff_t data_size;
fs_read(0,sizeof(b),&b);
logical_sector_size = GET_UNALIGNED_W(b.sector_size);
@ -321,17 +321,17 @@ void read_boot(DOS_FS *fs)
total_sectors = sectors ? sectors : CF_LE_L(b.total_sect);
if (verbose) printf("Checking we can access the last sector of the filesystem\n");
/* Can't access last odd sector anyway, so round down */
fs_test((off_t)((total_sectors & ~1)-1)*(off_t)logical_sector_size,
fs_test((loff_t)((total_sectors & ~1)-1)*(loff_t)logical_sector_size,
logical_sector_size);
fat_length = CF_LE_W(b.fat_length) ?
CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length);
fs->fat_start = (off_t)CF_LE_W(b.reserved)*logical_sector_size;
fs->root_start = ((off_t)CF_LE_W(b.reserved)+b.fats*fat_length)*
fs->fat_start = (loff_t)CF_LE_W(b.reserved)*logical_sector_size;
fs->root_start = ((loff_t)CF_LE_W(b.reserved)+b.fats*fat_length)*
logical_sector_size;
fs->root_entries = GET_UNALIGNED_W(b.dir_entries);
fs->data_start = fs->root_start+ROUND_TO_MULTIPLE(fs->root_entries <<
MSDOS_DIR_BITS,logical_sector_size);
data_size = (off_t)total_sectors*logical_sector_size-fs->data_start;
data_size = (loff_t)total_sectors*logical_sector_size-fs->data_start;
fs->clusters = data_size/fs->cluster_size;
fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */
fs->fsinfo_start = 0; /* no FSINFO structure */

View File

@ -29,6 +29,8 @@
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#define _LARGEFILE64_SOURCE
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -60,8 +62,7 @@ unsigned device_no;
#ifdef __DJGPP__
#include "volume.h" /* DOS lowlevel disk access functions */
#undef llseek
static loff_t llseek( int fd, loff_t offset, int whence )
loff_t llseek(int fd, loff_t offset, int whence)
{
if ((whence != SEEK_SET) || (fd == 4711)) return -1; /* only those supported */
return VolumeSeek(offset);
@ -70,6 +71,11 @@ static loff_t llseek( int fd, loff_t offset, int whence )
#define close CloseVolume
#define read(a,b,c) ReadVolume(b,c)
#define write(a,b,c) WriteVolume(b,c)
#else
loff_t llseek(int fd, loff_t offset, int whence)
{
return (loff_t) lseek64(fd, (off64_t)offset, whence);
}
#endif
void fs_open(char *path,int rw)

View File

@ -29,9 +29,9 @@
#include <sys/types.h> /* for loff_t */
/* In earlier versions, an own llseek() was used, but glibc lseek() is
* sufficient (or even better :) for 64 bit offsets in the meantime */
#define llseek lseek
loff_t llseek(int fd, loff_t offset, int whence);
/* lseek() analogue for large offsets. */
void fs_open(char *path,int rw);

View File

@ -538,7 +538,7 @@ valid_offset (int fd, loff_t offset)
static unsigned long long
count_blocks (char *filename)
{
off_t high, low;
loff_t high, low;
int fd;
if ((fd = open (filename, O_RDONLY)) < 0)
@ -1731,7 +1731,7 @@ main (int argc, char **argv)
die ("unable to open %s");
}
else {
off_t offset = blocks*BLOCK_SIZE - 1;
loff_t offset = blocks*BLOCK_SIZE - 1;
char null = 0;
/* create the file */
dev = open( device_name, O_EXCL|O_RDWR|O_CREAT|O_TRUNC, 0666 );