delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/08/15/06:38:19

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: Tue, 15 Aug 2000 12:33:53 +0200
MIME-Version: 1.0
Subject: small patch for unzip32
X-mailer: Pegasus Mail for Windows (v2.54DE)
Message-ID: <C72A0C6365E@HRZ1.hrz.tu-darmstadt.de>
Reply-To: djgpp-workers AT delorie DOT com

unzip32 has at least one bug and one misfeature
that appears when running unzip on plain dos.
1) the bug:
   The following path:
      .foo/bar.1.2.3
   will be converted into:
      _.foo/bar_foo_2.3
2) the misfeature:
   The following filename:
      verylongfile_name
   will be converted into:
      verylong.name
The bug is the insertion of the directory name into
the file name if the directory name starts with a dot.
The misfeature is the replacement of the last underscore
in a file name into a dot.
Both issues have their origin in the same algorithmus
in function mapname and map2fat in file: msdos/msdos.c.
The function of the algorithmus is to convert multiple
dot file names into valid plain dos file names. The
shortcomming of this algorithmus is not worth to be
explained. I have replaced it with a very simple one
that will do the right thing.
The only thing worth to be known is that the old renaming
algorithmus supposedly converted a file name with multiple
dots into a file name with only one dot by replaceing every
dot in the file name with an underscore except for the last one.
The simple algorithmus will do the same but this time without
errors. This means: no user visible changes.
I have also added a minor test for checking that file names
do not match MSDOS device names. This test is similar to
the one in tar, djtar and cpio.
The goal of this patch is to fix the bugs without introducing
user visible changes. The goal is *not* to convert unzip into
an DJGPP specific utility. So do not expect renamings like:
  Makefile.am.in -> Makefile.am-in
etc.

The patch is based on unzip 5.41 (latest stable release). I have
used this modified version for a month and i had no difficulties.
I have compiled the package, compressed the coff image with upx
and bound it with PMODE. If this new binary is wanted, let me know
and i will upload it to simtel.

Comments, suggestions, etc are welcome before a send a similar patch
to the InfoZip maintainers.

Regards,
Guerrero, Juan Manuel

diff -acrpNC5 unzip-5.41/msdos/msdos.c unzip-5.41-/msdos/msdos.c
*** unzip-5.41/msdos/msdos.c	Sat Apr 15 00:13:26 2000
--- unzip-5.41-djgpp/msdos/msdos.c	Sun Jul 9 00:23:24 2000
*************** int mapname(__G__ renamed)   /*  truncat
*** 410,426 ****
      char pathcomp[FILNAMSIZ];      /* path-component buffer */
      char *pp, *cp=(char *)NULL;    /* character pointers */
      char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */
  #ifdef MAYBE_PLAIN_FAT
      char *last_dot=(char *)NULL;   /* last dot not converted to underscore */
-     int dotname = FALSE;           /* path component begins with dot? */
  # ifdef USE_LFN
      int use_lfn = USE_LFN;         /* file system supports long filenames? */
  # endif
  #endif
      int error = 0;
      register unsigned workch;      /* hold the character being tested */
  
  
  /*---------------------------------------------------------------------------
      Initialize various pointers and counters and stuff.
    ---------------------------------------------------------------------------*/
--- 410,426 ----
      char pathcomp[FILNAMSIZ];      /* path-component buffer */
      char *pp, *cp=(char *)NULL;    /* character pointers */
      char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */
  #ifdef MAYBE_PLAIN_FAT
      char *last_dot=(char *)NULL;   /* last dot not converted to underscore */
  # ifdef USE_LFN
      int use_lfn = USE_LFN;         /* file system supports long filenames? */
  # endif
  #endif
      int error = 0;
      register unsigned workch;      /* hold the character being tested */
+     struct stat pathcomp_buffer;   /* for the device name check */
  
  
  /*---------------------------------------------------------------------------
      Initialize various pointers and counters and stuff.
    ---------------------------------------------------------------------------*/
*************** int mapname(__G__ renamed)   /*  truncat
*** 529,559 ****
                      *pp++ = (char)workch;
                      break;
                  }
  # endif
                  if (pp == pathcomp) {     /* nothing appended yet... */
!                     if (*cp == '/') {     /* don't bother appending a "./" */
!                         ++cp;             /*  component to the path:  skip */
!                         break;            /*  to next char after the '/' */
!                     } else if (*cp == '.' && cp[1] == '/') {   /* "../" */
!                         *pp++ = '.';      /* add first dot, unchanged... */
!                         ++cp;             /* skip second dot, since it will */
!                     } else {              /*  be "added" at end of if-block */
!                         *pp++ = '_';      /* FAT doesn't allow null filename */
!                         dotname = TRUE;   /*  bodies, so map .exrc -> _.exrc */
!                     }                     /*  (extra '_' now, "dot" below) */
!                 } else if (dotname) {     /* found a second dot, but still */
!                     dotname = FALSE;      /*  have extra leading underscore: */
!                     *pp = '\0';           /*  remove it by shifting chars */
!                     pp = pathcomp + 1;    /*  left one space (e.g., .p1.p2: */
!                     while (pp[1]) {       /*  __p1 -> _p1_p2 -> _p1.p2 when */
!                         *pp = pp[1];      /*  finished) [opt.:  since first */
!                         ++pp;             /*  two chars are same, can start */
!                     }                     /*  shifting at second position] */
                  }
-                 last_dot = pp;    /* point at last dot so far... */
-                 *pp++ = '_';      /* convert dot to underscore for now */
                  break;
  #endif /* MAYBE_PLAIN_FAT */
  
              case ';':             /* start of VMS version? */
                  lastsemi = pp;
