From a5961d734410944ed88a7d67d6d27850e2ed065e Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Thu, 21 Jan 2010 16:58:11 +0100 Subject: [PATCH] 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 --- src/boot.c | 16 ++++++++-------- src/io.c | 10 ++++++++-- src/io.h | 6 +++--- src/mkdosfs.c | 4 ++-- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/boot.c b/src/boot.c index c1cdf59..968c868 100644 --- a/src/boot.c +++ b/src/boot.c @@ -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 */ diff --git a/src/io.c b/src/io.c index c4457a8..2ea3fe7 100644 --- a/src/io.c +++ b/src/io.c @@ -29,6 +29,8 @@ /* FAT32, VFAT, Atari format support, and various fixes additions May 1998 * by Roman Hodek */ +#define _LARGEFILE64_SOURCE +#include #include #include #include @@ -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) diff --git a/src/io.h b/src/io.h index 803b6d5..9da453e 100644 --- a/src/io.h +++ b/src/io.h @@ -29,9 +29,9 @@ #include /* 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); diff --git a/src/mkdosfs.c b/src/mkdosfs.c index 7ee4d45..e7a84ed 100644 --- a/src/mkdosfs.c +++ b/src/mkdosfs.c @@ -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 );