delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/12/11/01:52:08

From: "Juan Manuel Guerrero" <ST001906 AT HRZ1 DOT HRZ DOT TU-Darmstadt DOT De>
Organization: Darmstadt University of Technology
To: djgpp-workers AT delorie DOT com
Date: Mon, 11 Dec 2000 07:50:08 +0200
MIME-Version: 1.0
Subject: A bugfix for djtar
X-mailer: Pegasus Mail for Windows (v2.54DE)
Message-ID: <116197B1031@HRZ1.hrz.tu-darmstadt.de>
Reply-To: djgpp-workers AT delorie DOT com

if djtar is invoked as:
  djtar -x foo.gz
djtar will exit with an error message like:

--- !!Directory checksum error!! ---

This is the way it should be.
Please note, that foo.gz is a **pure** gzip file and **not**
a gzip compressed tar file. It does *not* contain a tar archive
and this should be recognized by djtar.
Unfortunately, if the **unziped** file size exceeds 32kB
djtar will crash with the following traceback:

Abort!
Exiting due to signal SIGABRT
Raised at eip=0000f1b6
eax=000ee484 ebx=00000120 ecx=00000000 edx=00012990 esi=00004000 edi=00000001
ebp=000ee530 esp=000ee480 program=J:\DJTAR.EXE
cs: sel=00af  base=8115a000  limit=000fffff
ds: sel=00b7  base=8115a000  limit=000fffff
es: sel=00b7  base=8115a000  limit=000fffff
fs: sel=0087  base=00012990  limit=0000ffff
gs: sel=00c7  base=00000000  limit=0010ffff
ss: sel=00b7  base=8115a000  limit=000fffff
App stack: [000eef54..0006ef54]  Exceptn stack: [0006eea8..0006cf68]

Call frame traceback EIPs:
  0x0000f0d4 ___djgpp_traceback_exit+48
  0x0000f1b6 _raise+94
  0x0000e5fb _abort+27
  0x0001439b __put_path2+55
  0x00014342 __put_path+14
  0x000160eb __chmod+59
  0x00016535 ___file_exists+21
  0x00012ea7 ___open+247
  0x00006f7d _tarread+1817, line 277 of untar.c
  0x00007ced _flush_window+61, line 121 of util.c
  0x000042f0 _inflate_codes+1004, line 588 of inflate.c
  0x00004d01 _inflate_dynamic+1625, line 862 of inflate.c
  0x00004e21 _inflate_block+221, line 907 of inflate.c
  0x00004e96 _inflate+70, line 939 of inflate.c
  0x000077b9 _unzip+185, line 123 of unzip.c
  0x00007374 _tar_gz_read+272, line 350 of untar.c
  0x0000265c _main+1056, line 552 of djtar.c
  0x00009b42 ___crt1_startup+178

32kB is the size of the transfer array used to move the unziped data to tarread().
The reason for this program abort is that the global variable: looking_for_header
is not reset to the appropiate value every time that tarread() is called.
Before tarread() is called for the first time, looking_for_header has been set to 1.
This implies that tarread() checks the complete buf[] contents for tar headers.
If it finds one it will extract all the info needed to create the file form it.
If it does not find a header or the checksum is wrong it will set looking_for_header=0
and return with EOF. Neither the gzip nor the bzip decompression machinery can evaluate
(for different reasons) this return value. Unfortunately tarread() returns EOF if there
is an error condition **and** if there is really EOF. If tarread() is called a second time
with new buf[] contents it will not check for a tar header at all, and will directely call
open() with wrong parameters and producing the above abort.
The patch below will fix this for bzip/gzip compressed files and for all other functions
that may call tarread().
Please note that the goal of the patch is to fix the bug and not to allow the
user to use djtar to unzip plain .gz or .bz2 files.

regards,
Guerrero, Juan Manuel


diff -acprNC5 djgpp.orig/src/utils/djtar/untar.c djgpp/src/utils/djtar/untar.c
*** djgpp.orig/src/utils/djtar/untar.c	Tue Nov 28 21:20:44 2000
--- djgpp/src/utils/djtar/untar.c	Sun Dec 10 18:37:16 2000
*************** typedef struct {
*** 42,51 ****
--- 42,52 ----
    char flags[1];
    char filler[355];
  } TARREC;
  
  static TARREC header;
+ static int error_message_not_printed;
  static int looking_for_header;
  static char *changed_name;
  static int first_block = 1;
  static File_type file_type = DOS_BINARY;
  static long perm, uid, gid, size;
*************** tarread(char *buf, long buf_size)
*** 121,131 ****
          head_csum -= j;
        }
        if (head_csum && !ignore_csum)
        {
          /* Probably corrupted archive.  Bail out.  */
!         fprintf(log_out, "--- !!Directory checksum error!! ---\n");
          bytes_out += buf_size;
          return EOF;
        }
  
        changed_name = get_new_name(header.name, &should_be_written);
--- 122,140 ----
          head_csum -= j;
        }
        if (head_csum && !ignore_csum)
        {
          /* Probably corrupted archive.  Bail out.  */
!         if (error_message_not_printed)
!         {
!           error_message_not_printed = 0; /* Yes, we have printed it. */
!           fprintf(log_out, "--- !!Directory checksum error!! ---\n");
!         }
!         /* We have still not found a header in this buf[],
!            so we MUST continue looking for a header next time
!            that tarread() is called with a new buf[]. */
!         looking_for_header = 1;
          bytes_out += buf_size;
          return EOF;
        }
  
        changed_name = get_new_name(header.name, &should_be_written);
*************** tar_gz_read(char *fname)
*** 342,351 ****
--- 351,361 ----
              fname,
              method > MAX_METHODS ? "corrupted (?)" : zip_description[method],
              method == DEFLATED ? (pkzip ? "PKZip" : "GZip") : "");
  
    bytes_out = 0;
+   error_message_not_printed = 1;
    looking_for_header = 1;
    posn = 0;
  
    if ((*decompressor)(f) != OK)
    {

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019