home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / unzip / part07 < prev    next >
Internet Message Format  |  1994-09-19  |  72KB

  1. From: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
  2. Newsgroups: comp.sources.misc
  3. Subject: v44i072:  unzip - Info-ZIP portable UnZip, version 5.12, Part07/20
  4. Date: 18 Sep 1994 23:15:13 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <35j38h$qnk@sparky.sterling.com>
  9. X-Md4-Signature: bd4ea122fc1e2897017a5d25d9d70cc8
  10.  
  11. Submitted-by: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
  12. Posting-number: Volume 44, Issue 72
  13. Archive-name: unzip/part07
  14. Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT, AMIGA?, ATARI TOS, SGI, DEC, Cray, Convex, Amdahl, Sun
  15. Supersedes: unzip50: Volume 31, Issue 104-117
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  unzip-5.12/msdos/msdos.c unzip-5.12/zipinfo.doc
  22. # Wrapped by kent@sparky on Sat Sep 17 23:33:39 1994
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 7 (of 20)."'
  26. if test -f 'unzip-5.12/msdos/msdos.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'unzip-5.12/msdos/msdos.c'\"
  28. else
  29.   echo shar: Extracting \"'unzip-5.12/msdos/msdos.c'\" \(46263 characters\)
  30.   sed "s/^X//" >'unzip-5.12/msdos/msdos.c' <<'END_OF_FILE'
  31. X/*---------------------------------------------------------------------------
  32. X
  33. X  msdos.c
  34. X
  35. X  MSDOS-specific routines for use with Info-ZIP's UnZip 5.1 and later.
  36. X
  37. X  Contains:  Opendir()           (from zip)
  38. X             Readdir()           (from zip)
  39. X             do_wild()
  40. X             mapattr()
  41. X             mapname()
  42. X             checkdir()
  43. X             isfloppy()
  44. X             volumelabel()       (non-djgpp, non-emx)
  45. X             close_outfile()
  46. X             dateformat()
  47. X             version()
  48. X             _dos_getcountryinfo() (djgpp, emx)
  49. X             _dos_setftime()     (djgpp, emx)
  50. X             _dos_setfileattr()  (djgpp, emx)
  51. X             _dos_getdrive()     (djgpp, emx)
  52. X             _dos_creat()        (djgpp, emx)
  53. X             _dos_close()        (djgpp, emx)
  54. X             volumelabel()       (djgpp, emx)
  55. X
  56. X  ---------------------------------------------------------------------------*/
  57. X
  58. X
  59. X
  60. X#include "unzip.h"
  61. X#undef FILENAME    /* BC++ 3.1 and djgpp 1.11 define FILENAME in <dir.h> */
  62. X
  63. Xstatic int isfloppy OF((int nDrive));
  64. Xstatic int volumelabel OF((char *newlabel));
  65. X
  66. Xstatic int created_dir;        /* used by mapname(), checkdir() */
  67. Xstatic int renamed_fullpath;   /* ditto */
  68. Xstatic unsigned nLabelDrive;   /* ditto, plus volumelabel() */
  69. X
  70. X#if (defined(__GO32__) || defined(__EMX__))
  71. X#  define MKDIR(path,mode)   mkdir(path,mode)
  72. X#  include <dirent.h>        /* use readdir() */
  73. X#  define direct dirent
  74. X#  define Opendir opendir
  75. X#  define Readdir readdir
  76. X#  ifdef __EMX__
  77. X#    include <dos.h>
  78. X#    define GETDRIVE(d)      d = _getdrive()
  79. X#    define FA_LABEL         A_LABEL
  80. X#  else
  81. X#    define GETDRIVE(d)      _dos_getdrive(&d)
  82. X#  endif
  83. X#else /* !(__GO32__ || __EMX__) */
  84. X#  define MKDIR(path,mode)   mkdir(path)
  85. X#  ifdef __TURBOC__
  86. X#    define FATTR            FA_HIDDEN+FA_SYSTEM+FA_DIREC
  87. X#    define FVOLID           FA_VOLID
  88. X#    define FFIRST(n,d,a)    findfirst(n,(struct ffblk *)d,a)
  89. X#    define FNEXT(d)         findnext((struct ffblk *)d)
  90. X#    define GETDRIVE(d)      d=getdisk()+1
  91. X#    include <dir.h>
  92. X#  else /* !__TURBOC__ */
  93. X#    define FATTR            _A_HIDDEN+_A_SYSTEM+_A_SUBDIR
  94. X#    define FVOLID           _A_VOLID
  95. X#    define FFIRST(n,d,a)    _dos_findfirst(n,a,(struct find_t *)d)
  96. X#    define FNEXT(d)         _dos_findnext((struct find_t *)d)
  97. X#    define GETDRIVE(d)      _dos_getdrive(&d)
  98. X#    include <direct.h>
  99. X#  endif /* ?__TURBOC__ */
  100. X   typedef struct direct {
  101. X       char d_reserved[30];
  102. X       char d_name[13];
  103. X       int d_first;
  104. X   } DIR;
  105. X#  define closedir free
  106. X   DIR *Opendir OF((const char *));
  107. X   struct direct *Readdir OF((DIR *));
  108. X
  109. X
  110. X
  111. X
  112. X#ifndef SFX
  113. X
  114. X/**********************/   /* Borland C++ 3.x has its own opendir/readdir */
  115. X/* Function Opendir() */   /*  library routines, but earlier versions don't, */
  116. X/**********************/   /*  so use ours regardless */
  117. X
  118. XDIR *Opendir(name)
  119. X    const char *name;        /* name of directory to open */
  120. X{
  121. X    DIR *dirp;               /* malloc'd return value */
  122. X    char *nbuf;              /* malloc'd temporary string */
  123. X    int len = strlen(name);  /* path length to avoid strlens and strcats */
  124. X
  125. X
  126. X    if ((dirp = (DIR *)malloc(sizeof(DIR))) == (DIR *)NULL)
  127. X        return (DIR *)NULL;
  128. X    if ((nbuf = malloc(len + 5)) == (char *)NULL) {
  129. X        free(dirp);
  130. X        return (DIR *)NULL;
  131. X    }
  132. X    strcpy(nbuf, name);
  133. X    if (nbuf[len-1] == ':') {
  134. X        nbuf[len++] = '.';
  135. X    } else if (nbuf[len-1] == '/' || nbuf[len-1] == '\\')
  136. X        --len;
  137. X    strcpy(nbuf+len, "/*.*");
  138. X    Trace((stderr, "opendir:  nbuf = [%s]\n", nbuf));
  139. X
  140. X    if (FFIRST(nbuf, dirp, FATTR)) {
  141. X        free((voidp *)nbuf);
  142. X        return (DIR *)NULL;
  143. X    }
  144. X    free((voidp *)nbuf);
  145. X    dirp->d_first = 1;
  146. X    return dirp;
  147. X}
  148. X
  149. X
  150. X
  151. X
  152. X
  153. X/**********************/
  154. X/* Function Readdir() */
  155. X/**********************/
  156. X
  157. Xstruct direct *Readdir(d)
  158. X    DIR *d;         /* directory stream from which to read */
  159. X{
  160. X    /* Return pointer to first or next directory entry, or NULL if end. */
  161. X
  162. X    if (d->d_first)
  163. X        d->d_first = 0;
  164. X    else
  165. X        if (FNEXT(d))
  166. X            return (struct direct *)NULL;
  167. X    return (struct direct *)d;
  168. X}
  169. X
  170. X#endif /* !SFX */
  171. X#endif /* ?(__GO32__ || __EMX__) */
  172. X
  173. X
  174. X
  175. X
  176. X
  177. X#ifndef SFX
  178. X
  179. X/************************/
  180. X/*  Function do_wild()  */   /* identical to OS/2 version */
  181. X/************************/
  182. X
  183. Xchar *do_wild(wildspec)
  184. X    char *wildspec;          /* only used first time on a given dir */
  185. X{
  186. X    static DIR *dir = (DIR *)NULL;
  187. X    static char *dirname, *wildname, matchname[FILNAMSIZ];
  188. X    static char Far CantAllocateWildcard[] =
  189. X      "warning:  can't allocate wildcard buffers\n";
  190. X    static int firstcall=TRUE, have_dirname, dirnamelen;
  191. X    struct direct *file;
  192. X
  193. X
  194. X    /* Even when we're just returning wildspec, we *always* do so in
  195. X     * matchname[]--calling routine is allowed to append four characters
  196. X     * to the returned string, and wildspec may be a pointer to argv[].
  197. X     */
  198. X    if (firstcall) {        /* first call:  must initialize everything */
  199. X        firstcall = FALSE;
  200. X
  201. X        /* break the wildspec into a directory part and a wildcard filename */
  202. X        if ((wildname = strrchr(wildspec, '/')) == (char *)NULL &&
  203. X            (wildname = strrchr(wildspec, ':')) == (char *)NULL) {
  204. X            dirname = ".";
  205. X            dirnamelen = 1;
  206. X            have_dirname = FALSE;
  207. X            wildname = wildspec;
  208. X        } else {
  209. X            ++wildname;     /* point at character after '/' or ':' */
  210. X            dirnamelen = wildname - wildspec;
  211. X            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {
  212. X                FPRINTF(stderr, LoadFarString(CantAllocateWildcard));
  213. X                strcpy(matchname, wildspec);
  214. X                return matchname;   /* but maybe filespec was not a wildcard */
  215. X            }
  216. X/* GRR:  can't strip trailing char for opendir since might be "d:/" or "d:"
  217. X *       (would have to check for "./" at end--let opendir handle it instead) */
  218. X            strncpy(dirname, wildspec, dirnamelen);
  219. X            dirname[dirnamelen] = '\0';   /* terminate for strcpy below */
  220. X            have_dirname = TRUE;
  221. X        }
  222. X        Trace((stderr, "do_wild:  dirname = [%s]\n", dirname));
  223. X
  224. X        if ((dir = Opendir(dirname)) != (DIR *)NULL) {
  225. X            while ((file = Readdir(dir)) != (struct direct *)NULL) {
  226. X                Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
  227. X                if (match(file->d_name, wildname, 1)) {  /* 1 == ignore case */
  228. X                    Trace((stderr, "do_wild:  match() succeeds\n"));
  229. X                    if (have_dirname) {
  230. X                        strcpy(matchname, dirname);
  231. X                        strcpy(matchname+dirnamelen, file->d_name);
  232. X                    } else
  233. X                        strcpy(matchname, file->d_name);
  234. X                    return matchname;
  235. X                }
  236. X            }
  237. X            /* if we get to here directory is exhausted, so close it */
  238. X            closedir(dir);
  239. X            dir = (DIR *)NULL;
  240. X        }
  241. X        Trace((stderr, "do_wild:  opendir(%s) returns NULL\n", dirname));
  242. X
  243. X        /* return the raw wildspec in case that works (e.g., directory not
  244. X         * searchable, but filespec was not wild and file is readable) */
  245. X        strcpy(matchname, wildspec);
  246. X        return matchname;
  247. X    }
  248. X
  249. X    /* last time through, might have failed opendir but returned raw wildspec */
  250. X    if (dir == (DIR *)NULL) {
  251. X        firstcall = TRUE;  /* nothing left to try--reset for new wildspec */
  252. X        if (have_dirname)
  253. X            free(dirname);
  254. X        return (char *)NULL;
  255. X    }
  256. X
  257. X    /* If we've gotten this far, we've read and matched at least one entry
  258. X     * successfully (in a previous call), so dirname has been copied into
  259. X     * matchname already.
  260. X     */
  261. X    while ((file = Readdir(dir)) != (struct direct *)NULL)
  262. X        if (match(file->d_name, wildname, 1)) {   /* 1 == ignore case */
  263. X            if (have_dirname) {
  264. X                /* strcpy(matchname, dirname); */
  265. X                strcpy(matchname+dirnamelen, file->d_name);
  266. X            } else
  267. X                strcpy(matchname, file->d_name);
  268. X            return matchname;
  269. X        }
  270. X
  271. X    closedir(dir);     /* have read at least one dir entry; nothing left */
  272. X    dir = (DIR *)NULL;
  273. X    firstcall = TRUE;  /* reset for new wildspec */
  274. X    if (have_dirname)
  275. X        free(dirname);
  276. X    return (char *)NULL;
  277. X
  278. X} /* end function do_wild() */
  279. X
  280. X#endif /* !SFX */
  281. X
  282. X
  283. X
  284. X
  285. X
  286. X/**********************/
  287. X/* Function mapattr() */
  288. X/**********************/
  289. X
  290. Xint mapattr()
  291. X{
  292. X    /* set archive bit (file is not backed up): */
  293. X    pInfo->file_attr = (unsigned)(crec.external_file_attributes | 32) & 0xff;
  294. X    return 0;
  295. X
  296. X} /* end function mapattr() */
  297. X
  298. X
  299. X
  300. X
  301. X
  302. X/*****************************/
  303. X/*  Strings used in msdos.c  */
  304. X/*****************************/
  305. X
  306. Xstatic char Far ConversionFailed[] = "mapname:  conversion of %s failed\n";
  307. Xstatic char Far ErrSetVolLabel[] = "mapname:  error setting volume label\n";
  308. Xstatic char Far PathTooLong[] = "checkdir error:  path too long: %s\n";
  309. Xstatic char Far CantCreateDir[] = "checkdir error:  can't create %s\n\
  310. X                 unable to process %s.\n";
  311. Xstatic char Far DirIsntDirectory[] =
  312. X  "checkdir error:  %s exists but is not directory\n\
  313. X                 unable to process %s.\n";
  314. Xstatic char Far PathTooLongTrunc[] =
  315. X  "checkdir warning:  path too long; truncating\n                   %s\n\
  316. X                -> %s\n";
  317. X#if (!defined(SFX) || defined(SFX_EXDIR))
  318. X   static char Far CantCreateExtractDir[] =
  319. X     "checkdir:  can't create extraction directory: %s\n";
  320. X#endif
  321. X
  322. X
  323. X
  324. X
  325. X
  326. X/************************/
  327. X/*  Function mapname()  */
  328. X/************************/
  329. X
  330. Xint mapname(renamed)  /* return 0 if no error, 1 if caution (filename trunc), */
  331. X    int renamed;      /* 2 if warning (skip file because dir doesn't exist), */
  332. X{                     /* 3 if error (skip file), 10 if no memory (skip file) */
  333. X    char pathcomp[FILNAMSIZ];    /* path-component buffer */
  334. X    char *pp, *cp=(char *)NULL;  /* character pointers */
  335. X    char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */
  336. X    char *last_dot=(char *)NULL; /* last dot not converted to underscore */
  337. X    int quote = FALSE;           /* flag:  next char is literal */
  338. X    int dotname = FALSE;         /* flag:  path component begins with dot */
  339. X    int error = 0;
  340. X    register unsigned workch;    /* hold the character being tested */
  341. X
  342. X
  343. X/*---------------------------------------------------------------------------
  344. X    Initialize various pointers and counters and stuff.
  345. X  ---------------------------------------------------------------------------*/
  346. X
  347. X    /* can create path as long as not just freshening, or if user told us */
  348. X    create_dirs = (!fflag || renamed);
  349. X
  350. X    created_dir = FALSE;        /* not yet */
  351. X    renamed_fullpath = FALSE;
  352. X
  353. X/* GRR:  for VMS, convert to internal format now or later? or never? */
  354. X    if (renamed) {
  355. X        cp = filename - 1;      /* point to beginning of renamed name... */
  356. X        while (*++cp)
  357. X            if (*cp == '\\')    /* convert backslashes to forward */
  358. X                *cp = '/';
  359. X        cp = filename;
  360. X        /* use temporary rootpath if user gave full pathname */
  361. X        if (filename[0] == '/') {
  362. X            renamed_fullpath = TRUE;
  363. X            pathcomp[0] = '/';  /* copy the '/' and terminate */
  364. X            pathcomp[1] = '\0';
  365. X            ++cp;
  366. X        } else if (isalpha(filename[0]) && filename[1] == ':') {
  367. X            renamed_fullpath = TRUE;
  368. X            pp = pathcomp;
  369. X            *pp++ = *cp++;      /* copy the "d:" (+ '/', possibly) */
  370. X            *pp++ = *cp++;
  371. X            if (*cp == '/')
  372. X                *pp++ = *cp++;  /* otherwise add "./"? */
  373. X            *pp = '\0';
  374. X        }
  375. X    }
  376. X
  377. X    /* pathcomp is ignored unless renamed_fullpath is TRUE: */
  378. X    if ((error = checkdir(pathcomp, INIT)) != 0)    /* initialize path buffer */
  379. X        return error;           /* ...unless no mem or vol label on hard disk */
  380. X
  381. X    *pathcomp = '\0';           /* initialize translation buffer */
  382. X    pp = pathcomp;              /* point to translation buffer */
  383. X    if (!renamed) {             /* cp already set if renamed */
  384. X        if (jflag)              /* junking directories */
  385. X            cp = (char *)strrchr(filename, '/');
  386. X        if (cp == (char *)NULL) /* no '/' or not junking dirs */
  387. X            cp = filename;      /* point to internal zipfile-member pathname */
  388. X        else
  389. X            ++cp;               /* point to start of last component of path */
  390. X    }
  391. X
  392. X/*---------------------------------------------------------------------------
  393. X    Begin main loop through characters in filename.
  394. X  ---------------------------------------------------------------------------*/
  395. X
  396. X    while ((workch = (uch)*cp++) != 0) {
  397. X
  398. X        if (quote) {              /* if character quoted, */
  399. X            *pp++ = (char)workch; /*  include it literally */
  400. X            quote = FALSE;
  401. X        } else
  402. X            switch (workch) {
  403. X            case '/':             /* can assume -j flag not given */
  404. X                *pp = '\0';
  405. X/* GRR:  can add 8.3 truncation here */
  406. X                if (last_dot) {   /* one dot in directory name is legal */
  407. X                    *last_dot = '.';
  408. X                    last_dot = (char *)NULL;
  409. X                }
  410. X                if ((error = checkdir(pathcomp, APPEND_DIR)) > 1)
  411. X                    return error;
  412. X                pp = pathcomp;    /* reset conversion buffer for next piece */
  413. X                lastsemi = (char *)NULL; /* leave directory semi-colons alone */
  414. X                break;
  415. X
  416. X            case ':':             /* drive names not stored in zipfile, */
  417. X            case '[':             /*  so no colons allowed; no brackets, */
  418. X            case ']':             /*  either */
  419. X                *pp++ = '_';
  420. X                break;
  421. X
  422. X            case '.':
  423. X                if (pp == pathcomp) {     /* nothing appended yet... */
  424. X                    if (*cp == '/') {     /* don't bother appending a "./" */
  425. X                        ++cp;             /*  component to the path:  skip */
  426. X                        break;            /*  to next char after the '/' */
  427. X                    } else if (*cp == '.' && cp[1] == '/') {   /* "../" */
  428. X                        *pp++ = '.';      /* add first dot, unchanged... */
  429. X                        ++cp;             /* skip second dot, since it will */
  430. X                    } else {              /*  be "added" at end of if-block */
  431. X                        *pp++ = '_';      /* FAT doesn't allow null filename */
  432. X                        dotname = TRUE;   /*  bodies, so map .exrc -> _.exrc */
  433. X                    }                     /*  (extra '_' now, "dot" below) */
  434. X                } else if (dotname) {     /* found a second dot, but still */
  435. X                    dotname = FALSE;      /*  have extra leading underscore: */
  436. X                    *pp = '\0';           /*  remove it by shifting chars */
  437. X                    pp = pathcomp + 1;    /*  left one space (e.g., .p1.p2: */
  438. X                    while (pp[1]) {       /*  __p1 -> _p1_p2 -> _p1.p2 when */
  439. X                        *pp = pp[1];      /*  finished) [opt.:  since first */
  440. X                        ++pp;             /*  two chars are same, can start */
  441. X                    }                     /*  shifting at second position] */
  442. X                }
  443. X                last_dot = pp;    /* point at last dot so far... */
  444. X                *pp++ = '_';      /* convert dot to underscore for now */
  445. X                break;
  446. X
  447. X            case ';':             /* start of VMS version? */
  448. X                lastsemi = pp;    /* omit for now; remove VMS vers. later */
  449. X                break;
  450. X
  451. X            case '\026':          /* control-V quote for special chars */
  452. X                quote = TRUE;     /* set flag for next character */
  453. X                break;
  454. X
  455. X            case ' ':             /* change spaces to underscore only */
  456. X                if (sflag)        /*  if specifically requested */
  457. X                    *pp++ = '_';
  458. X                else
  459. X                    *pp++ = (char)workch;
  460. X                break;
  461. X
  462. X            default:
  463. X                /* allow European characters in filenames: */
  464. X                if (isprint(workch) || (128 <= workch && workch <= 254))
  465. X                    *pp++ = (char)workch;
  466. X            } /* end switch */
  467. X
  468. X    } /* end while loop */
  469. X
  470. X    *pp = '\0';                   /* done with pathcomp:  terminate it */
  471. X
  472. X    /* if not saving them, remove VMS version numbers (appended "###") */
  473. X    if (!V_flag && lastsemi) {
  474. X        pp = lastsemi;            /* semi-colon was omitted:  expect all #'s */
  475. X        while (isdigit((uch)(*pp)))
  476. X            ++pp;
  477. X        if (*pp == '\0')          /* only digits between ';' and end:  nuke */
  478. X            *lastsemi = '\0';
  479. X    }
  480. X
  481. X/* GRR:  can add 8.3 truncation here */
  482. X    if (last_dot != (char *)NULL) /* one dot is OK:  put it back in */
  483. X        *last_dot = '.';          /* (already done for directories) */
  484. X
  485. X/*---------------------------------------------------------------------------
  486. X    Report if directory was created (and no file to create:  filename ended
  487. X    in '/'), check name to be sure it exists, and combine path and name be-
  488. X    fore exiting.
  489. X  ---------------------------------------------------------------------------*/
  490. X
  491. X    if (filename[strlen(filename) - 1] == '/') {
  492. X        checkdir(filename, GETPATH);
  493. X        if (created_dir && QCOND2) {
  494. X            FPRINTF(stdout, "   creating: %s\n", filename);
  495. X            return IZ_CREATED_DIR;   /* set dir time (note trailing '/') */
  496. X        }
  497. X        return 2;   /* dir existed already; don't look for data to extract */
  498. X    }
  499. X
  500. X    if (*pathcomp == '\0') {
  501. X        FPRINTF(stderr, LoadFarString(ConversionFailed), filename);
  502. X        return 3;
  503. X    }
  504. X
  505. X    checkdir(pathcomp, APPEND_NAME);   /* returns 1 if truncated:  care? */
  506. X    checkdir(filename, GETPATH);
  507. X
  508. X    if (pInfo->vollabel) {   /* set the volume label now */
  509. X        if (QCOND2)
  510. X            FPRINTF(stdout, "labelling %c: %-22s\n", (nLabelDrive + 'a' - 1),
  511. X              filename);
  512. X        if (volumelabel(filename)) {
  513. X            FPRINTF(stderr, LoadFarString(ErrSetVolLabel));
  514. X            return 3;
  515. X        }
  516. X        return 2;   /* success:  skip the "extraction" quietly */
  517. X    }
  518. X
  519. X    return error;
  520. X
  521. X} /* end function mapname() */
  522. X
  523. X
  524. X
  525. X
  526. X
  527. X/***********************/
  528. X/* Function checkdir() */
  529. X/***********************/
  530. X
  531. Xint checkdir(pathcomp, flag)
  532. X    char *pathcomp;
  533. X    int flag;
  534. X/*
  535. X * returns:  1 - (on APPEND_NAME) truncated filename
  536. X *           2 - path doesn't exist, not allowed to create
  537. X *           3 - path doesn't exist, tried to create and failed; or
  538. X *               path exists and is not a directory, but is supposed to be
  539. X *           4 - path is too long
  540. X *          10 - can't allocate memory for filename buffers
  541. X */
  542. X{
  543. X    static int rootlen = 0;   /* length of rootpath */
  544. X    static char *rootpath;    /* user's "extract-to" directory */
  545. X    static char *buildpath;   /* full path (so far) to extracted file */
  546. X    static char *end;         /* pointer to end of buildpath ('\0') */
  547. X#ifdef MSC
  548. X    int attrs;                /* work around MSC stat() bug */
  549. X#endif
  550. X
  551. X#   define FN_MASK   7
  552. X#   define FUNCTION  (flag & FN_MASK)
  553. X
  554. X
  555. X
  556. X/*---------------------------------------------------------------------------
  557. X    APPEND_DIR:  append the path component to the path being built and check
  558. X    for its existence.  If doesn't exist and we are creating directories, do
  559. X    so for this one; else signal success or error as appropriate.
  560. X  ---------------------------------------------------------------------------*/
  561. X
  562. X    if (FUNCTION == APPEND_DIR) {
  563. X        int too_long = FALSE;
  564. X
  565. X        Trace((stderr, "appending dir segment [%s]\n", pathcomp));
  566. X        while ((*end = *pathcomp++) != '\0')
  567. X            ++end;
  568. X
  569. X        /* GRR:  could do better check, see if overrunning buffer as we go:
  570. X         * check end-buildpath after each append, set warning variable if
  571. X         * within 20 of FILNAMSIZ; then if var set, do careful check when
  572. X         * appending.  Clear variable when begin new path. */
  573. X
  574. X        if ((end-buildpath) > FILNAMSIZ-3)  /* need '/', one-char name, '\0' */
  575. X            too_long = TRUE;                /* check if extracting directory? */
  576. X#ifdef MSC /* MSC 6.00 bug:  stat(non-existent-dir) == 0 [exists!] */
  577. X        if (_dos_getfileattr(buildpath, &attrs) || stat(buildpath, &statbuf))  
  578. X#else
  579. X        if (stat(buildpath, &statbuf))      /* path doesn't exist */
  580. X#endif
  581. X        {
  582. X            if (!create_dirs) {   /* told not to create (freshening) */
  583. X                free(buildpath);
  584. X                return 2;         /* path doesn't exist:  nothing to do */
  585. X            }
  586. X            if (too_long) {
  587. X                FPRINTF(stderr, LoadFarString(PathTooLong), buildpath);
  588. X                fflush(stderr);
  589. X                free(buildpath);
  590. X                return 4;         /* no room for filenames:  fatal */
  591. X            }
  592. X            if (MKDIR(buildpath, 0777) == -1) {   /* create the directory */
  593. X                FPRINTF(stderr, LoadFarString(CantCreateDir), buildpath,
  594. X                        filename);
  595. X                fflush(stderr);
  596. X                free(buildpath);
  597. X                return 3;      /* path didn't exist, tried to create, failed */
  598. X            }
  599. X            created_dir = TRUE;
  600. X        } else if (!S_ISDIR(statbuf.st_mode)) {
  601. X            FPRINTF(stderr, LoadFarString(DirIsntDirectory), buildpath,
  602. X                    filename);
  603. X            fflush(stderr);
  604. X            free(buildpath);
  605. X            return 3;          /* path existed but wasn't dir */
  606. X        }
  607. X        if (too_long) {
  608. X            FPRINTF(stderr, LoadFarString(PathTooLong), buildpath);
  609. X            fflush(stderr);
  610. X            free(buildpath);
  611. X            return 4;         /* no room for filenames:  fatal */
  612. X        }
  613. X        *end++ = '/';
  614. X        *end = '\0';
  615. X        Trace((stderr, "buildpath now = [%s]\n", buildpath));
  616. X        return 0;
  617. X
  618. X    } /* end if (FUNCTION == APPEND_DIR) */
  619. X
  620. X/*---------------------------------------------------------------------------
  621. X    GETPATH:  copy full path to the string pointed at by pathcomp, and free
  622. X    buildpath.
  623. X  ---------------------------------------------------------------------------*/
  624. X
  625. X    if (FUNCTION == GETPATH) {
  626. X        strcpy(pathcomp, buildpath);
  627. X        Trace((stderr, "getting and freeing path [%s]\n", pathcomp));
  628. X        free(buildpath);
  629. X        buildpath = end = (char *)NULL;
  630. X        return 0;
  631. X    }
  632. X
  633. X/*---------------------------------------------------------------------------
  634. X    APPEND_NAME:  assume the path component is the filename; append it and
  635. X    return without checking for existence.
  636. X  ---------------------------------------------------------------------------*/
  637. X
  638. X    if (FUNCTION == APPEND_NAME) {
  639. X        Trace((stderr, "appending filename [%s]\n", pathcomp));
  640. X        while ((*end = *pathcomp++) != '\0') {
  641. X            ++end;
  642. X            if ((end-buildpath) >= FILNAMSIZ) {
  643. X                *--end = '\0';
  644. X                FPRINTF(stderr, LoadFarString(PathTooLongTrunc),
  645. X                        filename, buildpath);
  646. X                fflush(stderr);
  647. X                return 1;   /* filename truncated */
  648. X            }
  649. X        }
  650. X        Trace((stderr, "buildpath now = [%s]\n", buildpath));
  651. X        return 0;  /* could check for existence here, prompt for new name... */
  652. X    }
  653. X
  654. X/*---------------------------------------------------------------------------
  655. X    INIT:  allocate and initialize buffer space for the file currently being
  656. X    extracted.  If file was renamed with an absolute path, don't prepend the
  657. X    extract-to path.
  658. X  ---------------------------------------------------------------------------*/
  659. X
  660. X    if (FUNCTION == INIT) {
  661. X        Trace((stderr, "initializing buildpath to "));
  662. X        if ((buildpath = (char *)malloc(strlen(filename)+rootlen+1)) ==
  663. X            (char *)NULL)
  664. X            return 10;
  665. X        if (pInfo->vollabel) {
  666. X/* GRR:  for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */
  667. X            if (renamed_fullpath && pathcomp[1] == ':')
  668. X                *buildpath = ToLower(*pathcomp);
  669. X            else if (!renamed_fullpath && rootpath && rootpath[1] == ':')
  670. X                *buildpath = ToLower(*rootpath);
  671. X            else {
  672. X                GETDRIVE(nLabelDrive);   /* assumed that a == 1, b == 2, etc. */
  673. X                *buildpath = (char)(nLabelDrive - 1 + 'a');
  674. X            }
  675. X            nLabelDrive = *buildpath - 'a' + 1;       /* save for mapname() */
  676. X            if (volflag == 0 || *buildpath < 'a' ||   /* no labels/bogus disk */
  677. X                (volflag == 1 && !isfloppy(nLabelDrive))) {  /* -$:  no fixed */
  678. X                free(buildpath);
  679. X                return IZ_VOL_LABEL;     /* skipping with message */
  680. X            }
  681. X            *buildpath = '\0';
  682. X            end = buildpath;
  683. X        } else if (renamed_fullpath) {   /* pathcomp = valid data */
  684. X            end = buildpath;
  685. X            while ((*end = *pathcomp++) != '\0')
  686. X                ++end;
  687. X        } else if (rootlen > 0) {
  688. X            strcpy(buildpath, rootpath);
  689. X            end = buildpath + rootlen;
  690. X        } else {
  691. X            *buildpath = '\0';
  692. X            end = buildpath;
  693. X        }
  694. X        Trace((stderr, "[%s]\n", buildpath));
  695. X        return 0;
  696. X    }
  697. X
  698. X/*---------------------------------------------------------------------------
  699. X    ROOT:  if appropriate, store the path in rootpath and create it if neces-
  700. X    sary; else assume it's a zipfile member and return.  This path segment
  701. X    gets used in extracting all members from every zipfile specified on the
  702. X    command line.  Note that under OS/2 and MS-DOS, if a candidate extract-to
  703. X    directory specification includes a drive letter (leading "x:"), it is
  704. X    treated just as if it had a trailing '/'--that is, one directory level
  705. X    will be created if the path doesn't exist, unless this is otherwise pro-
  706. X    hibited (e.g., freshening).
  707. X  ---------------------------------------------------------------------------*/
  708. X
  709. X#if (!defined(SFX) || defined(SFX_EXDIR))
  710. X    if (FUNCTION == ROOT) {
  711. X        Trace((stderr, "initializing root path to [%s]\n", pathcomp));
  712. X        if (pathcomp == (char *)NULL) {
  713. X            rootlen = 0;
  714. X            return 0;
  715. X        }
  716. X        if ((rootlen = strlen(pathcomp)) > 0) {
  717. X            int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2;
  718. X
  719. X            if (isalpha(pathcomp[0]) && pathcomp[1] == ':')
  720. X                has_drive = TRUE;   /* drive designator */
  721. X            if (pathcomp[rootlen-1] == '/') {
  722. X                pathcomp[--rootlen] = '\0';
  723. X                had_trailing_pathsep = TRUE;
  724. X            }
  725. X            if (has_drive && (rootlen == 2)) {
  726. X                if (!had_trailing_pathsep)   /* i.e., original wasn't "x:/" */
  727. X                    xtra = 3;      /* room for '.' + '/' + 0 at end of "x:" */
  728. X            } else if (rootlen > 0) {     /* need not check "x:." and "x:/" */
  729. X#ifdef MSC
  730. X                /* MSC 6.00 bug:  stat(non-existent-dir) == 0 [exists!] */
  731. X                if (_dos_getfileattr(pathcomp, &attrs) ||
  732. X                    SSTAT(pathcomp, &statbuf) || !S_ISDIR(statbuf.st_mode))
  733. X#else
  734. X                if (SSTAT(pathcomp, &statbuf) || !S_ISDIR(statbuf.st_mode))
  735. X#endif
  736. X                {
  737. X                    /* path does not exist */
  738. X                    if (!create_dirs                 /* || iswild(pathcomp) */
  739. X#ifdef OLD_EXDIR
  740. X                                     || (!has_drive && !had_trailing_pathsep)
  741. X#endif
  742. X                                                                             ) {
  743. X                        rootlen = 0;
  744. X                        return 2;   /* treat as stored file */
  745. X                    }
  746. X/* GRR:  scan for wildcard characters?  OS-dependent...  if find any, return 2:
  747. X * treat as stored file(s) */
  748. X                    /* create directory (could add loop here to scan pathcomp
  749. X                     * and create more than one level, but really necessary?) */
  750. X                    if (MKDIR(pathcomp, 0777) == -1) {
  751. X                        FPRINTF(stderr, LoadFarString(CantCreateExtractDir),
  752. X                                pathcomp);
  753. X                        fflush(stderr);
  754. X                        rootlen = 0;   /* path didn't exist, tried to create, */
  755. X                        return 3;  /* failed:  file exists, or need 2+ levels */
  756. X                    }
  757. X                }
  758. X            }
  759. X            if ((rootpath = (char *)malloc(rootlen+xtra)) == (char *)NULL) {
  760. X                rootlen = 0;
  761. X                return 10;
  762. X            }
  763. X            strcpy(rootpath, pathcomp);
  764. X            if (xtra == 3)                  /* had just "x:", make "x:." */
  765. X                rootpath[rootlen++] = '.';
  766. X            rootpath[rootlen++] = '/';
  767. X            rootpath[rootlen] = '\0';
  768. X        }
  769. X        Trace((stderr, "rootpath now = [%s]\n", rootpath));
  770. X        return 0;
  771. X    }
  772. X#endif /* !SFX || SFX_EXDIR */
  773. X
  774. X/*---------------------------------------------------------------------------
  775. X    END:  free rootpath, immediately prior to program exit.
  776. X  ---------------------------------------------------------------------------*/
  777. X
  778. X    if (FUNCTION == END) {
  779. X        Trace((stderr, "freeing rootpath\n"));
  780. X        if (rootlen > 0)
  781. X            free(rootpath);
  782. X        return 0;
  783. X    }
  784. X
  785. X    return 99;  /* should never reach */
  786. X
  787. X} /* end function checkdir() */
  788. X
  789. X
  790. X
  791. X
  792. X
  793. X
  794. X/***********************/
  795. X/* Function isfloppy() */
  796. X/***********************/
  797. X
  798. Xstatic int isfloppy(nDrive)  /* more precisely, is it removable? */
  799. X    int nDrive;
  800. X{
  801. X    union REGS regs;
  802. X
  803. X    regs.h.ah = 0x44;
  804. X    regs.h.al = 0x08;
  805. X    regs.h.bl = (uch)nDrive;
  806. X#ifdef __EMX__
  807. X    _int86(0x21, ®s, ®s);
  808. X    if (regs.x.flags & 1)
  809. X#else
  810. X    intdos(®s, ®s);
  811. X    if (regs.x.cflag)        /* error:  do default a/b check instead */
  812. X#endif
  813. X    {
  814. X        Trace((stderr,
  815. X          "error in DOS function 0x44 (AX = 0x%04x):  guessing instead...\n",
  816. X          regs.x.ax));
  817. X        return (nDrive == 1 || nDrive == 2)? TRUE : FALSE;
  818. X    } else
  819. X        return regs.x.ax? FALSE : TRUE;
  820. X}
  821. X
  822. X
  823. X
  824. X
  825. X#if (!defined(__GO32__) && !defined(__EMX__))
  826. X
  827. Xtypedef struct dosfcb {
  828. X    uch  flag;        /* ff to indicate extended FCB */
  829. X    char res[5];      /* reserved */
  830. X    uch  vattr;       /* attribute */
  831. X    uch  drive;       /* drive (1=A, 2=B, ...) */
  832. X    uch  vn[11];      /* file or volume name */
  833. X    char dmmy[5];
  834. X    uch  nn[11];      /* holds new name if renaming (else reserved) */
  835. X    char dmmy2[9];
  836. X} dos_fcb;
  837. X
  838. X/**************************/
  839. X/* Function volumelabel() */
  840. X/**************************/
  841. X
  842. Xstatic int volumelabel(newlabel)
  843. X    char *newlabel;
  844. X{
  845. X#ifdef DEBUG
  846. X    char *p;
  847. X#endif
  848. X    int len = strlen(newlabel);
  849. X    dos_fcb  fcb, dta, far *pfcb=&fcb, far *pdta=&dta;
  850. X    struct SREGS sregs;
  851. X    union REGS regs;
  852. X
  853. X
  854. X/*---------------------------------------------------------------------------
  855. X    Label the diskette specified by nLabelDrive using FCB calls.  (Old ver-
  856. X    sions of MS-DOS and OS/2 DOS boxes can't use DOS function 3Ch to create
  857. X    labels.)  Must use far pointers for MSC FP_* macros to work; must pad
  858. X    FCB filenames with spaces; and cannot include dot in 8th position.  May
  859. X    or may not need to zero out FCBs before using; do so just in case.
  860. X  ---------------------------------------------------------------------------*/
  861. X
  862. X    memset((char *)&dta, 0, sizeof(dos_fcb));
  863. X    memset((char *)&fcb, 0, sizeof(dos_fcb));
  864. X
  865. X#ifdef DEBUG
  866. X    for (p = (char *)&dta; (p - (char *)&dta) < sizeof(dos_fcb); ++p)
  867. X        if (*p)
  868. X            fprintf(stderr, "error:  dta[%d] = %x\n", (p - (char *)&dta), *p);
  869. X    for (p = (char *)&fcb; (p - (char *)&fcb) < sizeof(dos_fcb); ++p)
  870. X        if (*p)
  871. X            fprintf(stderr, "error:  fcb[%d] = %x\n", (p - (char *)&fcb), *p);
  872. X    printf("testing pointer macros:\n");
  873. X    segread(&sregs);
  874. X    printf("cs = %x, ds = %x, es = %x, ss = %x\n", sregs.cs, sregs.ds, sregs.es,
  875. X      sregs.ss);
  876. X#endif /* DEBUG */
  877. X
  878. X#if 0
  879. X#ifdef __TURBOC__
  880. X    bdosptr(0x1a, dta, DO_NOT_CARE);
  881. X#else
  882. X    (intdosx method below)
  883. X#endif
  884. X#endif /* 0 */
  885. X
  886. X    /* set the disk transfer address for subsequent FCB calls */
  887. X    sregs.ds = FP_SEG(pdta);
  888. X    regs.x.dx = FP_OFF(pdta);
  889. X    Trace((stderr, "segment:offset of pdta = %x:%x\n", sregs.ds, regs.x.dx));
  890. X    Trace((stderr, "&dta = %lx, pdta = %lx\n", (ulg)&dta, (ulg)pdta));
  891. X    regs.h.ah = 0x1a;
  892. X    intdosx(®s, ®s, &sregs);
  893. X
  894. X    /* fill in the FCB */
  895. X    sregs.ds = FP_SEG(pfcb);
  896. X    regs.x.dx = FP_OFF(pfcb);
  897. X    pfcb->flag = 0xff;          /* extended FCB */
  898. X    pfcb->vattr = 0x08;         /* attribute:  disk volume label */
  899. X    pfcb->drive = (uch)nLabelDrive;
  900. X
  901. X#ifdef DEBUG
  902. X    Trace((stderr, "segment:offset of pfcb = %x:%x\n", sregs.ds, regs.x.dx));
  903. X    Trace((stderr, "&fcb = %lx, pfcb = %lx\n", (ulg)&fcb, (ulg)pfcb));
  904. X    Trace((stderr, "(2nd check:  labelling drive %c:)\n", pfcb->drive-1+'A'));
  905. X    if (pfcb->flag != fcb.flag)
  906. X        fprintf(stderr, "error:  pfcb->flag = %d, fcb.flag = %d\n",
  907. X          pfcb->flag, fcb.flag);
  908. X    if (pfcb->drive != fcb.drive)
  909. X        fprintf(stderr, "error:  pfcb->drive = %d, fcb.drive = %d\n",
  910. X          pfcb->drive, fcb.drive);
  911. X    if (pfcb->vattr != fcb.vattr)
  912. X        fprintf(stderr, "error:  pfcb->vattr = %d, fcb.vattr = %d\n",
  913. X          pfcb->vattr, fcb.vattr);
  914. X#endif /* DEBUG */
  915. X
  916. X    /* check for existing label */
  917. X    Trace((stderr, "searching for existing label via FCBs\n"));
  918. X    regs.h.ah = 0x11;      /* FCB find first */
  919. X#if 0  /* THIS STRNCPY FAILS (MSC bug?): */
  920. X    strncpy(pfcb->vn, "???????????", 11);   /* i.e., "*.*" */
  921. X    Trace((stderr, "pfcb->vn = %lx\n", (ulg)pfcb->vn));
  922. X    Trace((stderr, "flag = %x, drive = %d, vattr = %x, vn = %s = %s.\n",
  923. X      fcb.flag, fcb.drive, fcb.vattr, fcb.vn, pfcb->vn));
  924. X#endif
  925. X    strncpy((char *)fcb.vn, "???????????", 11);   /* i.e., "*.*" */
  926. X    Trace((stderr, "fcb.vn = %lx\n", (ulg)fcb.vn));
  927. X    Trace((stderr, "regs.h.ah = %x, regs.x.dx = %04x, sregs.ds = %04x\n",
  928. X      regs.h.ah, regs.x.dx, sregs.ds));
  929. X    Trace((stderr, "flag = %x, drive = %d, vattr = %x, vn = %s = %s.\n",
  930. X      fcb.flag, fcb.drive, fcb.vattr, fcb.vn, pfcb->vn));
  931. X    intdosx(®s, ®s, &sregs);
  932. X
  933. X/*---------------------------------------------------------------------------
  934. X    If not previously labelled, write a new label.  Otherwise just rename,
  935. X    since MS-DOS 2.x has a bug which damages the FAT when the old label is
  936. X    deleted.
  937. X  ---------------------------------------------------------------------------*/
  938. X
  939. X    if (regs.h.al) {
  940. X        Trace((stderr, "no label found\n\n"));
  941. X        regs.h.ah = 0x16;                 /* FCB create file */
  942. X        strncpy((char *)fcb.vn, newlabel, len);
  943. X        if (len < 11)   /* fill with spaces */
  944. X            strncpy((char *)(fcb.vn+len), "           ", 11-len);
  945. X        Trace((stderr, "fcb.vn = %lx  pfcb->vn = %lx\n", (ulg)fcb.vn,
  946. X          (ulg)pfcb->vn));
  947. X        Trace((stderr, "flag = %x, drive = %d, vattr = %x\n", fcb.flag,
  948. X          fcb.drive, fcb.vattr));
  949. X        Trace((stderr, "vn = %s = %s.\n", fcb.vn, pfcb->vn));
  950. X        intdosx(®s, ®s, &sregs);
  951. X        regs.h.ah = 0x10;                 /* FCB close file */
  952. X        if (regs.h.al) {
  953. X            Trace((stderr, "unable to write volume name (AL = %x)\n",
  954. X              regs.h.al));
  955. X            intdosx(®s, ®s, &sregs);
  956. X            return 1;
  957. X        } else {
  958. X            intdosx(®s, ®s, &sregs);
  959. X            Trace((stderr, "new volume label [%s] written\n", newlabel));
  960. X            return 0;
  961. X        }
  962. X    } else {
  963. X        Trace((stderr, "found old label [%s]\n\n", dta.vn));  /* not term. */
  964. X        regs.h.ah = 0x17;                 /* FCB rename */
  965. X        strncpy((char *)fcb.vn, (char *)dta.vn, 11);
  966. X        strncpy((char *)fcb.nn, newlabel, len);
  967. X        if (len < 11)                     /* fill with spaces */
  968. X            strncpy((char *)(fcb.nn+len), "           ", 11-len);
  969. X        Trace((stderr, "fcb.vn = %lx  pfcb->vn = %lx\n", (ulg)fcb.vn,
  970. X          (ulg)pfcb->vn));
  971. X        Trace((stderr, "fcb.nn = %lx  pfcb->nn = %lx\n", (ulg)fcb.nn,
  972. X          (ulg)pfcb->nn));
  973. X        Trace((stderr, "flag = %x, drive = %d, vattr = %x\n", fcb.flag,
  974. X          fcb.drive, fcb.vattr));
  975. X        Trace((stderr, "vn = %s = %s.\n", fcb.vn, pfcb->vn));
  976. X        Trace((stderr, "nn = %s = %s.\n", fcb.nn, pfcb->nn));
  977. X        intdosx(®s, ®s, &sregs);
  978. X        if (regs.h.al) {
  979. X            Trace((stderr, "Unable to change volume name (AL = %x)\n",
  980. X              regs.h.al));
  981. X            return 1;
  982. X        } else {
  983. X            Trace((stderr, "volume label changed to [%s]\n", newlabel));
  984. X            return 0;
  985. X        }
  986. X    }
  987. X} /* end function volumelabel() */
  988. X
  989. X#endif /* !__GO32__ && !__EMX__ */
  990. X
  991. X
  992. X
  993. X
  994. X
  995. X/****************************/
  996. X/* Function close_outfile() */
  997. X/****************************/
  998. X
  999. Xvoid close_outfile()
  1000. X /*
  1001. X  * MS-DOS VERSION
  1002. X  *
  1003. X  * Set the output file date/time stamp according to information from the
  1004. X  * zipfile directory record for this member, then close the file and set
  1005. X  * its permissions (archive, hidden, read-only, system).  Aside from closing
  1006. X  * the file, this routine is optional (but most compilers support it).
  1007. X  */
  1008. X{
  1009. X#ifdef __TURBOC__
  1010. X    union {
  1011. X        struct ftime ft;        /* system file time record */
  1012. X        struct {
  1013. X            ush ztime;          /* date and time words */
  1014. X            ush zdate;          /* .. same format as in .ZIP file */
  1015. X        } zt;
  1016. X    } td;
  1017. X#endif
  1018. X
  1019. X
  1020. X/*---------------------------------------------------------------------------
  1021. X    Copy and/or convert time and date variables, if necessary; then set the
  1022. X    file time/date.  WEIRD BORLAND "BUG":  if output is buffered, and if run
  1023. X    under at least some versions of DOS (e.g., 6.0), and if files are smaller
  1024. X    than DOS physical block size (i.e., 512 bytes) (?), then files MAY NOT
  1025. X    get timestamped correctly--apparently setftime() occurs before any data
  1026. X    are written to the file, and when file is closed and buffers are flushed,
  1027. X    timestamp is overwritten with current time.  Even with a 32K buffer, this
  1028. X    does not seem to occur with larger files.  UnZip output is now unbuffered,
  1029. X    but if it were not, could still avoid problem by adding "fflush(outfile)"
  1030. X    just before setftime() call.  Weird, huh?
  1031. X  ---------------------------------------------------------------------------*/
  1032. X
  1033. X#ifdef __TURBOC__
  1034. X    td.zt.ztime = lrec.last_mod_file_time;
  1035. X    td.zt.zdate = lrec.last_mod_file_date;
  1036. X    setftime(fileno(outfile), &td.ft);
  1037. X#else
  1038. X    _dos_setftime(fileno(outfile), lrec.last_mod_file_date,
  1039. X                                   lrec.last_mod_file_time);
  1040. X#endif
  1041. X
  1042. X/*---------------------------------------------------------------------------
  1043. X    And finally we can close the file...at least everybody agrees on how to
  1044. X    do *this*.  I think...  Also change the mode according to the stored file
  1045. X    attributes, since we didn't do that when we opened the dude.
  1046. X  ---------------------------------------------------------------------------*/
  1047. X
  1048. X    fclose(outfile);
  1049. X
  1050. X#ifdef __TURBOC__
  1051. X#   if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0452))
  1052. X#     define Chmod  _rtl_chmod
  1053. X#   else
  1054. X#     define Chmod  _chmod
  1055. X#   endif
  1056. X    if (Chmod(filename, 1, pInfo->file_attr) != pInfo->file_attr)
  1057. X        FPRINTF(stderr, "\nwarning:  file attributes may not be correct\n");
  1058. X#else /* !__TURBOC__ */
  1059. X    _dos_setfileattr(filename, pInfo->file_attr);
  1060. X#endif /* ?__TURBOC__ */
  1061. X
  1062. X} /* end function close_outfile() */
  1063. X
  1064. X
  1065. X
  1066. X
  1067. X
  1068. X#ifndef SFX
  1069. X
  1070. X/*************************/
  1071. X/* Function dateformat() */
  1072. X/*************************/
  1073. X
  1074. Xint dateformat()
  1075. X{
  1076. X
  1077. X/*---------------------------------------------------------------------------
  1078. X    For those operating systems which support it, this function returns a
  1079. X    value which tells how national convention says that numeric dates are
  1080. X    displayed.  Return values are DF_YMD, DF_DMY and DF_MDY (the meanings
  1081. X    should be fairly obvious).
  1082. X  ---------------------------------------------------------------------------*/
  1083. X
  1084. X#ifndef MSWIN
  1085. X#if (!defined(__GO32__) && !defined(__EMX__))
  1086. X    unsigned short _CountryInfo[18];
  1087. X    unsigned short far *CountryInfo = _CountryInfo;
  1088. X    struct SREGS sregs;
  1089. X    union REGS regs;
  1090. X
  1091. X    sregs.ds  = FP_SEG(CountryInfo);
  1092. X    regs.x.dx = FP_OFF(CountryInfo);
  1093. X    regs.x.ax = 0x3800;
  1094. X    int86x(0x21, ®s, ®s, &sregs);
  1095. X
  1096. X#else /* __GO32__ || __EMX__ */
  1097. X    unsigned short CountryInfo[18];
  1098. X
  1099. X    _dos_getcountryinfo(CountryInfo);
  1100. X#endif
  1101. X
  1102. X    switch(CountryInfo[0]) {
  1103. X        case 0:
  1104. X            return DF_MDY;
  1105. X        case 1:
  1106. X            return DF_DMY;
  1107. X        case 2:
  1108. X            return DF_YMD;
  1109. X    }
  1110. X#endif /* !MSWIN */
  1111. X
  1112. X    return DF_MDY;   /* default for systems without locale info */
  1113. X
  1114. X} /* end function dateformat() */
  1115. X
  1116. X
  1117. X
  1118. X
  1119. X
  1120. X/************************/
  1121. X/*  Function version()  */
  1122. X/************************/
  1123. X
  1124. Xvoid version()
  1125. X{
  1126. X    extern char Far  CompiledWith[];
  1127. X#if defined(__WATCOMC__) || defined(__TURBOC__) || defined(_MSC_VER)
  1128. X    char buf[80];
  1129. X#endif
  1130. X
  1131. X    PRINTF(LoadFarString(CompiledWith),
  1132. X
  1133. X#ifdef __GNUC__
  1134. X#  ifdef __EMX__      /* __EMX__ is defined as "1" only (sigh) */
  1135. X      "emx+gcc ",
  1136. X#  else
  1137. X#  ifdef __GO32__     /* ...so is __GO32__ (double sigh) */
  1138. X      "djgpp gcc ",
  1139. X#  else
  1140. X      "gcc ",
  1141. X#  endif
  1142. X#  endif
  1143. X      __VERSION__,
  1144. X#else
  1145. X#ifdef __WATCOMC__
  1146. X      "Watcom C", (sprintf(buf, " (__WATCOMC__ = %d)", __WATCOMC__), buf),
  1147. X#else
  1148. X#ifdef __TURBOC__
  1149. X#  ifdef __BORLANDC__
  1150. X      "Borland C++",
  1151. X#    if (__BORLANDC__ < 0x0200)
  1152. X        " 1.0",
  1153. X#    else
  1154. X#    if (__BORLANDC__ == 0x0200)   /* James:  __TURBOC__ = 0x0297 */
  1155. X        " 2.0",
  1156. X#    else
  1157. X#    if (__BORLANDC__ == 0x0400)
  1158. X        " 3.0",
  1159. X#    else
  1160. X#    if (__BORLANDC__ == 0x0410)   /* __BCPLUSPLUS__ = 0x0310 */
  1161. X        " 3.1",
  1162. X#    else
  1163. X#    if (__BORLANDC__ == 0x0452)   /* __BCPLUSPLUS__ = 0x0320 */
  1164. X        " 4.0 or 4.02",
  1165. X#    else
  1166. X        " later than 4.1",
  1167. X#    endif
  1168. X#    endif
  1169. X#    endif
  1170. X#    endif
  1171. X#    endif
  1172. X#  else
  1173. X      "Turbo C",
  1174. X#    if (__TURBOC__ >= 0x0400)     /* Kevin:  3.0 -> 0x0401 */
  1175. X        "++ 3.0 or later",
  1176. X#    else
  1177. X#    if (__TURBOC__ == 0x0295)     /* [661] vfy'd by Kevin */
  1178. X        "++ 1.0",
  1179. X#    else
  1180. X#    if ((__TURBOC__ >= 0x018d) && (__TURBOC__ <= 0x0200))  /* James: 0x0200 */
  1181. X        " 2.0",
  1182. X#    else
  1183. X#    if (__TURBOC__ > 0x0100)
  1184. X        " 1.5",                    /* James:  0x0105? */
  1185. X#    else
  1186. X        " 1.0",                    /* James:  0x0100 */
  1187. X#    endif
  1188. X#    endif
  1189. X#    endif
  1190. X#    endif
  1191. X#  endif
  1192. X#else
  1193. X#ifdef MSC
  1194. X      "Microsoft C ",
  1195. X#  ifdef _MSC_VER
  1196. X#    if (_MSC_VER == 800)
  1197. X        "8.0/8.0c (Visual C++ 1.0/1.5)",
  1198. X#    else
  1199. X        (sprintf(buf, "%d.%02d", _MSC_VER/100, _MSC_VER%100), buf),
  1200. X#    endif
  1201. X#  else
  1202. X      "5.1 or earlier",
  1203. X#  endif
  1204. X#else
  1205. X      "unknown compiler", "",
  1206. X#endif /* MSC */
  1207. X#endif /* __TURBOC__ */
  1208. X#endif /* __WATCOMC__ */
  1209. X#endif /* __GNUC__ */
  1210. X
  1211. X      "MS-DOS",
  1212. X
  1213. X#if (defined(__GNUC__) || (defined(__WATCOMC__) && defined(__386__)))
  1214. X      " (32-bit)",
  1215. X#else
  1216. X#  if defined(M_I86HM) || defined(__HUGE__)
  1217. X      " (16-bit, huge)",
  1218. X#  else
  1219. X#  if defined(M_I86LM) || defined(__LARGE__)
  1220. X      " (16-bit, large)",
  1221. X#  else
  1222. X#  if defined(M_I86MM) || defined(__MEDIUM__)
  1223. X      " (16-bit, medium)",
  1224. X#  else
  1225. X#  if defined(M_I86CM) || defined(__COMPACT__)
  1226. X      " (16-bit, compact)",
  1227. X#  else
  1228. X#  if defined(M_I86SM) || defined(__SMALL__)
  1229. X      " (16-bit, small)",
  1230. X#  else
  1231. X#  if defined(M_I86TM) || defined(__TINY__)
  1232. X      " (16-bit, tiny)",
  1233. X#  else
  1234. X      " (16-bit)",
  1235. X#  endif
  1236. X#  endif
  1237. X#  endif
  1238. X#  endif
  1239. X#  endif
  1240. X#  endif
  1241. X#endif
  1242. X
  1243. X#ifdef __DATE__
  1244. X      " on ", __DATE__
  1245. X#else
  1246. X      "", ""
  1247. X#endif
  1248. X      );
  1249. X
  1250. X    /* temporary debugging code for Borland compilers only */
  1251. X#ifdef __TURBOC__
  1252. X    PRINTF("\tdebug(__TURBOC__ = 0x%04x = %d)\n", __TURBOC__, __TURBOC__);
  1253. X#ifdef __BORLANDC__
  1254. X    PRINTF("\tdebug(__BORLANDC__ = 0x%04x)\n", __BORLANDC__);
  1255. X#else
  1256. X    PRINTF("\tdebug(__BORLANDC__ not defined)\n");
  1257. X#endif
  1258. X#ifdef __TCPLUSPLUS__
  1259. X    PRINTF("\tdebug(__TCPLUSPLUS__ = 0x%04x)\n", __TCPLUSPLUS__);
  1260. X#else
  1261. X    PRINTF("\tdebug(__TCPLUSPLUS__ not defined)\n");
  1262. X#endif
  1263. X#ifdef __BCPLUSPLUS__
  1264. X    PRINTF("\tdebug(__BCPLUSPLUS__ = 0x%04x)\n\n", __BCPLUSPLUS__);
  1265. X#else
  1266. X    PRINTF("\tdebug(__BCPLUSPLUS__ not defined)\n\n");
  1267. X#endif
  1268. X#endif
  1269. X
  1270. X} /* end function version() */
  1271. X
  1272. X#endif /* !SFX */
  1273. X
  1274. X
  1275. X
  1276. X
  1277. X
  1278. X#if (defined(__GO32__) || defined(__EMX__))
  1279. X
  1280. Xint volatile _doserrno;
  1281. X
  1282. Xunsigned _dos_getcountryinfo(void *countrybuffer)
  1283. X{
  1284. X    asm("movl %0, %%edx": : "g" (countrybuffer));
  1285. X    asm("movl $0x3800, %eax");
  1286. X    asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi");
  1287. X    _doserrno = 0;
  1288. X    asm("jnc 1f");
  1289. X    asm("movl %%eax, %0": "=m" (_doserrno));
  1290. X    asm("1:");
  1291. X    return _doserrno;
  1292. X}
  1293. X
  1294. Xvoid _dos_setftime(int fd, ush dosdate, ush dostime)
  1295. X{
  1296. X    asm("movl %0, %%ebx": : "g" (fd));
  1297. X    asm("movl %0, %%ecx": : "g" (dostime));
  1298. X    asm("movl %0, %%edx": : "g" (dosdate));
  1299. X    asm("movl $0x5701, %eax");
  1300. X    asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi");
  1301. X}
  1302. X
  1303. Xvoid _dos_setfileattr(char *name, int attr)
  1304. X{
  1305. X    asm("movl %0, %%edx": : "g" (name));
  1306. X    asm("movl %0, %%ecx": : "g" (attr));
  1307. X    asm("movl $0x4301, %eax");
  1308. X    asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi");
  1309. X}
  1310. X
  1311. Xvoid _dos_getdrive(unsigned *d)
  1312. X{
  1313. X    asm("movl $0x1900, %eax");
  1314. X    asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi");
  1315. X    asm("xorb %ah, %ah");
  1316. X    asm("incb %al");
  1317. X    asm("movl %%eax, %0": "=a" (*d));
  1318. X}
  1319. X
  1320. Xunsigned _dos_creat(char *path, unsigned attr, int *fd)
  1321. X{
  1322. X    asm("movl $0x3c00, %eax");
  1323. X    asm("movl %0, %%edx": :"g" (path));
  1324. X    asm("movl %0, %%ecx": :"g" (attr));
  1325. X    asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi");
  1326. X    asm("movl %%eax, %0": "=a" (*fd));
  1327. X    _doserrno = 0;
  1328. X    asm("jnc 1f");
  1329. X    _doserrno = *fd;
  1330. X    switch (_doserrno) {
  1331. X    case 3:
  1332. X           errno = ENOENT;
  1333. X           break;
  1334. X    case 4:
  1335. X           errno = EMFILE;
  1336. X           break;
  1337. X    case 5:
  1338. X           errno = EACCES;
  1339. X           break;
  1340. X    }
  1341. X    asm("1:");
  1342. X    return _doserrno;
  1343. X}
  1344. X
  1345. Xunsigned _dos_close(int fd)
  1346. X{
  1347. X    asm("movl %0, %%ebx": : "g" (fd));
  1348. X    asm("movl $0x3e00, %eax");
  1349. X    asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi");
  1350. X    _doserrno = 0;
  1351. X    asm("jnc 1f");
  1352. X    asm ("movl %%eax, %0": "=m" (_doserrno));
  1353. X    if (_doserrno == 6) {
  1354. X          errno = EBADF;
  1355. X    }
  1356. X    asm("1:");
  1357. X    return _doserrno;
  1358. X}
  1359. X
  1360. Xstatic int volumelabel(char *name)
  1361. X{
  1362. X    int fd;
  1363. X
  1364. X    return _dos_creat(name, FA_LABEL, &fd) ? fd : _dos_close(fd);
  1365. X}
  1366. X
  1367. X#endif /* __GO32__ || __EMX__ */
  1368. END_OF_FILE
  1369.   if test 46263 -ne `wc -c <'unzip-5.12/msdos/msdos.c'`; then
  1370.     echo shar: \"'unzip-5.12/msdos/msdos.c'\" unpacked with wrong size!
  1371.   fi
  1372.   # end of 'unzip-5.12/msdos/msdos.c'
  1373. fi
  1374. if test -f 'unzip-5.12/zipinfo.doc' -a "${1}" != "-c" ; then 
  1375.   echo shar: Will not clobber existing file \"'unzip-5.12/zipinfo.doc'\"
  1376. else
  1377.   echo shar: Extracting \"'unzip-5.12/zipinfo.doc'\" \(21079 characters\)
  1378.   sed "s/^X//" >'unzip-5.12/zipinfo.doc' <<'END_OF_FILE'
  1379. X
  1380. XZIPINFO(1L)       MISC. REFERENCE MANUAL PAGES        ZIPINFO(1L)
  1381. X
  1382. XNAME
  1383. X     zipinfo - list detailed information about a ZIP archive
  1384. X
  1385. XSYNOPSIS
  1386. X     zipinfo     [-12smlvhtTz]      file[.zip]      [file(s) ...]
  1387. X     [-x xfile(s) ...]
  1388. X
  1389. X     unzip    -Z    [-12smlvhtTz]    file[.zip]     [file(s) ...]
  1390. X     [-x xfile(s) ...]
  1391. X
  1392. XDESCRIPTION
  1393. X     zipinfo lists technical information about  files  in  a  ZIP
  1394. X     archive, most commonly found on MS-DOS systems.  Such infor-
  1395. X     mation includes file access permissions, encryption  status,
  1396. X     type  of  compression,  version and operating system or file
  1397. X     system of compressing program, and the  like.   The  default
  1398. X     behavior  (with  no  options) is to list single-line entries
  1399. X     for each file in the archive, with header and trailer  lines
  1400. X     providing  summary  information for the entire archive.  The
  1401. X     format is a cross between Unix ``ls -l''  and  ``unzip  -v''
  1402. X     output.   See DETAILED DESCRIPTION below.  Note that zipinfo
  1403. X     is the same program as unzip (under Unix, a link to it);  on
  1404. X     some systems, however, zipinfo support may have been omitted
  1405. X     when unzip was compiled.
  1406. X
  1407. XARGUMENTS
  1408. X     file[.zip]
  1409. X          Path of the ZIP archive(s).  If the file  specification
  1410. X          is  a  wildcard,  each matching file is processed in an
  1411. X          order determined by the operating system (or file  sys-
  1412. X          tem).   Only  the  filename can be a wildcard; the path
  1413. X          itself cannot.  Wildcard  expressions  are  similar  to
  1414. X          Unix egrep(1) (regular) expressions and may contain:
  1415. X
  1416. X          *    matches a sequence of 0 or more characters
  1417. X
  1418. X          ?    matches exactly 1 character
  1419. X
  1420. X          [...]
  1421. X               matches any  single  character  found  inside  the
  1422. X               brackets;  ranges  are  specified  by  a beginning
  1423. X               character, a hyphen, and an ending character.   If
  1424. X               an  exclamation point or a caret (`!' or `^') fol-
  1425. X               lows the left bracket, then the range  of  charac-
  1426. X               ters within the brackets is complemented (that is,
  1427. X               anything except the characters inside the brackets
  1428. X               is considered a match).
  1429. X
  1430. X          (Be sure to quote any character which  might  otherwise
  1431. X          be  interpreted  or  modified  by the operating system,
  1432. X          particularly under Unix and VMS.)  If  no  matches  are
  1433. X          found,  the  specification  is  assumed to be a literal
  1434. X
  1435. XInfo-ZIP         Last change: 28 Aug 94 (v2.02)                 1
  1436. X
  1437. XZIPINFO(1L)       MISC. REFERENCE MANUAL PAGES        ZIPINFO(1L)
  1438. X
  1439. X          filename; and if that also fails, the  suffix  .zip  is
  1440. X          appended.  Note that self-extracting ZIP files are sup-
  1441. X          ported; just specify the .exe suffix  (if  any)  expli-
  1442. X          citly.
  1443. X
  1444. X     [file(s)]
  1445. X          An optional list of archive members  to  be  processed.
  1446. X          Regular  expressions  (wildcards)  may be used to match
  1447. X          multiple members; see above.  Again, be sure  to  quote
  1448. X          expressions  that  would otherwise be expanded or modi-
  1449. X          fied by the operating system.
  1450. X
  1451. X     [-x xfile(s)]
  1452. X          An optional list of archive members to be excluded from
  1453. X          processing.
  1454. X
  1455. XOPTIONS
  1456. X     -1   list  filenames  only,  one  per  line.   This   option
  1457. X          excludes all others; headers, trailers and zipfile com-
  1458. X          ments are never printed.  It is  intended  for  use  in
  1459. X          Unix shell scripts.
  1460. X
  1461. X     -2   list filenames only, one per line,  but  allow  headers
  1462. X          (-h), trailers (-t) and zipfile comments (-z), as well.
  1463. X          This option may be useful in  cases  where  the  stored
  1464. X          filenames are particularly long.
  1465. X
  1466. X     -s   list zipfile info in short Unix ``ls -l'' format.  This
  1467. X          is the default behavior; see below.
  1468. X
  1469. X     -m   list zipfile info in  medium  Unix  ``ls  -l''  format.
  1470. X          Identical to the -s output, except that the compression
  1471. X          factor, expressed as a percentage, is also listed.
  1472. X
  1473. X     -l   list zipfile info in long Unix ``ls  -l''  format.   As
  1474. X          with  -m  except that the compressed size (in bytes) is
  1475. X          printed instead of the compression ratio.
  1476. X
  1477. X     -v   list zipfile information in verbose, multi-page format.
  1478. X
  1479. X     -h   list header line.  The archive name,  actual  size  (in
  1480. X          bytes) and total number of files is printed.
  1481. X
  1482. X     -t   list totals for files listed or  for  all  files.   The
  1483. X          number   of   files   listed,  their  uncompressed  and
  1484. X          compressed total sizes, and their  overall  compression
  1485. X          factor is printed; or, if only the totals line is being
  1486. X          printed, the values for the entire archive  are  given.
  1487. X          Note  that  the total compressed (data) size will never
  1488. X          match  the  actual  zipfile  size,  since  the   latter
  1489. X          includes  all  of the internal zipfile headers in addi-
  1490. X          tion to the compressed data.
  1491. X
  1492. XInfo-ZIP         Last change: 28 Aug 94 (v2.02)                 2
  1493. X
  1494. XZIPINFO(1L)       MISC. REFERENCE MANUAL PAGES        ZIPINFO(1L)
  1495. X
  1496. X     -T   print the file dates and times in  a  sortable  decimal
  1497. X          format  (yymmdd.hhmmss).   The default date format is a
  1498. X          more standard, human-readable version with  abbreviated
  1499. X          month names (see examples below).
  1500. X
  1501. X     -z   include the archive comment (if any) in the listing.
  1502. X
  1503. XDETAILED DESCRIPTION
  1504. X     zipinfo has a number of  modes,  and  its  behavior  can  be
  1505. X     rather  difficult  to fathom if one isn't familiar with Unix
  1506. X     ls(1) (or even if one is).  The default behavior is to  list
  1507. X     files in the following format:
  1508. X
  1509. X-rw-rws---  1.9 unx    2802 t- defX 11-Aug-91 13:48 perms.2660
  1510. X
  1511. X     The last three fields are the modification date and time  of
  1512. X     the  file,  and  its  name.   The  case  of  the filename is
  1513. X     respected; thus files  which  come  from  MS-DOS  PKZIP  are
  1514. X     always  capitalized.   If  the file was zipped with a stored
  1515. X     directory name, that  is  also  displayed  as  part  of  the
  1516. X     filename.
  1517. X
  1518. X     The second and third  fields  indicate  that  the  file  was
  1519. X     zipped  under  Unix with version 1.9 of zip.  Since it comes
  1520. X     from Unix, the file permissions at the beginning of the line
  1521. X     are  printed  in  Unix  format.   The uncompressed file-size
  1522. X     (2802 in this example) is the fourth field.
  1523. X
  1524. X     The fifth field consists of two characters, either of  which
  1525. X     may  take  on  several  values.   The first character may be
  1526. X     either `t' or `b', indicating that zip believes the file  to
  1527. X     be  text  or  binary,  respectively;  but  if  the  file  is
  1528. X     encrypted, zipinfo notes this fact by capitalizing the char-
  1529. X     acter  (`T'  or `B').  The second character may also take on
  1530. X     four values, depending on whether there is an extended local
  1531. X     header  and/or  an  ``extra field'' associated with the file
  1532. X     (fully explained  in  PKWare's  APPNOTE.TXT,  but  basically
  1533. X     analogous  to  pragmas in ANSI C--i.e., they provide a stan-
  1534. X     dard  way  to  include  non-standard  information   in   the
  1535. X     archive).  If neither exists, the character will be a hyphen
  1536. X     (`-'); if there is an extended local  header  but  no  extra
  1537. X     field,  `l';  if  the  reverse, `x'; and if both exist, `X'.
  1538. X     Thus the file in this example is (probably) a text file,  is
  1539. X     not  encrypted,  and  has  neither  an  extra  field  nor an
  1540. X     extended local  header  associated  with  it.   The  example
  1541. X     below,  on  the other hand, is an encrypted binary file with
  1542. X     an extra field:
  1543. X
  1544. XRWD,R,R     0.9 vms     168 Bx shrk  9-Aug-91 19:15 perms.0644
  1545. X
  1546. X     Extra fields are used for various purposes  (see  discussion
  1547. X     of  the  -v  option below) including the storage of VMS file
  1548. X
  1549. XInfo-ZIP         Last change: 28 Aug 94 (v2.02)                 3
  1550. X
  1551. XZIPINFO(1L)       MISC. REFERENCE MANUAL PAGES        ZIPINFO(1L)
  1552. X
  1553. X     attributes, which is presumably the case  here.   Note  that
  1554. X     the  file  attributes  are listed in VMS format.  Some other
  1555. X     possibilities for the host operating system (which is  actu-
  1556. X     ally  a  misnomer--host file system is more correct) include
  1557. X     OS/2 or NT with High Performance File System (HPFS), MS-DOS,
  1558. X     OS/2 or NT with File Allocation Table (FAT) file system, and
  1559. X     Macintosh.  These are denoted as follows:
  1560. X
  1561. X-rw-a--     1.0 hpf    5358 Tl i4:3  4-Dec-91 11:33 longfilename.hpfs
  1562. X-r--ahs     1.1 fat    4096 b- i4:2 14-Jul-91 12:58 EA DATA. SF
  1563. X--w-------  1.0 mac   17357 bx i8:2  4-May-92 04:02 unzip.macr
  1564. X
  1565. X     File attributes in the first two cases are  indicated  in  a
  1566. X     Unix-like format, where the seven subfields indicate whether
  1567. X     the file:  (1) is  a  directory,  (2)  is  readable  (always
  1568. X     true),  (3)  is  writable, (4) is executable (guessed on the
  1569. X     basis of the extension--.exe,  .com,  .bat,  .cmd  and  .btm
  1570. X     files  are  assumed  to be so), (5) has its archive bit set,
  1571. X     (6) is hidden, and (7) is a system file.  Interpretation  of
  1572. X     Macintosh  file attributes is unreliable because some Macin-
  1573. X     tosh archivers don't store any attributes in the archive.
  1574. X
  1575. X     Finally, the sixth field indicates  the  compression  method
  1576. X     and  possible  sub-method used.  There are six methods known
  1577. X     at present:  storing (no compression), reducing,  shrinking,
  1578. X     imploding, tokenizing (never publicly released), and deflat-
  1579. X     ing.  In addition, there are  four  levels  of  reducing  (1
  1580. X     through  4);  four types of imploding (4K or 8K sliding dic-
  1581. X     tionary, and 2 or 3 Shannon-Fano trees); and four levels  of
  1582. X     deflating  (superfast,  fast,  normal, maximum compression).
  1583. X     zipinfo represents these methods and  their  sub-methods  as
  1584. X     follows:   stor;  re:1,  re:2, etc.; shrk; i4:2, i8:3, etc.;
  1585. X     tokn; and defS, defF, defN, and defX.
  1586. X
  1587. X     The medium and long listings are  almost  identical  to  the
  1588. X     short  format except that they add information on the file's
  1589. X     compression.  The medium format lists the file's compression
  1590. X     factor  as a percentage indicating the amount of space which
  1591. X     has been ``removed'':
  1592. X
  1593. X-rw-rws---  1.5 unx    2802 t- 81% defX 11-Aug-91 13:48 perms.2660
  1594. X
  1595. X     In this example, the file has been compressed by more than a
  1596. X     factor of five; the compressed data are only 19% of the ori-
  1597. X     ginal size.  The long format  gives  the  compressed  file's
  1598. X     size in bytes, instead:
  1599. X
  1600. X-rw-rws---  1.5 unx    2802 t-     538 defX 11-Aug-91 13:48 perms.2660
  1601. X
  1602. X     Adding the -T option changes  the  file  date  and  time  to
  1603. X     decimal format:
  1604. X
  1605. XInfo-ZIP         Last change: 28 Aug 94 (v2.02)                 4
  1606. X
  1607. XZIPINFO(1L)       MISC. REFERENCE MANUAL PAGES        ZIPINFO(1L)
  1608. X
  1609. X-rw-rws---  1.5 unx    2802 t-     538 defX 910811.134804 perms.2660
  1610. X
  1611. X     Note that because of limitations in the MS-DOS  format  used
  1612. X     to  store file times, the seconds field is always rounded to
  1613. X     the nearest even second.  For Unix files this is expected to
  1614. X     change in the next major releases of zip(1L) and unzip.
  1615. X
  1616. X     In addition to individual file information, a  default  zip-
  1617. X     file listing also includes header and trailer lines:
  1618. X
  1619. XArchive:  OS2.zip   5453 bytes   5 files
  1620. X,,rw,       1.0 hpf     730 b- i4:3 26-Jun-92 23:40 Contents
  1621. X,,rw,       1.0 hpf    3710 b- i4:3 26-Jun-92 23:33 makefile.os2
  1622. X,,rw,       1.0 hpf    8753 b- i8:3 26-Jun-92 15:29 os2unzip.c
  1623. X,,rw,       1.0 hpf      98 b- stor 21-Aug-91 15:34 unzip.def
  1624. X,,rw,       1.0 hpf      95 b- stor 21-Aug-91 17:51 zipinfo.def
  1625. X5 files, 13386 bytes uncompressed, 4951 bytes compressed:  63.0%
  1626. X
  1627. X     The header line gives the name of  the  archive,  its  total
  1628. X     size,  and  the total number of files; the trailer gives the
  1629. X     number of files listed, their total uncompressed  size,  and
  1630. X     their  total  compressed  size  (not  including any of zip's
  1631. X     internal overhead).  If, however, one or  more  file(s)  are
  1632. X     provided, the header and trailer lines are not listed.  This
  1633. X     behavior is also similar to that of Unix's ``ls -l''; it may
  1634. X     be  overridden  by  specifying  the -h and -t options expli-
  1635. X     citly.  In such a case  the  listing  format  must  also  be
  1636. X     specified  explicitly,  since  -h  or  -t  (or  both) in the
  1637. X     absence of other options implies that  ONLY  the  header  or
  1638. X     trailer  line (or both) is listed.  See the EXAMPLES section
  1639. X     below for a semi-intelligible translation of this nonsense.
  1640. X
  1641. X     The verbose listing is  mostly  self-explanatory.   It  also
  1642. X     lists file comments and the zipfile comment, if any, and the
  1643. X     type and  number  of  bytes  in  any  stored  extra  fields.
  1644. X     Currently  known  types  of  extra  fields  include PKWARE's
  1645. X     authentication (``AV'') info; OS/2 extended attributes;  VMS
  1646. X     filesystem  info,  both PKWARE and Info-ZIP versions; Macin-
  1647. X     tosh resource forks; Acorn/Archimedes SparkFS info;  and  so
  1648. X     on.   (Note  that  in the case of OS/2 extended attributes--
  1649. X     perhaps the most common use  of  zipfile  extra  fields--the
  1650. X     size  of the stored EAs as reported by zipinfo may not match
  1651. X     the number given by OS/2's dir command: OS/2 always  reports
  1652. X     the  number  of  bytes  required  in  16-bit format, whereas
  1653. X     zipinfo always reports the 32-bit storage.)
  1654. X
  1655. XENVIRONMENT OPTIONS
  1656. X     Modifying zipinfo's default behavior via options  placed  in
  1657. X     an environment variable can be a bit complicated to explain,
  1658. X     due to zipinfo's attempts to handle various defaults  in  an
  1659. X     intuitive,  yet  Unix-like,  manner.   (Try  not  to laugh.)
  1660. X     Nevertheless, there is some  underlying  logic.   In  brief,
  1661. X
  1662. XInfo-ZIP         Last change: 28 Aug 94 (v2.02)                 5
  1663. X
  1664. XZIPINFO(1L)       MISC. REFERENCE MANUAL PAGES        ZIPINFO(1L)
  1665. X
  1666. X     there are three ``priority levels'' of options:  the default
  1667. X     options; environment options, which can override or  add  to
  1668. X     the  defaults; and explicit options given by the user, which
  1669. X     can override or add to either of the above.
  1670. X
  1671. X     The default listing  format,  as  noted  above,  corresponds
  1672. X     roughly  to  the "zipinfo -hst" command (except when indivi-
  1673. X     dual zipfile members are specified).  A user who prefers the
  1674. X     long-listing  format  (-l)  can  make  use  of the zipinfo's
  1675. X     environment variable to change this default:
  1676. X
  1677. X         ZIPINFO=-l; export ZIPINFO    Unix Bourne shell
  1678. X         setenv ZIPINFO -l             Unix C shell
  1679. X         set ZIPINFO=-l                OS/2 or MS-DOS
  1680. X         define ZIPINFO_OPTS "-l"      VMS (quotes for lowercase)
  1681. X
  1682. X     If,  in  addition,  the  user  dislikes  the  trailer  line,
  1683. X     zipinfo's  concept  of  ``negative  options'' may be used to
  1684. X     override the default inclusion of the line.  This is  accom-
  1685. X     plished  by  preceding the undesired option with one or more
  1686. X     minuses:  e.g., ``-l-t'' or ``--tl'', in this example.   The
  1687. X     first  hyphen  is  the regular switch character, but the one
  1688. X     before the `t' is a minus sign.  The dual use of hyphens may
  1689. X     seem   a  little  awkward,  but  it's  reasonably  intuitive
  1690. X     nonetheless:  simply ignore the first  hyphen  and  go  from
  1691. X     there.   It is also consistent with the behavior of the Unix
  1692. X     command nice(1).
  1693. X
  1694. X     As  suggested  above,  the  default   variable   names   are
  1695. X     ZIPINFO_OPTS  for  VMS  (where  the  symbol  used to install
  1696. X     zipinfo as a foreign command  would  otherwise  be  confused
  1697. X     with  the  environment  variable), and ZIPINFO for all other
  1698. X     operating systems.  For compatibility with  zip(1L),  ZIPIN-
  1699. X     FOOPT  is  also  accepted  (don't ask).  If both ZIPINFO and
  1700. X     ZIPINFOOPT are defined, however, ZIPINFO  takes  precedence.
  1701. X     unzip's  diagnostic  option (-v with no zipfile name) can be
  1702. X     used to check the values of  all  four  possible  unzip  and
  1703. X     zipinfo environment variables.
  1704. X
  1705. XEXAMPLES
  1706. X     To get a basic, short-format listing of  the  complete  con-
  1707. X     tents  of  a  ZIP  archive storage.zip, with both header and
  1708. X     totals lines, use only the archive name as  an  argument  to
  1709. X     zipinfo:
  1710. X
  1711. X         zipinfo storage
  1712. X
  1713. X     To produce  a  basic,  long-format  listing  (not  verbose),
  1714. X     including header and totals lines, use -l:
  1715. X
  1716. X         zipinfo -l storage
  1717. X
  1718. XInfo-ZIP         Last change: 28 Aug 94 (v2.02)                 6
  1719. X
  1720. XZIPINFO(1L)       MISC. REFERENCE MANUAL PAGES        ZIPINFO(1L)
  1721. X
  1722. X     To list the complete contents of the archive without  header
  1723. X     and  totals  lines,  either  negate the -h and -t options or
  1724. X     else specify the contents explicitly:
  1725. X
  1726. X         zipinfo --h-t storage
  1727. X         zipinfo storage \*
  1728. X
  1729. X     (where the backslash is required only  if  the  shell  would
  1730. X     otherwise  expand the `*' wildcard, as in Unix when globbing
  1731. X     is turned on--double quotes around the asterisk  would  have
  1732. X     worked  as  well).   To turn off the totals line by default,
  1733. X     use the environment variable (C shell is assumed here):
  1734. X
  1735. X         setenv ZIPINFO --t
  1736. X         zipinfo storage
  1737. X
  1738. X     To get the full, short-format listing of the  first  example
  1739. X     again,  given that the environment variable is set as in the
  1740. X     previous example, it is necessary to specify the  -s  option
  1741. X     explicitly,  since the -t option by itself implies that ONLY
  1742. X     the footer line is to be printed:
  1743. X
  1744. X         setenv ZIPINFO --t
  1745. X         zipinfo -t storage            [only totals line]
  1746. X         zipinfo -st storage           [full listing]
  1747. X
  1748. X     The -s option, like -m and -l, includes headers and  footers
  1749. X     by  default, unless otherwise specified.  Since the environ-
  1750. X     ment variable specified no footers and  that  has  a  higher
  1751. X     precedence  than  the default behavior of -s, an explicit -t
  1752. X     option was necessary to produce the full  listing.   Nothing
  1753. X     was  indicated  about  the header, however, so the -s option
  1754. X     was sufficient.  Note that both the -h and -t options,  when
  1755. X     used  by themselves or with each other, override any default
  1756. X     listing of member files; only the header and/or  footer  are
  1757. X     printed.   This behavior is useful when zipinfo is used with
  1758. X     a wildcard zipfile specification; the contents of  all  zip-
  1759. X     files are then summarized with a single command.
  1760. X
  1761. X     To list information on a single file within the archive,  in
  1762. X     medium format, specify the filename explicitly:
  1763. X
  1764. X         zipinfo -m storage unshrink.c
  1765. X
  1766. X     The specification of any member file, as  in  this  example,
  1767. X     will  override the default header and totals lines; only the
  1768. X     single line of information about the requested file will  be
  1769. X     printed.   This  is  intuitively  what one would expect when
  1770. X     requesting information about a single  file.   For  multiple
  1771. X     files,  it  is often useful to know the total compressed and
  1772. X     uncompressed size; in such cases -t may be specified  expli-
  1773. X     citly:
  1774. X
  1775. XInfo-ZIP         Last change: 28 Aug 94 (v2.02)                 7
  1776. X
  1777. XZIPINFO(1L)       MISC. REFERENCE MANUAL PAGES        ZIPINFO(1L)
  1778. X
  1779. X         zipinfo -mt storage "*.[ch]" Mak\*
  1780. X
  1781. X     To get maximal information about the ZIP  archive,  use  the
  1782. X     verbose  option.  It is usually wise to pipe the output into
  1783. X     a filter such as Unix more(1) if the operating system allows
  1784. X     it:
  1785. X
  1786. X         zipinfo -v storage | more
  1787. X
  1788. X     Finally, to see the most  recently  modified  files  in  the
  1789. X     archive,  use  the -T option in conjunction with an external
  1790. X     sorting utility such as Unix sort(1) (and tail(1)  as  well,
  1791. X     in this example):
  1792. X
  1793. X         zipinfo -T storage | sort -n +6 | tail -15
  1794. X
  1795. X     The -n option to sort(1) tells it to sort numerically rather
  1796. X     than  in  ASCII order, and the +6 option tells it to sort on
  1797. X     the sixth field after  the  first  one  (i.e.,  the  seventh
  1798. X     field).   This  assumes the default short-listing format; if
  1799. X     -m or -l is used, the proper sort(1)  option  would  be  +7.
  1800. X     The tail(1) command filters out all but the last 15 lines of
  1801. X     the listing.  Future releases  of  zipinfo  may  incorporate
  1802. X     date/time and filename sorting as built-in options.
  1803. X
  1804. XTIPS
  1805. X     The author finds it convenient to define  an  alias  ii  for
  1806. X     zipinfo  on  systems  which allow aliases (or, on other sys-
  1807. X     tems, copy/rename the executable, create a link or create  a
  1808. X     command  file with the name ii).  The ii usage parallels the
  1809. X     common ll alias for long listings in Unix, and the  similar-
  1810. X     ity between the outputs of the two commands was intentional.
  1811. X
  1812. XBUGS
  1813. X     None known at this time, but we're always delighted to  find
  1814. X     a good one.
  1815. X
  1816. XSEE ALSO
  1817. X     ls(1),   funzip(1L),   unzip(1L),   unzipsfx(1L),   zip(1L),
  1818. X     zipcloak(1L), zipnote(1L), zipsplit(1L)
  1819. X
  1820. XAUTHOR
  1821. X     Greg Roelofs (a.k.a. Cave Newt).  ZipInfo contains  pattern-
  1822. X     matching  code  by Mark Adler and fixes/improvements by many
  1823. X     others.  Please refer to the  CONTRIBS  file  in  the  UnZip
  1824. X     source distribution for a more complete list.
  1825. X
  1826. XInfo-ZIP         Last change: 28 Aug 94 (v2.02)                 8
  1827. X
  1828. END_OF_FILE
  1829.   if test 21079 -ne `wc -c <'unzip-5.12/zipinfo.doc'`; then
  1830.     echo shar: \"'unzip-5.12/zipinfo.doc'\" unpacked with wrong size!
  1831.   fi
  1832.   # end of 'unzip-5.12/zipinfo.doc'
  1833. fi
  1834. echo shar: End of archive 7 \(of 20\).
  1835. cp /dev/null ark7isdone
  1836. MISSING=""
  1837. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
  1838.     if test ! -f ark${I}isdone ; then
  1839.     MISSING="${MISSING} ${I}"
  1840.     fi
  1841. done
  1842. if test "${MISSING}" = "" ; then
  1843.     echo You have unpacked all 20 archives.
  1844.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1845. else
  1846.     echo You still must unpack the following archives:
  1847.     echo "        " ${MISSING}
  1848. fi
  1849. exit 0
  1850. exit 0 # Just in case...
  1851.