Pārlūkot izejas kodu

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>

Steven J. Magnani 14 gadi atpakaļ
vecāks
revīzija
a5961d7344
4 mainītis faili ar 21 papildinājumiem un 15 dzēšanām
  1. 8 8
      src/boot.c
  2. 8 2
      src/io.c
  3. 3 3
      src/io.h
  4. 2 2
      src/mkdosfs.c

+ 8 - 8
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 */

+ 8 - 2
src/io.c

@@ -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)

+ 3 - 3
src/io.h

@@ -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);
 

+ 2 - 2
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 );