--- 529,550 ----
                      *pp++ = (char)workch;
                      break;
                  }
  # endif
                  if (pp == pathcomp) {     /* nothing appended yet... */
!                     if (*cp == '/')       /* don't bother appending a "./" component to */
!                         ++cp;             /* the path and skip to next char after the '/' */
!                     else if (*cp == '.' && cp[1] == '/') {   /* "../" */
!                         *pp++ = '.';      /*  add the first dot, */
!                         *pp++ = '.';      /*  add the second dot */
!                         ++cp;             /*  and move to the directory separator */
!                     } else                /* FAT doesn't allow null filename */
!                         *pp++ = '_';      /*  bodies, so map .exrc -> _exrc */
!                 } else {                  /* found a second dot in the file name */
!                     last_dot = pp;        /*  point at last dot so far and */
!                     *pp++ = '_';          /*  convert dot to underscore for now */
                  }
                  break;
  #endif /* MAYBE_PLAIN_FAT */
  
              case ';':             /* start of VMS version? */
                  lastsemi = pp;
*************** int mapname(__G__ renamed)   /*  truncat
*** 588,597 ****
--- 579,604 ----
          } /* end switch */
      } /* end while loop */
  
      *pp = '\0';                   /* done with pathcomp:  terminate it */
  
+ /*---------------------------------------------------------------------------
+     Put an underscore in front of the file name if the file name is a
+     DOS/WINDOWS device name like CON.*, AUX.*, PRN.*, etc. Trying to
+     extract such a file would fail at best and wedge us at worst.
+   ---------------------------------------------------------------------------*/
+ 
+     while (stat (pathcomp, &pathcomp_buffer) == 0 && S_ISCHR (pathcomp_buffer.st_mode)) {
+         int i;
+ 
+         /* Prepend a '_'.  */
+         for (i = pp - pathcomp; i > -1; i--)
+             pathcomp[i + 1] = pathcomp[i];
+         pathcomp[0] = '_';
+         pp++;
+     }
+ 
      /* if not saving them, remove VMS version numbers (appended ";###") */
      if (!uO.V_flag && lastsemi) {
  #ifndef MAYBE_PLAIN_FAT
          pp = lastsemi + 1;
  #else
*************** static void map2fat(pathcomp, last_dot)
*** 690,721 ****
      char *pathcomp, *last_dot;
  {
      char *pEnd = pathcomp + strlen(pathcomp);
  
  /*---------------------------------------------------------------------------
!     Case 1:  filename has no dot, so figure out if we should add one.  Note
!     that the algorithm does not try to get too fancy:  if there are no dots
!     already, the name either gets truncated at 8 characters or the last un-
!     derscore is converted to a dot (only if more characters are saved that
!     way).  In no case is a dot inserted between existing characters.
  
                GRR:  have problem if filename is volume label??
  
    ---------------------------------------------------------------------------*/
  
!     if (last_dot == (char *)NULL) {   /* no dots:  check for underscores... */
!         char *plu = strrchr(pathcomp, '_');   /* pointer to last underscore */
! 
!         if (plu == (char *)NULL) {  /* no dots, no underscores:  truncate at */
!             if (pEnd > pathcomp+8)  /* 8 chars (could insert '.' and keep 11) */
!                 *(pEnd = pathcomp+8) = '\0';
!         } else if (MIN(plu - pathcomp, 8) + MIN(pEnd - plu - 1, 3) > 8) {
!             last_dot = plu;       /* be lazy:  drop through to next if-block */
!         } else if ((pEnd - pathcomp) > 8)    /* more fits into just basename */
!             pathcomp[8] = '\0';    /* than if convert last underscore to dot */
          /* else whole thing fits into 8 chars or less:  no change */
-     }
  
  /*---------------------------------------------------------------------------
      Case 2:  filename has dot in it, so truncate first half at 8 chars (shift
      extension if necessary) and second half at three.
    ---------------------------------------------------------------------------*/
--- 697,718 ----
      char *pathcomp, *last_dot;
  {
      char *pEnd = pathcomp + strlen(pathcomp);
  
  /*---------------------------------------------------------------------------
!     Case 1:  filename has no dot, so never insert one. On MS-DOS, the meaning
!     and function of an extension is different compared with other OSs, so NEVER
!     convert a file without extension in one with extension.
  
                GRR:  have problem if filename is volume label??
  
    ---------------------------------------------------------------------------*/
  
!     if (last_dot == (char *)NULL)  /* no dots in file name */
!         if (pEnd > pathcomp+8)     /* truncate at 8 chars, */
!             pathcomp[8] = '\0';    /* if needed */
          /* else whole thing fits into 8 chars or less:  no change */
  
  /*---------------------------------------------------------------------------
      Case 2:  filename has dot in it, so truncate first half at 8 chars (shift
      extension if necessary) and second half at three.
    ---------------------------------------------------------------------------*/
diff -acrpNC5 unzip-5.41/process.c unzip-5.41-/process.c
*** unzip-5.41/process.c	Sat Apr 15 00:33:06 2000
--- unzip-5.41-djgpp/process.c	Sun Jul 9 00:26:28 2000
*************** int process_zipfiles(__G)    /* return P
*** 215,225 ****
--- 215,234 ----
      {
          char *p;
          G.tz_is_valid = VALID_TIMEZONE(p);
  #  ifndef SFX
          if (!G.tz_is_valid) {
+ #   ifndef __DJGPP__
+      /*
+         This is DJGPP specific:
+         TZ is usualy not defined in the AUTOEXEC.BAT of an average user.
+         Issueing continuously this warning may confuse most of the newbies.
+         All this means:
+         check for TZ, use it if available but do not complain if not available.
+      */
              Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ)));
+ #   endif
              error_in_archive = error = PK_WARN;
          }
  #  endif /* !SFX */
      }
  #endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */

- Raw text -


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