More fixes for files bigger than 2GB

Francois Gouget fgouget@codeweavers.com
Fri May 18 14:16:00 GMT 2012


This is related to PR 13534 but most of it was fixed already.
http://sourceware.org/bugzilla/show_bug.cgi?id=13534

So the best was to test for this now is to archive / unarchive a 4GB 
file on a 32bit system:

$ dd if=/dev/zero of=file4G bs=1M count=4096
4096+0 enregistrements lus
4096+0 enregistrements écrits
4294967296 bytes (4,3 GB) copied, 44,7366 s, 96,0 MB/s
$ ./binutils/ar q ar4G.ar file4G
$ ./binutils/ar tv ar4G.ar
rw-r--r-- 1001/2000      0 May 18 08:29 2012 file4G
$ ./binutils/ar x ar4G.ar
$ ls -l file4G
-rw-r--r-- 1 gouget cw 0 mai 18 14:06 file4G
$ ./binutils/ar p ar4G.ar >file4G
$ ls -l file4G
-rw-r--r-- 1 gouget cw 0 mai 18 14:07 file4G

This issue happens because of the conversion of the st_size values which 
are typically of the off64_t type to size_t variables that can only hold 
unsigned 32bit values. Archive element sizes should only ever be held in 
bfd_size_type variables.

The bucomm.c (print_arelt_descr) chunks fix 'ar tv', the ar.c 
(print_contents) chunks fix 'ar p' and the ar.c (extract_file) chunks 
fix 'ar x'.

I believe the ar.c part was supposed to be included in the previous 
commit for PR 13534 but somehow got left out (the changelog mentions 
ar.c but the commit does not touch it).

I've tried to provide a suitable changelog below but feel free to fix it 
as you see fit.


2012-05-17  Francois Gouget  <fgouget@codeweavers.com>

    PR binutils/13534
        * bucomm.c (print_arelt_descr): Correctly report the archive size field.
        * ar.c (print_contents): Use correct types for archive element sizes.
        (extract_file): Likewise.

diff --git a/binutils/ar.c b/binutils/ar.c
index 13637f4..6ee1dd0 100644
--- a/binutils/ar.c
+++ b/binutils/ar.c
@@ -937,10 +937,10 @@ open_inarch (const char *archive_filename, const char *file)
 static void
 print_contents (bfd *abfd)
 {
-  size_t ncopied = 0;
+  bfd_size_type ncopied = 0;
   char *cbuf = (char *) xmalloc (BUFSIZE);
   struct stat buf;
-  size_t size;
+  bfd_size_type size;
   if (bfd_stat_arch_elt (abfd, &buf) != 0)
     /* xgettext:c-format */
     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
@@ -954,12 +954,12 @@ print_contents (bfd *abfd)
   while (ncopied < size)
     {
 
-      size_t nread;
-      size_t tocopy = size - ncopied;
+      bfd_size_type nread;
+      bfd_size_type tocopy = size - ncopied;
       if (tocopy > BUFSIZE)
 	tocopy = BUFSIZE;
 
-      nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
+      nread = bfd_bread (cbuf, tocopy, abfd);
       if (nread != tocopy)
 	/* xgettext:c-format */
 	fatal (_("%s is not a valid archive"),
@@ -990,9 +990,9 @@ extract_file (bfd *abfd)
 {
   FILE *ostream;
   char *cbuf = (char *) xmalloc (BUFSIZE);
-  size_t nread, tocopy;
-  size_t ncopied = 0;
-  size_t size;
+  bfd_size_type nread, tocopy;
+  bfd_size_type ncopied = 0;
+  bfd_size_type size;
   struct stat buf;
 
   if (bfd_stat_arch_elt (abfd, &buf) != 0)
@@ -1027,7 +1027,7 @@ extract_file (bfd *abfd)
 	if (tocopy > BUFSIZE)
 	  tocopy = BUFSIZE;
 
-	nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
+	nread = bfd_bread (cbuf, tocopy, abfd);
 	if (nread != tocopy)
 	  /* xgettext:c-format */
 	  fatal (_("%s is not a valid archive"),
diff --git a/binutils/bucomm.c b/binutils/bucomm.c
index 86cb6e4..bb3fb3f 100644
--- a/binutils/bucomm.c
+++ b/binutils/bucomm.c
@@ -427,16 +427,18 @@ print_arelt_descr (FILE *file, bfd *abfd, bfd_boolean verbose)
 	  char timebuf[40];
 	  time_t when = buf.st_mtime;
 	  const char *ctime_result = (const char *) ctime (&when);
+	  bfd_size_type size;
 
 	  /* POSIX format:  skip weekday and seconds from ctime output.  */
 	  sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
 
 	  mode_string (buf.st_mode, modebuf);
 	  modebuf[10] = '\0';
+	  size = buf.st_size;
 	  /* POSIX 1003.2/D11 says to skip first character (entry type).  */
-	  fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1,
+	  fprintf (file, "%s %ld/%ld %6" BFD_VMA_FMT "u %s ", modebuf + 1,
 		   (long) buf.st_uid, (long) buf.st_gid,
-		   (long) buf.st_size, timebuf);
+		   size, timebuf);
 	}
     }
 

-- 
Francois Gouget <fgouget@codeweavers.com>              


More information about the Binutils mailing list