home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3612 < prev    next >
Encoding:
Text File  |  1991-07-11  |  35.3 KB  |  1,102 lines

  1. Newsgroups: alt.sources
  2. Subject: zoo 2.1 source part 15/15
  3. Message-ID: <12782@bsu-cs.bsu.edu>
  4. From: dhesi@bsu-cs.bsu.edu (Rahul Dhesi)
  5. Date: 10 Jul 91 12:05:22 GMT
  6.  
  7. Checksum: 1510081511 (verify with "brik -cv")
  8. Submitted-by: dhesi@bsu-cs.bsu.edu
  9. Archive-name: zoo210/part15
  10.  
  11. ---- Cut Here and feed the following to sh ----
  12. #!/bin/sh
  13. # This is part 15 of zoo210
  14. # ============= zoolist.c ==============
  15. if test -f 'zoolist.c' -a X"$1" != X"-c"; then
  16.     echo 'x - skipping zoolist.c (File already exists)'
  17. else
  18. echo 'x - extracting zoolist.c (Text)'
  19. sed 's/^X//' << 'SHAR_EOF' > 'zoolist.c' &&
  20. #ifndef LINT
  21. /* derived from: zoolist.c 2.27 88/08/15 11:03:16 */
  22. static char sccsid[]="$Source: /usr/home/dhesi/zoo/RCS/zoolist.c,v $\n\
  23. $Id: zoolist.c,v 1.4 91/07/09 01:54:16 dhesi Exp $";
  24. #endif /* LINT */
  25. X
  26. /*
  27. If TRACE_LIST is defined, any list command may be followed
  28. by 'D' to show verbose information about each directory
  29. entry in the archive.   Do not define both TRACE_LIST and
  30. TRACE_IO else a symbol conflict will occur and in any case
  31. duplicate information will be dumped.
  32. */
  33. X
  34. /* #define TRACE_LIST */
  35. X
  36. /*
  37. Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  38. (C) Copyright 1988 Rahul Dhesi -- All rights reserved
  39. */
  40. #include "options.h"
  41. #include "portable.h"
  42. #include "zoomem.h"  /* to get ZOOCOUNT */
  43. X
  44. /* Lists files in archive */
  45. #include "zoo.h"
  46. #include "errors.i"
  47. #include "zooio.h"
  48. #include "various.h"
  49. #include "zoofns.h"
  50. X
  51. #ifdef TRACE_LIST
  52. void show_dir PARMS ((struct direntry *direntry));
  53. static int trace_list = 0;
  54. #endif /* TRACE_LIST */
  55. X
  56. static char tot_fmt[] = "%8lu %3u%% %8lu  %4d file";
  57. static char tot_line[] =
  58. X   /* "------------  --------  ---  --------  --------- --------\n"; */
  59. X   "--------  --- --------  --------- --------\n";
  60. X
  61. static char dbl_percent[] = "Archive %s:  %s";
  62. X
  63. extern int quiet;                /* assumed initialized to zero */
  64. X
  65. void show_comment PARMS((struct direntry *, ZOOFILE, int, char *));
  66. int ver_too_high PARMS((struct zoo_header *));
  67. int needed PARMS((char *, struct direntry *, struct zoo_header *));
  68. void printtz PARMS((int));
  69. X
  70. void zoolist (argv, option, argc)
  71. char **argv, *option;
  72. int argc;
  73. {
  74. char whichname[PATHSIZE];  /* which name to use */
  75. char *this_zoo;            /* currently matched archive name */
  76. register ZOOFILE zoo_file;
  77. char *flist[ZOOCOUNT];       /* list of ptrs to input archive names */
  78. int fptr;                  /* will point to within list of archive names */
  79. X
  80. struct direntry direntry;
  81. struct zoo_header zoo_header;
  82. int size_factor;
  83. unsigned long tot_org_siz = 0L, tot_siz_now = 0L;
  84. int   tot_sf;
  85. int file_count = 0;
  86. int del_count = 0;                  /* number of deleted entries */
  87. int bad_pack;                 /* 1 if packing method is unknown */
  88. static char *month_list="000JanFebMarAprMayJunJulAugSepOctNovDec";
  89. static char dashes[] = "------------\n";
  90. int year, month, day, hours, min, sec;
  91. int list_deleted = 0;         /* list deleted files too */
  92. int fast = 0;                 /* fast list */
  93. long fiz_ofs = 0;             /* offset where to start */
  94. long dat_ofs = 0;             /* ... data offset of file data */
  95. int verb_list = 0;            /* if verbose listing needed */
  96. int show_name = 0;            /* if archive name to be included in listing */
  97. int show_crc = 0;                    /* if crc should be listed */
  98. int zoocount = 1;             /* number of archives to list */
  99. int biglist = 0;              /* multiarchive listing */
  100. int one_col = 0;                    /* one column listing requested */
  101. int showdir = 0;                    /* show directory name in fast listing */
  102. int longest;                  /* length of longest archive name */
  103. int talking;                        /* opposite of quiet */
  104. int column = 0;               /* for column printing */
  105. int first_ever = 1;                /* first time ever -- very special case */
  106. int neednl = 0;                    /* whether to print a newline */
  107. int need_acmt = 0;                /* show archive comment */
  108. int show_gen = 0;                    /* show generation count */
  109. int genson = 1;                    /* enable/disable generations */
  110. #ifdef FATTR
  111. int show_mode = 0;                /* show file protection */
  112. #endif
  113. int first_dir = 1;                /* if first direntry -- to adjust dat_ofs */
  114. X
  115. while (*option) {
  116. X   switch (*option) {
  117. X      case 'a': show_name++; break;
  118. #ifdef TRACE_LIST
  119. X        case 'D': trace_list++; break;
  120. #endif /* TRACE_LIST */
  121. X      case 'd': list_deleted++; break;
  122. X      case 'f': fast++; break;
  123. X        case 'g': show_gen++; break;
  124. X        case '/': showdir++; break;
  125. X        case 'A':
  126. X        case 'v': need_acmt++; break;
  127. X      case 'V': need_acmt++; /* fall through */
  128. X      case 'c': verb_list++; break;
  129. X        case 'C': show_crc++; break;
  130. X      case 'l': break;
  131. X      case 'L': biglist++; zoocount = argc; break;
  132. #ifdef FATTR
  133. X        case 'm': show_mode++; break;
  134. #endif
  135. X        case '1': one_col++; break;
  136. X        case '+': genson = 1; break;
  137. X        case '-': genson = 0; break;
  138. X        /* following code same as in zooext.c */
  139. X      case '@':     /* if @m,n specified, fiz_ofs = m, dat_ofs = n */
  140. X            {
  141. X                char *comma_pos;
  142. X                ++option;
  143. X                comma_pos = strchr(option, ',');
  144. X                if (comma_pos != NULL) {
  145. X                    dat_ofs = calc_ofs (comma_pos + 1);
  146. X                    *comma_pos = '\0';
  147. X                }
  148. X                fiz_ofs = calc_ofs(option); 
  149. X                goto no_more;
  150. X            }
  151. X        case 'q': quiet++; break;
  152. X      default:
  153. X         prterror ('w', option_ignored, *option);
  154. X   }
  155. X   option++;
  156. }
  157. X
  158. no_more:  /* come from exit from while loop above */
  159. X
  160. if (fast && show_name) {      /* don't allow 'a' with 'f' */
  161. X   show_name = 0;
  162. X   prterror ('w', option_ignored, 'a');
  163. }
  164. X
  165. talking = !quiet;                    /* for convenience */
  166. X
  167. #ifdef WILDCARD
  168. X   /* For each archive name supplied, if it is not a char range and
  169. X      does not contain a dot, append "*.zoo". */
  170. X   {
  171. X      int i;
  172. X      for (i = 0; i < argc;  i++) {
  173. X         if (strchr (nameptr (argv[i]), EXT_CH) == NULL && 
  174. X                           !match_half (nameptr (argv[0]), "?-?"))
  175. X            argv[i] = newcat (argv[i], "*.zoo");
  176. X      }
  177. X   }
  178. #endif
  179. X
  180. makelist (zoocount, argv, flist,        ZOOCOUNT-2,   (char *) NULL,".","..", &longest);
  181. /*        ^argc     ^argv ^list_pointer ^max_no_files   ^exclude */
  182. X
  183. for (fptr = 0;  (this_zoo = flist[fptr]) != NULL; fptr++) {
  184. X   int ercount;                  /* count of errors */
  185. X   int entrycount;               /* count of directory entries */
  186. X   int expl_deleted;             /* explain what D means */
  187. X   int expl_comment;             /* explain what comment means */
  188. X   int expl_ver;                 /* Explain what V means */
  189. X   int expl_star;                /* Explain what * means */
  190. X   int first_time;               /* first time through loop for an archive */
  191. X
  192. X   ercount = entrycount = del_count =
  193. X      expl_deleted = expl_comment = expl_ver = expl_star = 0;
  194. X
  195. X    if (talking)
  196. X        column = 0;                        /* if quiet, names will run together */
  197. X
  198. X   first_time = 1;
  199. X
  200. #ifndef WILDCARD
  201. X   /* Add default extension if none supplied */
  202. X   if (strchr (nameptr (this_zoo), EXT_CH) == NULL)
  203. X      this_zoo = newcat (this_zoo, EXT_DFLT);
  204. #endif
  205. X
  206. X   zoo_file = zooopen (this_zoo, Z_READ);
  207. X
  208. X   if (zoo_file == NOFILE) {
  209. X      prterror ('e', could_not_open, this_zoo);
  210. X      continue;
  211. X   } else if (!show_name && talking)
  212. X      printf ("\nArchive %s:\n", this_zoo);
  213. X   
  214. if (fiz_ofs != 0L) {                /* if offset specified, start there */
  215. X    prterror ('m', start_ofs, fiz_ofs, dat_ofs);
  216. X   zooseek (zoo_file, fiz_ofs, 0);
  217. } else {
  218. X   if (frd_zooh (&zoo_header, zoo_file) == -1 ||
  219. X                                             zoo_header.zoo_tag != ZOO_TAG) {
  220. X      prterror ('e', dbl_percent, this_zoo, invalid_header);
  221. X      goto loop_end;
  222. X   }
  223. #if 0
  224. X    if (talking && (!show_name || verb_list || need_acmt))
  225. #else
  226. X    if (need_acmt && talking)
  227. #endif
  228. X    {
  229. X        void show_acmt PARMS ((struct zoo_header *, ZOOFILE, int));
  230. X        show_acmt (&zoo_header, zoo_file, 0);        /* show archive comment */
  231. X    }
  232. X
  233. X   /* Seek to the beginning of the first directory entry */
  234. X   if (zooseek (zoo_file, zoo_header.zoo_start, 0) != 0) {
  235. X      ercount++;
  236. X      prterror ('e', dbl_percent, this_zoo, bad_directory);
  237. X      goto loop_end;
  238. X   }
  239. X   if (!show_name && ver_too_high (&zoo_header)) {
  240. X      ercount++;
  241. X      if (ercount < 2)
  242. X         prterror ('M', wrong_version, 
  243. X                                        zoo_header.major_ver, zoo_header.minor_ver);
  244. X   }
  245. } /* end if (fiz_ofs !- 0L) */
  246. X
  247. X   /* Now we print information about each file in the archive */
  248. X   
  249. X   if (!show_name) { /* initialize for each file only if not disk catalog */
  250. X      tot_org_siz = 0L;  
  251. X      tot_siz_now = 0L;
  252. X      file_count = 0;
  253. X      del_count = 0;
  254. X   }
  255. X
  256. X   while (1) {
  257. X      if (readdir (&direntry, zoo_file, 0) == -1) {
  258. X         prterror ('F', dbl_percent, this_zoo, bad_directory);
  259. X         goto givesummary;
  260. X      }
  261. X      if (direntry.zoo_tag != ZOO_TAG) {
  262. X         long currpos, zoolength;
  263. X         prterror ('F', dbl_percent, this_zoo, invalid_header);
  264. X         if ((currpos = zootell (zoo_file)) != -1L)
  265. X            if (zooseek (zoo_file, 0L, 2) == 0)
  266. X               if ((zoolength = zootell (zoo_file)) != -1L)
  267. X                  printf (cant_process, zoolength - currpos);              
  268. X         goto givesummary;
  269. X      }
  270. X   
  271. X      if (direntry.next == 0L)      /* EXIT on end of chain */
  272. X         break;                                 
  273. X      else
  274. X         entrycount++;              /* Number of directory entries */
  275. X        /* first direntry read, change dat_ofs from abs. pos. to rel. offset */
  276. X        if (first_dir && dat_ofs != 0) {
  277. X            dat_ofs -= direntry.offset;
  278. X            first_dir = 0;
  279. X        }
  280. X        direntry.next += dat_ofs;                /* allow for user-specified offset */
  281. X        if (direntry.comment != 0L)
  282. X            direntry.comment += dat_ofs;        /* so show_comment finds it */
  283. X   
  284. X      if (direntry.deleted)
  285. X         ++del_count;
  286. X
  287. #ifdef TRACE_LIST
  288. X        if (trace_list)
  289. X            show_dir (&direntry);
  290. #endif /* TRACE_LIST */
  291. X      
  292. X        /* Into `whichname' put the filename to display. Use long filename if 
  293. X        it exists, else use short filename.  */
  294. X            strcpy (whichname, fullpath (&direntry));
  295. X            if (zoo_header.vdata & VFL_ON)
  296. X                add_version (whichname, &direntry);    /* add version suffix */
  297. #ifdef DEBUG
  298. X      printf("matching against [%s] and [%s]\n", 
  299. X               nameptr(whichname), whichname);
  300. #endif
  301. X
  302. X      if ( ( (list_deleted && direntry.deleted) ||
  303. X               (list_deleted < 2 && !direntry.deleted)
  304. X           ) 
  305. X              && (biglist || needed(whichname, &direntry, &zoo_header))) {
  306. X            /* if generations forced off, then strip added version field */
  307. X            if (!genson) {    /* HORRENDOUSLY INEFFICIENT AND REPETITIOUS */
  308. X                char *ver_pos;
  309. X                ver_pos = findlast (whichname, VER_DISPLAY);
  310. X                if (ver_pos != NULL)
  311. X                    *ver_pos = '\0';
  312. X            }
  313. X   
  314. X         file_count++;
  315. X   
  316. X         if (direntry.packing_method > MAX_PACK) {
  317. X            bad_pack = 1;
  318. X            expl_ver = 1;
  319. X         }  else
  320. X            bad_pack = 0;
  321. X      
  322. X         size_factor = cfactor (direntry.org_size, direntry.size_now);
  323. X   
  324. X         year  =  ((unsigned int) direntry.date >> 9) & 0x7f;
  325. X         month =  ((unsigned int) direntry.date >> 5) & 0x0f;
  326. X         day   =  direntry.date        & 0x1f;
  327. X   
  328. X         hours =  ((unsigned int) direntry.time >> 11)& 0x1f;
  329. X         min   =  ((unsigned int) direntry.time >> 5) & 0x3f;
  330. X         sec   =  ((unsigned int) direntry.time & 0x1f) * 2;
  331. X   
  332. X            /* Alignment in columns is a horrendously complex undertaking. */
  333. X
  334. X         if (fast) {
  335. X                int space_left;
  336. X                int namelen;
  337. X                int next_col;
  338. #if 0
  339. X            if ( (quiet && !first_ever || !first_time) && one_col)
  340. X               fputchar ('\n');
  341. X                first_ever = 0;
  342. #endif
  343. X                /* If we are showing directories, whichname already contains the
  344. X                full pathname string.  Else we only use the filename as follows:
  345. X                long filename if possible, else short filename */
  346. X                if (!showdir) {
  347. X                   strcpy (whichname, 
  348. X                      (direntry.namlen != 0) ? direntry.lfname : direntry.fname);
  349. X                    if (genson && zoo_header.vdata & VFL_ON)
  350. X                        add_version (whichname, &direntry);    /* add version suffix */
  351. X                }
  352. X                namelen = strlen (whichname);
  353. X
  354. #define MARGIN            78
  355. #define COL_WIDTH        16
  356. #if 1
  357. X                /* if not enough space left, move to next line */
  358. X                if (!one_col && column != 0) {
  359. X                    space_left = MARGIN - column;
  360. X                    if (namelen > space_left) {
  361. X                        neednl = 1;
  362. X                        column = 0;
  363. X                    }
  364. X                }
  365. #endif
  366. X            if ( (quiet && !first_ever || !first_time) && (neednl || one_col))
  367. X                    printf ("\n");
  368. X                first_ever = 0;
  369. X                neednl = 0;
  370. X
  371. X            printf("%s", whichname);
  372. X                fflush (stdout);
  373. X                /* move to next column stop */
  374. X                column += namelen;
  375. X                next_col = ((column + (COL_WIDTH - 1)) / COL_WIDTH) * COL_WIDTH;
  376. X                if (next_col - column < 2)        /* need at least 2 spaces */
  377. X                    next_col += COL_WIDTH;
  378. X                if (next_col > MARGIN) {
  379. X                    neednl = 1;
  380. X                    column = 0;
  381. X                } else {
  382. X                    if (!one_col)
  383. X                        printf ("%*s", (next_col - column), " ");
  384. X                    column = next_col;
  385. X                }
  386. X   
  387. X         } else {
  388. X            if (talking && first_time && !show_name) {/*print archive header */
  389. X               printf ("Length    CF  Size Now  Date      Time\n");
  390. X               printf (tot_line);
  391. X            }
  392. X            printf ("%8lu %3u%% %8lu  %2d %-.3s %02d %02d:%02d:%02d",  
  393. X                     direntry.org_size, 
  394. X                     size_factor, direntry.size_now, 
  395. X                     day, &month_list[month*3], 
  396. X                     (day && month) ?  (year+80) % 100 : 0,
  397. X                     hours, min, sec);
  398. X               tot_org_siz += direntry.org_size;
  399. X               tot_siz_now += direntry.size_now;
  400. #ifdef GETTZ
  401. X                printtz ((int) direntry.tz);    /* show timezone */
  402. #else
  403. X                printf (" ");
  404. #endif
  405. X
  406. X                if (show_crc)
  407. X                    printf ("%04x ", direntry.file_crc);
  408. X                if (show_gen) {
  409. X                    if (direntry.vflag & VFL_ON)
  410. X                        printf ("%2dg ", direntry.vflag & VFL_GEN);
  411. X                    else
  412. X                        printf ("--g ");
  413. X                }
  414. X   
  415. X            if (direntry.cmt_size) {
  416. X               expl_comment++;
  417. X               printf ("C");
  418. X            } else
  419. X               printf (" ");
  420. X   
  421. X            if (direntry.deleted) {
  422. X               expl_deleted++;
  423. X               printf ("D");
  424. X            }  else
  425. X               printf (" ");
  426. X            if (list_deleted)
  427. X               printf (" ");
  428. X            if (show_name)
  429. X               printf ("%-*s ", longest, this_zoo);
  430. X
  431. #ifdef FATTR
  432. X                if (show_mode) {
  433. X                    if (direntry.fattr == 0)
  434. X                        printf ("--- ");
  435. X                    else if ((direntry.fattr >> 22) == 1)
  436. X                        printf ("%03o ", direntry.fattr & 0x1ff);
  437. X                    else
  438. X                        printf ("??? ");
  439. X                }
  440. #endif /* FATTR */
  441. X
  442. X                /* new code to get around a common compiler bug */
  443. X                printf ("%s", whichname);
  444. X                if (direntry.dir_crc != 0) {
  445. X                    expl_star++;
  446. X                    printf ("*");
  447. X                }
  448. X
  449. X            if (bad_pack)
  450. X               printf (" (V%d.%d)", direntry.major_ver, direntry.minor_ver);
  451. X            printf ("\n");
  452. X         }
  453. X         first_time = 0;
  454. X   
  455. X         /* if verbose listing requested show any comment.  f overrrides v */
  456. X         if (verb_list && !fast)
  457. X            show_comment (&direntry, zoo_file, 0, (char *) NULL);
  458. X      } /* end if (lots of conditions) */
  459. X   
  460. X        /* ..seek to next dir entry */
  461. X      zooseek (zoo_file, direntry.next, 0);
  462. X   } /* end while */
  463. X   
  464. X   givesummary:
  465. X   
  466. X    if (fast && talking) {
  467. X       if (file_count) {
  468. X           if (del_count || (show_gen && zoo_header.type > 0))
  469. X              printf ("\n-----\n");
  470. X            else
  471. X              fputchar ('\n');
  472. X        }
  473. X        if (del_count)
  474. X            printf ("%d deleted.\n", del_count);
  475. X        if (show_gen && zoo_header.type > 0) {
  476. X            printf ("Generation limit %u",
  477. X                        zoo_header.vdata & VFL_GEN);
  478. X            if ((zoo_header.vdata & VFL_ON) == 0)
  479. X                printf (" (off).\n");
  480. X            else
  481. X                printf (".\n");
  482. X        }
  483. X    } /* end if (fast && talking) */
  484. X
  485. X   if (talking && !show_name) {
  486. X      if (!fast && file_count) {
  487. X         tot_sf = cfactor (tot_org_siz, tot_siz_now);
  488. X         printf (tot_line);
  489. X      
  490. X         printf (tot_fmt, tot_org_siz, tot_sf, tot_siz_now, file_count);
  491. X            if (file_count > 1)
  492. X                printf ("s\n");
  493. X            else
  494. X                printf ("\n");
  495. X         
  496. X         if (del_count || expl_ver || expl_deleted || expl_comment ||
  497. X                    expl_star || (show_gen && (zoo_header.type > 0)))
  498. X            printf (dashes);
  499. X      }
  500. X   
  501. X      if (!fast) {
  502. X         if (del_count) {
  503. X            if (expl_deleted)
  504. X               printf ("D: deleted file.\n");
  505. X            else {
  506. X               if (del_count == 1)
  507. X                  printf ("There is 1 deleted file.\n");
  508. X               else
  509. X                  printf ("There are %d deleted files.\n", del_count);
  510. X            }
  511. X         }
  512. X      }
  513. X      if (expl_comment && !fast && !verb_list) 
  514. X         printf ("C: file has attached comment.\n");
  515. X      if (expl_ver && !fast)
  516. X         printf ("V: minimum version of Zoo needed to extract this file.\n");
  517. X      if (expl_star && !fast)
  518. X         printf ("*: directory entry may be corrupted.\n");
  519. X      if (!file_count)
  520. X         printf ("Zoo:  %s", no_match);
  521. X      
  522. X      if (!entrycount && !fiz_ofs)
  523. X         printf ("(The archive is empty.)\n");
  524. X        if (show_gen && (zoo_header.type > 0) && !fast) {
  525. X            printf ("Archive generation limit is %u",
  526. X                        zoo_header.vdata & VFL_GEN);
  527. X            if ((zoo_header.vdata & VFL_ON) == 0)
  528. X                printf (" (generations off).\n");
  529. X            else
  530. X                printf (".\n");
  531. X        }
  532. X   } /* end if (talking && !show_name) */
  533. loop_end:            /* jump here on badly structured archive */
  534. X   zooclose (zoo_file);
  535. } /* end for */
  536. X
  537. if (talking && show_name) {
  538. X   if (file_count) {
  539. X      tot_sf = cfactor (tot_org_siz, tot_siz_now);
  540. X      printf (tot_line);
  541. X      printf (tot_fmt, tot_org_siz, tot_sf, tot_siz_now, file_count);
  542. X        if (file_count > 1)
  543. X            printf ("s\n");
  544. X        else
  545. X            printf ("\n");
  546. X   } 
  547. } else if (fast && quiet)
  548. X    fputchar ('\n');
  549. X    
  550. X
  551. if (!file_count)
  552. X   zooexit (1);            /* Consider it an error if there were no files */
  553. } /* zoolist() */
  554. X
  555. #ifdef GETTZ
  556. void printtz (file_tz)
  557. int file_tz;
  558. {
  559. X    long gettz();
  560. X    int diff_tz;                /* timezone difference */
  561. X    if (file_tz == NO_TZ)     /* if no timezone stored ..*/
  562. X        printf ("   ");            /* .. just pad with blanks */
  563. X    else {
  564. X        diff_tz = (file_tz / 4) - (int) (gettz() / 3600);
  565. X        if (diff_tz == 0)
  566. X            printf ("   ");                    /* print nothing if same */
  567. X        else if (diff_tz > 0)            /* else print signed difference */
  568. X            printf ("+%1d ", diff_tz);
  569. X        else
  570. X            printf ("-%1d ", -diff_tz);
  571. X    }
  572. }
  573. #endif
  574. X
  575. /*
  576. FOLLOWING CODE IS FOR DEBUGGING ONLY.  IT IS COMPILED IN ONLY
  577. IF THE SYMBOL TRACE_LIST IS DEFINED
  578. */
  579. X
  580. #ifdef TRACE_LIST
  581. /* code copied from portable.c near end */
  582. /* dump contents of directory entry */
  583. void show_dir (direntry)
  584. struct direntry *direntry;
  585. {
  586. X   printf ("Directory entry for file [%s][%s]:\n",
  587. X            direntry->fname, direntry->lfname);
  588. X   printf ("tag = [%8lx] type = [%d] PM = [%d] Next = [%8lx] Offset = [%8lx]\n",
  589. X            direntry->zoo_tag, (int) direntry->type, 
  590. X            (int) direntry->packing_method, direntry->next, 
  591. X            direntry->offset);
  592. X   printf ("Orig size = [%ld] Size now = [%ld] dmaj_v.dmin_v = [%d.%d]\n",
  593. X         direntry->org_size, direntry->size_now,
  594. X         (int) direntry->major_ver, (int) direntry->minor_ver);
  595. X   printf ("Struc = [%d] DEL = [%d] comment_offset = [%8lx] cmt_size = [%d]\n",
  596. X         (int) direntry->struc, (int) direntry->deleted, direntry->comment,
  597. X         direntry->cmt_size);
  598. X   printf ("var_dir_len = [%d] TZ = [%d] dir_crc = [%4x]\n",
  599. X            direntry->var_dir_len, (int) direntry->tz, direntry->dir_crc);
  600. X   printf ("system_id = [%d]  dirlen = [%d]  namlen = [%d] fattr=[%24lx]\n", 
  601. X        direntry->system_id, direntry->dirlen, direntry->namlen, direntry->fattr);
  602. X    printf ("vflag = [%4x] version_no = [%4x]\n",
  603. X                direntry->vflag, direntry->version_no);
  604. X   if (direntry->dirlen > 0)
  605. X      printf ("dirname = [%s]\n", direntry->dirname);
  606. X   printf ("---------\n");
  607. }
  608. #endif   /* TRACE_IO */
  609. SHAR_EOF
  610. chmod 0644 zoolist.c ||
  611. echo 'restore of zoolist.c failed'
  612. Wc_c="`wc -c < 'zoolist.c'`"
  613. test 18884 -eq "$Wc_c" ||
  614.     echo 'zoolist.c: original size 18884, current size' "$Wc_c"
  615. fi
  616. # ============= zoomem.h ==============
  617. if test -f 'zoomem.h' -a X"$1" != X"-c"; then
  618.     echo 'x - skipping zoomem.h (File already exists)'
  619. else
  620. echo 'x - extracting zoomem.h (Text)'
  621. sed 's/^X//' << 'SHAR_EOF' > 'zoomem.h' &&
  622. /* derived from: zoomem.h 2.1 87/12/25 12:26:18 */
  623. /* $Path$ */
  624. /* $Id: zoomem.h,v 1.3 91/07/09 01:43:06 dhesi Exp $ */
  625. X
  626. /*
  627. (C) Copyright 1991 Rahul Dhesi -- All rights reserved
  628. X
  629. Defines parameters used for memory allocation.
  630. */
  631. X
  632. /* ZOOCOUNT is the number of archive names that may be matched by the
  633. archive filespec specified for a list.
  634. X
  635. MAXADD is the number of filenames that may be added to an archive
  636. at one go.  The total number of files that an archive may contain
  637. is not determined by MAXADD but is determined by available memory.
  638. */
  639. X
  640. #ifdef   SMALL_MEM
  641. #define  ZOOCOUNT   (30)
  642. #define  MAXADD     (100)
  643. #endif
  644. X
  645. #ifdef   MED_MEM
  646. #define  ZOOCOUNT   (50)
  647. #define  MAXADD     (200)
  648. #endif
  649. X
  650. #ifdef   BIG_MEM
  651. #define  ZOOCOUNT   (400)
  652. #define  MAXADD     (4000)
  653. #endif
  654. X
  655. /* Customizable sizes */
  656. #ifdef   SPEC_MEM
  657. #define  ZOOCOUNT    (100)
  658. #define  MAXADD      (400)
  659. #endif
  660. X
  661. extern char *out_buf_adr;              /* global I/O buffer */
  662. X
  663. /*************************************************************/
  664. /* DO NOT CHANGE THE REST OF THIS FILE.                      */
  665. /*************************************************************/
  666. X
  667. /*
  668. The main I/O buffer (called in_buf_adr in zoo.c) is reused
  669. in several places.
  670. */
  671. X
  672. #define  IN_BUF_SIZE       8192
  673. #define  OUT_BUF_SIZE      8192
  674. X
  675. /* MEM_BLOCK_SIZE must be no less than (2 * DICSIZ + MAXMATCH)
  676. (see ar.h and lzh.h for values).  The buffer of this size will
  677. also hold an input buffer of IN_BUF_SIZE and an output buffer
  678. of OUT_BUF_SIZE.  FUDGE is a fudge factor, to keep some spare and
  679. avoid off-by-one errors. */
  680. X
  681. #define FUDGE        8
  682. #define  MEM_BLOCK_SIZE    (8192 + 8192 + 256 + 8)
  683. X
  684. SHAR_EOF
  685. chmod 0644 zoomem.h ||
  686. echo 'restore of zoomem.h failed'
  687. Wc_c="`wc -c < 'zoomem.h'`"
  688. test 1639 -eq "$Wc_c" ||
  689.     echo 'zoomem.h: original size 1639, current size' "$Wc_c"
  690. fi
  691. # ============= zoopack.c ==============
  692. if test -f 'zoopack.c' -a X"$1" != X"-c"; then
  693.     echo 'x - skipping zoopack.c (File already exists)'
  694. else
  695. echo 'x - extracting zoopack.c (Text)'
  696. sed 's/^X//' << 'SHAR_EOF' > 'zoopack.c' &&
  697. #ifndef LINT
  698. /* derived from: @(#) zoopack.c 2.16 88/08/22 15:51:20 */
  699. /*$Source: /usr/home/dhesi/zoo/RCS/zoopack.c,v $*/
  700. /*$Id: zoopack.c,v 1.5 91/07/09 01:54:17 dhesi Exp $*/
  701. static char sccsid[]="$Source: /usr/home/dhesi/zoo/RCS/zoopack.c,v $\n\
  702. $Id: zoopack.c,v 1.5 91/07/09 01:54:17 dhesi Exp $";
  703. #endif /* LINT */
  704. X
  705. /*
  706. Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  707. (C) Copyright 1988 Rahul Dhesi -- All rights reserved
  708. */
  709. #include "options.h"
  710. /* Packs an archive.  The sequence is:
  711. X   1. Copy all files from current archive to new one.
  712. X   2. If the user didn't want a backup, delete the old archive
  713. X      else rename it to same name with extension of .BAK.
  714. X   3. Rename temporary archive to old name.
  715. */
  716. X
  717. /* define this to make packing noisless */
  718. #define QUIETPACK 1
  719. X
  720. X
  721. #include "portable.h"
  722. #include "zooio.h"
  723. #include "various.h"
  724. #include "zoo.h"
  725. #include "zoofns.h"
  726. #include "errors.i"
  727. #ifndef NOSIGNAL
  728. #include <signal.h>
  729. #endif
  730. X
  731. char *mktemp PARMS((char *));
  732. X
  733. struct zoo_header zoo_header = {
  734. X   TEXT,
  735. X   ZOO_TAG,
  736. X   (long) SIZ_ZOOH,
  737. X   (long) (-SIZ_ZOOH),
  738. X   MAJOR_VER,
  739. X   MINOR_VER,
  740. X    H_TYPE,
  741. X    0L,                        /* comment position */
  742. X    0,                            /* comment length */
  743. X    GEN_DEFAULT                /* generations */
  744. };
  745. char file_leader[] = FILE_LEADER;
  746. extern int quiet;
  747. int break_hit;
  748. X
  749. int ver_too_high PARMS((struct zoo_header *));
  750. X
  751. void zoopack(zoo_path, option)
  752. char *zoo_path, *option;
  753. {
  754. char temp_file[PATHSIZE];
  755. static char xes[]="XXXXXX";               /* template for temp file */
  756. X
  757. #ifndef NOSIGNAL
  758. T_SIGNAL (*oldsignal)();
  759. #endif
  760. register ZOOFILE zoo_file;                /* archive */
  761. ZOOFILE new_file;                         /* destination archive */
  762. long next_ptr;                            /* pointer to within archive */
  763. long new_dir_pos;                         /* ditto */
  764. struct direntry direntry;                 /* directory entry */
  765. struct zoo_header old_zoo_header;         /* just for reading old header */
  766. int status;                               /* error status */
  767. int nobackup = 0;                         /* keep backup */
  768. int force = 0;                            /* force overwrite of old backup */
  769. int extcount = 0;                         /* how many files moved */
  770. char backup_name[PATHSIZE];               /* name of backup */
  771. int bad_header = 0;                       /* if archive has bad header */
  772. int latest_date = 0;                      /* latest date on any file moved */
  773. int latest_time = 0;                      /*  ...likewise */
  774. int curr_dir = 0;                                    /* create backup in curr dir */
  775. static char partial_msg[] =
  776. X   "Partially packed archive left in %s.\n";
  777. X
  778. #ifdef FATTR
  779. unsigned long zoofattr;                            /* zoo archive protection */
  780. int setfattr PARMS ((char *, unsigned long));
  781. unsigned long getfattr                            /* params below */
  782. # ifdef FATTR_FNAME
  783. X  PARMS ((char *));
  784. # else
  785. X  PARMS ((ZOOFILE));
  786. # endif /* FATTR_FNAME */
  787. #endif /* FATTR */
  788. X
  789. while (*option) {
  790. X   switch (*option) {
  791. X      case 'P': force++; break;
  792. X      case 'E': nobackup++; break;
  793. X      case 'q': quiet++; break;
  794. X        case '.': curr_dir++; break;
  795. X      default:
  796. X         prterror ('f', inv_option, *option);
  797. X   }
  798. X   option++;
  799. }
  800. if (force == 1)         /* force only if P was doubled */
  801. X   force--;
  802. X
  803. zoo_path = addext (zoo_path, EXT_DFLT);      /* add default extension */
  804. X
  805. /* Create a backup name by replacing any extension by backup extension. */
  806. strcpy (backup_name, zoo_path);
  807. {
  808. X   char *temp;
  809. X   if ((temp = strrchr (backup_name,EXT_CH)) != 0)  /* if dot found */
  810. X      strcpy (temp, BACKUP_EXT);                /* replace old extension */
  811. X   else
  812. X      strcat (backup_name, BACKUP_EXT);         /* else just append */
  813. }
  814. X
  815. /*
  816. Open original archive for read-write access.  Although we will only
  817. read from it and never write to it, we want to avoid packing an
  818. archive that is read-only, since presumably the user didn't want
  819. to risk changing it in any way.
  820. */
  821. zoo_file = zooopen(zoo_path, Z_RDWR);
  822. X
  823. if (zoo_file == NOFILE)
  824. X   prterror ('f', could_not_open, zoo_path);
  825. X
  826. /* If possible, save protection code of old archive for propagation to new */
  827. #ifdef FATTR
  828. # ifdef FATTR_FNAME
  829. X   zoofattr = getfattr (zoo_path);
  830. # else
  831. X   zoofattr = getfattr (zoo_file);
  832. # endif /* FATTR_FNAME */
  833. #endif /* FATTR */
  834. X
  835. /* Read the header of the old archive. */
  836. frd_zooh(&old_zoo_header, zoo_file);
  837. X
  838. if ((old_zoo_header.zoo_start + old_zoo_header.zoo_minus) != 0L) {
  839. X   prterror ('w', failed_consistency);
  840. X   ++bad_header;                    /* remember for future error message */
  841. }
  842. X
  843. /* Refuse to pack it if its version number is higher than we can accept */
  844. if (ver_too_high (&old_zoo_header))
  845. X   prterror ('f', wrong_version, old_zoo_header.major_ver,
  846. X                                    old_zoo_header.minor_ver);
  847. X
  848. /* Now see if the archive already exists with the backup extension.  If so,
  849. X   give an error message and abort.  However, we skip this test if the user
  850. X   specified overwriting the backup */
  851. X
  852. if (!force) {
  853. X   if (exists (backup_name))
  854. X      prterror ('f', "File %s already exists.  Delete it or use PP option.\n",
  855. X                      backup_name);
  856. }
  857. X
  858. /*
  859. Open the new archive by a temporary name.  If not otherwise specified,
  860. we open the new archive in the same directory as the original.  But if
  861. the curr_dir switch was given, we just put XXXXXX into temp_file.
  862. */
  863. if (!curr_dir) {
  864. X    strcpy (temp_file, zoo_path);          /* original archive name */
  865. X    *nameptr (temp_file) = '\0';           /* ... minus original filename */
  866. X    strcat (temp_file, xes);               /* ... plus XXXXXX */
  867. } else {
  868. X   strcpy (temp_file, xes);
  869. }
  870. mktemp (temp_file);                    /* ... and make unique */
  871. new_file = zoocreate (temp_file);
  872. if (new_file == NOFILE)
  873. X   prterror ('f', "Could not create temporary file %s.\n", temp_file);
  874. X
  875. /*
  876. If old_zoo_header greater than type 0, we update zoo_header as follows:  
  877. new archive comment will be just after archive header;  zoo_start will 
  878. point to just beyond archive comment.  But if old_zoo_header is of 
  879. type 0, we leave zoo_header unchanged.  However, we always 
  880. unconditionally update the header type to be type H_TYPE.  
  881. (Note:  zoo_header.type is initialized to H_TYPE in the
  882. global declaration of zoo_header.)
  883. */
  884. if (old_zoo_header.type > 0) {
  885. X    zoo_header.zoo_start = SIZ_ZOOH + old_zoo_header.acmt_len;
  886. X    zoo_header.zoo_minus = -zoo_header.zoo_start;
  887. X    zoo_header.acmt_pos = SIZ_ZOOH;    /* new comment just after header */
  888. X    zoo_header.acmt_len = old_zoo_header.acmt_len;
  889. X    zoo_header.vdata      = old_zoo_header.vdata;
  890. } else /* keep generations off if using old format archive */
  891. X    zoo_header.vdata &=  (~VFL_ON);
  892. X
  893. /* Write the header of the new archive, updated with our own data */
  894. fwr_zooh (&zoo_header, new_file);
  895. X
  896. /* copy archive comment */
  897. if (old_zoo_header.acmt_len != 0) {
  898. X    zooseek (zoo_file, old_zoo_header.acmt_pos, 0);    /* find archive comment */
  899. X    getfile (zoo_file, new_file, (long) zoo_header.acmt_len, 0); /* copy it */
  900. }
  901. X
  902. /* WARNING: CHECK FOR SEEK BEYOND END OF FILE */
  903. zooseek (new_file, zoo_header.zoo_start, 0);       /* position to add files */
  904. X
  905. zooseek (zoo_file, old_zoo_header.zoo_start, 0); /* seek to where data begins */
  906. X
  907. /* Now we loop through the old archive's files and add each to the new
  908. archive.  The only changes needed are to update the .next and .offset
  909. fields of the directory entry. */
  910. X
  911. while (1) {
  912. X   frd_dir(&direntry, zoo_file);
  913. X   if (direntry.zoo_tag != ZOO_TAG) {
  914. X      long currpos, zoolength;
  915. X      prterror ('F', bad_directory);
  916. X      if (bad_header) {    /* bad headers means don't save temp file */
  917. X         zooclose (new_file);
  918. X         unlink (temp_file);
  919. X      } else {
  920. X         writenull (new_file, MAXDIRSIZE);    /* write final null entry */
  921. X         printf (partial_msg, temp_file);
  922. X         if ((currpos = ftell (zoo_file)) != -1L)
  923. X            if (zooseek (zoo_file, 0L, 2) == 0)
  924. X               if ((zoolength = ftell (zoo_file)) != -1L)
  925. X                  printf (cant_process, zoolength - currpos);
  926. X      }
  927. X      zooexit (1);
  928. X   }
  929. X   if (direntry.next == 0L) {                /* END OF CHAIN */
  930. X      break;                                 /* EXIT on end of chain */
  931. X   }
  932. X   next_ptr = direntry.next;                 /* ptr to next dir entry */
  933. X
  934. X   if (!direntry.deleted) {
  935. #ifdef QUIETPACK
  936. /* nothing */
  937. #else
  938. X      prterror ('m', "%-14s -- ",
  939. X         direntry.namlen > 0 ? direntry.lfname : direntry.fname);
  940. #endif
  941. X
  942. X      if (zooseek (zoo_file, direntry.offset, 0) == -1L) {
  943. X         prterror ('f', "Could not seek to file data.\n");
  944. X      } else {
  945. X         extcount++;          /* update count of files extracted */
  946. X
  947. X         /* write a directory entry for this file */
  948. X         new_dir_pos = zootell (new_file); /* new direntry pos in new archive */
  949. X
  950. X         /*
  951. X         Write a null directory entry to preserve integrity in case of
  952. X         program being interrupted.  Note:  I don't think it is
  953. X         necessary to save direntry.next but I haven't checked.
  954. X         */
  955. X         {
  956. X            long oldnext;
  957. X            oldnext = direntry.next;
  958. X            direntry.next = 0L;
  959. X            fwr_dir(&direntry, new_file);
  960. X            direntry.next = oldnext;
  961. X         }
  962. X
  963. X         zooseek (zoo_file, direntry.offset, 0);  /* where to start copying */
  964. X         /* Write file leader and remember position of new file data */
  965. X         (void) zoowrite (new_file, file_leader, SIZ_FLDR);
  966. X         direntry.offset = zootell (new_file);
  967. X         status = getfile (zoo_file, new_file, direntry.size_now, 0);
  968. X         /* if no error copy any comment attached to file */
  969. X         if (status == 0 && direntry.cmt_size != 0) {
  970. X            zooseek (zoo_file, direntry.comment, 0);  /* seek to old comment  */
  971. X            direntry.comment = zootell (new_file); /* location of new comment */
  972. X            status = getfile (zoo_file, new_file,
  973. X                                 (long) direntry.cmt_size, 0);
  974. X         }
  975. X
  976. X         if (status != 0) {
  977. X            if (status == 1) {
  978. X               memerr(0);
  979. X            } else
  980. X               if (status == 2 || status == 3) {
  981. X                  prterror ('F', disk_full);
  982. X                  printf (partial_msg, temp_file);
  983. X                  zooexit (1);
  984. X               } else
  985. X                  prterror ('f', internal_error);
  986. X         } else {
  987. X            if (latest_date < direntry.date ||
  988. X                     (latest_date == direntry.date &&
  989. X                           latest_time < direntry.time))  {
  990. X               latest_date = direntry.date;
  991. X               latest_time = direntry.time;
  992. X            }
  993. X         }
  994. X         direntry.next = zootell (new_file);
  995. X         zooseek (new_file, new_dir_pos, 0);  /* position to write direntry */
  996. X
  997. X         break_hit = 0;
  998. #ifndef NOSIGNAL
  999. X         oldsignal = signal (SIGINT, SIG_IGN);
  1000. X         if (oldsignal != SIG_IGN)
  1001. X            signal (SIGINT, handle_break);
  1002. #endif
  1003. X
  1004. X            /* Bug fix thanks to Mark Alexander */
  1005. X         if (fwr_dir (&direntry, new_file) != -1 &&
  1006. X            zoowrite (new_file, file_leader, SIZ_FLDR) == SIZ_FLDR) {
  1007. #ifdef QUIETPACK
  1008. X            /* prterror ('M', "."); */ ;
  1009. #else
  1010. X            prterror ('M', "moved\n");
  1011. #endif
  1012. X         } else
  1013. X            prterror ('f', "Write to temporary packed archive %s failed.\n", temp_file);
  1014. #ifndef NOSIGNAL
  1015. X         signal (SIGINT, oldsignal);
  1016. #endif
  1017. X         if (break_hit)
  1018. X            zooexit (1);
  1019. X         zooseek (new_file, direntry.next, 0);  /* back to end of new archive */
  1020. X      }  /* end if (lseek ... */
  1021. X   } /* end if (!direntry.deleted) */
  1022. X
  1023. zooseek (zoo_file, next_ptr, 0);   /* ..seek to next dir entry */
  1024. } /* end while */
  1025. X
  1026. zooclose (zoo_file);
  1027. X
  1028. /* write a final null entry */
  1029. writenull (new_file, MAXDIRSIZE);
  1030. X
  1031. #ifdef NIXTIME
  1032. zooclose (new_file);
  1033. setutime (temp_file, latest_date, latest_time);
  1034. #else
  1035. settime (new_file, latest_date, latest_time);    /* adjust its time */
  1036. zooclose (new_file);
  1037. #endif
  1038. X
  1039. /* Important note:  At this point, it is assumed that the archive was
  1040. X   packed and written to a new file without error.  If control reaches
  1041. X   here without the new archive having been written properly, then
  1042. X   loss of data due to deletion of the original file could occur.  In
  1043. X   other words, if something went wrong, execution MUST NOT reach here. */
  1044. X
  1045. if (extcount == 0) {
  1046. X   unlink (temp_file);
  1047. X   prterror ('m', "No files moved.\n");
  1048. } else {
  1049. X   /* (a) if user requested, delete original, else rename it to
  1050. X   *.bak.  (b) rename temp file to same base name as zoo_file. */
  1051. X
  1052. #ifdef QUIETPACK
  1053. X   /* prterror('M', "\n"); */
  1054. #endif
  1055. X
  1056. X   unlink (backup_name);    /* remove any previous backup in any case */
  1057. X   if (nobackup)
  1058. X      unlink (zoo_path);
  1059. X   else
  1060. X      chname (backup_name, zoo_path);
  1061. X
  1062. X    /* if we are packing into current directory, we will rename temp file
  1063. X        to same basename but without the preceding pathname */
  1064. X    if (curr_dir)
  1065. X        zoo_path = nameptr (zoo_path);        /* strip pathname */
  1066. X
  1067. X
  1068. X   if (chname (zoo_path, temp_file)) {
  1069. X      prterror ('w', "Renaming error.  Packed archive is now in %s.\n", temp_file);
  1070. X      zooexit (1);
  1071. X   }
  1072. X
  1073. /*
  1074. Set protection on packed archive -- after renaming, since some
  1075. OSs might not allow renaming of read-only files
  1076. */
  1077. #ifdef FATTR
  1078. X    setfattr (zoo_path, zoofattr);
  1079. #endif /* FATTR */
  1080. X
  1081. } /* end if */
  1082. X
  1083. } /* end zoopack() */
  1084. X
  1085. /* handle_break() */
  1086. /* Sets break_hit to 1 when called */
  1087. T_SIGNAL handle_break()
  1088. {
  1089. #ifndef NOSIGNAL
  1090. X   signal (SIGINT, SIG_IGN);     /* ignore future control ^Cs for now */
  1091. X   break_hit = 1;
  1092. #endif
  1093. }
  1094. SHAR_EOF
  1095. chmod 0644 zoopack.c ||
  1096. echo 'restore of zoopack.c failed'
  1097. Wc_c="`wc -c < 'zoopack.c'`"
  1098. test 13324 -eq "$Wc_c" ||
  1099.     echo 'zoopack.c: original size 13324, current size' "$Wc_c"
  1100. fi
  1101. exit 0
  1102.