home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / zoo / part07 < prev    next >
Encoding:
Internet Message Format  |  1987-08-17  |  26.6 KB

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v11i016:  File archive program, Part07/07
  5. Message-ID: <996@uunet.UU.NET>
  6. Date: 18 Aug 87 22:49:29 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 827
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: iuvax!bsu-cs!dhesi@seismo.CSS.GOV (Rahul Dhesi)
  12. Posting-number: Volume 11, Issue 16
  13. Archive-name: zoo/Part07
  14.  
  15. #! /bin/sh
  16. #
  17. # This is a shell archive, meaning:
  18. # 1. Remove everything above the #! /bin/sh line.
  19. # 2. Save the resulting text in a file.
  20. # 3. Execute the file with /bin/sh (not csh) to create:
  21. #    zoolist.c
  22. #    zoomem.h
  23. #    zoopack.c
  24. export PATH; PATH=/bin:/usr/bin:$PATH
  25. if test -f 'zoolist.c'
  26. then
  27.     echo shar: "will not over-write existing file 'zoolist.c'"
  28. else
  29. sed 's/^X//' << \SHAR_EOF > 'zoolist.c'
  30. X#ifndef LINT
  31. Xstatic char sccsid[]="@(#) zoolist.c 1.12 87/05/29 12:56:18";
  32. X#endif /* LINT */
  33. X
  34. X/*
  35. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  36. X*/
  37. X#include "options.h"
  38. X#include "portable.h"
  39. X#include "zoomem.h"  /* to get ZOOCOUNT */
  40. X
  41. X/* Lists files in archive */
  42. X#include "zoo.h"
  43. X#include "errors.i"
  44. X#include <stdio.h>
  45. X#include "various.h"
  46. X#include "zoofns.h"
  47. X
  48. Xstatic char tot_fmt[] = "%8lu %3u%% %8lu  %4d file"; 
  49. Xstatic char tot_line[] = 
  50. X   /* "------------  --------  ---  --------  --------- --------\n"; */
  51. X   "--------  --- --------  --------- --------\n";
  52. X
  53. Xstatic char dbl_percent[] = "Archive %s:  %s";
  54. X
  55. X#ifdef LINT_ARGS
  56. Xvoid show_comment (struct direntry *, FILE *, int, char *);
  57. Xint ver_too_high (struct zoo_header *);
  58. X#endif
  59. X
  60. Xvoid zoolist (argv, option, argc)
  61. Xchar **argv, *option;
  62. Xint argc;
  63. X{
  64. Xchar whichname[PATHSIZE];  /* which name to use */
  65. Xchar *this_zoo;            /* currently matched archive name */
  66. Xregister FILE *zoo_file;
  67. Xchar *flist[ZOOCOUNT];       /* list of ptrs to input archive names */
  68. Xint fptr;                  /* will point to within list of archive names */
  69. X
  70. Xstruct direntry direntry;
  71. Xstruct zoo_header zoo_header;
  72. Xint size_factor;
  73. Xchar packing[9];
  74. Xunsigned long tot_org_siz = 0L, tot_siz_now = 0L;
  75. Xint   tot_sf;
  76. Xint file_count = 0;
  77. Xint del_count = 0;                  /* number of deleted entries */
  78. Xint bad_pack;                 /* 1 if packing method is unknown */
  79. Xstatic char *month_list="000JanFebMarAprMayJunJulAugSepOctNovDec";
  80. Xstatic char dashes[] = "------------\n";
  81. Xint year, month, day, hours, min, sec;
  82. Xint list_deleted = 0;         /* list deleted files too */
  83. Xint fast = 0;                 /* fast list */
  84. Xint column;                   /* for column printing */
  85. Xlong fiz_ofs = 0;             /* offset where to start */
  86. Xint verb_list = 0;            /* if verbose listing needed */
  87. Xint show_name = 0;            /* if archive name to be included in listing */
  88. Xint zoocount = 1;             /* number of archives to list */
  89. Xint biglist = 0;              /* multiarchive listing */
  90. Xint longest;                  /* length of longest archive name */
  91. X
  92. Xwhile (*option) {
  93. X   switch (*option) {
  94. X      case 'a': show_name++; break;
  95. X      case 'd': list_deleted++; break;
  96. X      case 'f': fast++; break;
  97. X      case 'c':
  98. X      case 'v': verb_list++; break;
  99. X      case 'l': break;
  100. X      case 'L': biglist++; zoocount = argc; break;
  101. X      case '@': 
  102. X         ++option;
  103. X         fiz_ofs = calc_ofs(option); 
  104. X         goto no_more;
  105. X      default:
  106. X         prterror ('w', option_ignored, *option);
  107. X   }
  108. X   option++;
  109. X}
  110. X
  111. Xno_more:  /* come from exit from while loop above */
  112. X
  113. Xif (fast && show_name) {      /* don't allow 'a' with 'f' */
  114. X   show_name = 0;
  115. X   prterror ('w', option_ignored, 'a');
  116. X}
  117. X
  118. X#ifdef WILDCARD
  119. X   /* For each archive name supplied, if it is not a char range and
  120. X      does not contain a dot, append "*.zoo". */
  121. X   {
  122. X      int i;
  123. X      for (i = 0; i < argc;  i++) {
  124. X         if (strchr (nameptr (argv[i]), EXT_CH) == NULL && 
  125. X                           !match_half (nameptr (argv[0]), "?-?"))
  126. X            argv[i] = newcat (argv[i], "*.zoo");
  127. X      }
  128. X   }
  129. X#endif
  130. X
  131. Xmakelist (zoocount, argv, flist,        ZOOCOUNT-2,   (char *) NULL,".","..", &longest);
  132. X/*        ^argc     ^argv ^list_pointer ^max_no_files   ^exclude */
  133. X
  134. Xfor (fptr = 0;  (this_zoo = flist[fptr]) != NULL; fptr++) {
  135. X   int ercount;                  /* count of errors */
  136. X   int entrycount;               /* count of directory entries */
  137. X   int column;                   /* for column printing */
  138. X   int expl_deleted;             /* explain what D means */
  139. X   int expl_comment;             /* explain what comment means */
  140. X   int expl_ver;                 /* Explain what V means */
  141. X   int expl_star;                /* Explain what * means */
  142. X   int first_time;               /* first time through loop for an archive */
  143. X
  144. X   ercount = entrycount = column = del_count =
  145. X      expl_deleted = expl_comment = expl_ver = expl_star = 0;
  146. X   first_time = 1;
  147. X
  148. X#ifndef WILDCARD
  149. X   /* Add default extension if none supplied */
  150. X   if (strchr (nameptr (this_zoo), EXT_CH) == NULL)
  151. X      this_zoo = newcat (this_zoo, EXT_DFLT);
  152. X#endif
  153. X
  154. X   zoo_file = fopen (this_zoo, FRDSTR);
  155. X
  156. X   if (zoo_file == NULL) {
  157. X      prterror ('e', could_not_open, this_zoo);
  158. X      continue;
  159. X   } else if (!show_name)
  160. X      printf ("\nArchive %s:\n", this_zoo);
  161. X   
  162. Xif (fiz_ofs != 0L) {                /* if offset specified, start there */
  163. X   prterror('m', "Starting at %ld\n", fiz_ofs);
  164. X   fseek (zoo_file, fiz_ofs, 0);
  165. X} else {
  166. X   if (frd_zooh (&zoo_header, zoo_file) == -1 ||
  167. X                                             zoo_header.zoo_tag != ZOO_TAG) {
  168. X      prterror ('e', dbl_percent, this_zoo, invalid_header);
  169. X      goto loop_end;
  170. X   }
  171. X   /* Seek to the beginning of the first directory entry */
  172. X   if (fseek (zoo_file, zoo_header.zoo_start, 0) != 0) {
  173. X      ercount++;
  174. X      prterror ('e', dbl_percent, this_zoo, bad_directory);
  175. X      goto loop_end;
  176. X   }
  177. X   if (!show_name && ver_too_high (&zoo_header)) {
  178. X      ercount++;
  179. X      if (ercount < 2) {
  180. X         prterror ('w', dbl_percent, this_zoo, "");
  181. X         prterror ('M', wrong_version, zoo_header.major_ver, zoo_header.minor_ver);
  182. X      }
  183. X   }
  184. X} /* end if (fiz_ofs !- 0L) */
  185. X
  186. X   /* Now we print information about each file in the archive */
  187. X   
  188. X   if (!show_name) { /* initialize for each file only if not disk catalog */
  189. X      tot_org_siz = 0L;  
  190. X      tot_siz_now = 0L;
  191. X      file_count = 0;
  192. X      del_count = 0;
  193. X   }
  194. X
  195. X   while (1) {
  196. X      if (readdir (&direntry, zoo_file, 0) == -1) {
  197. X         prterror ('F', dbl_percent, this_zoo, bad_directory);
  198. X         goto givesummary;
  199. X      }
  200. X      if (direntry.zoo_tag != ZOO_TAG) {
  201. X         long currpos, zoolength;
  202. X         prterror ('F', dbl_percent, this_zoo, invalid_header);
  203. X         if ((currpos = ftell (zoo_file)) != -1L)
  204. X            if (fseek (zoo_file, 0L, 2) == 0)
  205. X               if ((zoolength = ftell (zoo_file)) != -1L)
  206. X                  printf (cant_process, zoolength - currpos);              
  207. X         goto givesummary;
  208. X      }
  209. X   
  210. X      if (direntry.next == 0L)      /* EXIT on end of chain */
  211. X         break;                                 
  212. X      else
  213. X         entrycount++;              /* Number of directory entries */
  214. X   
  215. X      if (direntry.deleted)
  216. X         ++del_count;
  217. X      
  218. X        /* Into whichname put the combined pathname + filename */
  219. X        strcpy (whichname, fullpath (&direntry));
  220. X#ifdef DEBUG
  221. X      printf("matching against [%s] and [%s]\n", 
  222. X               nameptr(whichname), whichname);
  223. X#endif
  224. X
  225. X      if ( ( (list_deleted && direntry.deleted) ||
  226. X               (list_deleted < 2 && !direntry.deleted)
  227. X           ) 
  228. X              && (biglist || needed(whichname))) {
  229. X   
  230. X         file_count++;
  231. X   
  232. X         if (direntry.packing_method > MAX_PACK) {
  233. X            bad_pack = 1;
  234. X            expl_ver = 1;
  235. X         }  else
  236. X            bad_pack = 0;
  237. X      
  238. X         size_factor = cfactor (direntry.org_size, direntry.size_now);
  239. X   
  240. X         year  =  ((unsigned int) direntry.date >> 9) & 0x7f;
  241. X         month =  ((unsigned int) direntry.date >> 5) & 0x0f;
  242. X         day   =  direntry.date        & 0x1f;
  243. X   
  244. X         hours =  ((unsigned int) direntry.time >> 11)& 0x1f;
  245. X         min   =  ((unsigned int) direntry.time >> 5) & 0x3f;
  246. X         sec   =  ((unsigned int) direntry.time & 0x1f) * 2;
  247. X   
  248. X         if (fast) {
  249. X            if ((column++ % 5) == 0 && !first_time)
  250. X               fputchar ('\n');
  251. X            printf("%-12s  ", direntry.fname);
  252. X                fflush (stdout);
  253. X   
  254. X         } else {
  255. X            if (first_time && !show_name) {     /* print archive header */
  256. X               printf ("Length    CF  Size Now  Date      Time\n");
  257. X               printf (tot_line);
  258. X            }
  259. X            printf ("%8lu %3u%% %8lu  %2d %-.3s %02d %02d:%02d:%02d",  
  260. X                     direntry.org_size, 
  261. X                     size_factor, direntry.size_now, 
  262. X                     day, &month_list[month*3], 
  263. X                     (day && month) ?  (year+80) % 100 : 0,
  264. X                     hours, min, sec);
  265. X               tot_org_siz += direntry.org_size;
  266. X               tot_siz_now += direntry.size_now;
  267. X   
  268. X            if (direntry.cmt_size) {
  269. X               expl_comment++;
  270. X               printf ("C");
  271. X            } else
  272. X               printf (" ");
  273. X   
  274. X            if (direntry.deleted) {
  275. X               expl_deleted++;
  276. X               printf ("D");
  277. X            }  else
  278. X               printf (" ");
  279. X            if (list_deleted)
  280. X               printf (" ");
  281. X            if (show_name)
  282. X               printf ("%-*s ", longest, this_zoo);
  283. X
  284. X                /* new code to get around a common compiler bug */
  285. X                printf (whichname);
  286. X                if (direntry.dir_crc != 0) {
  287. X                    expl_star++;
  288. X                    printf ("*");
  289. X                }
  290. X
  291. X            if (bad_pack)
  292. X               printf (" (V%d.%d)", direntry.major_ver, direntry.minor_ver);
  293. X            printf ("\n");
  294. X         }
  295. X         first_time = 0;
  296. X   
  297. X         /* if verbose listing requested show any comment.  f overrrides v */
  298. X         if (verb_list && !fast)
  299. X            show_comment (&direntry, zoo_file, 0, (char *) NULL);
  300. X      }
  301. X   
  302. X      fseek (zoo_file, direntry.next, 0); /* ..seek to next dir entry */
  303. X   } /* end while */
  304. X   
  305. X   givesummary:
  306. X   
  307. X   if (!show_name) {
  308. X      if (fast) {
  309. X         if (file_count) {
  310. X            if (del_count)
  311. X               printf ("\n-----\n");
  312. X            else
  313. X               fputchar ('\n');
  314. X         }
  315. X         if (del_count)
  316. X            printf ("%d deleted.\n", del_count);
  317. X      }
  318. X      if (!fast && file_count) {
  319. X         tot_sf = cfactor (tot_org_siz, tot_siz_now);
  320. X         printf (tot_line);
  321. X      
  322. X         printf (tot_fmt, tot_org_siz, tot_sf, tot_siz_now, file_count);
  323. X            if (file_count > 1)
  324. X                printf ("s\n");
  325. X            else
  326. X                printf ("\n");
  327. X         
  328. X         if (del_count || expl_ver || expl_deleted || expl_comment)
  329. X            printf (dashes);
  330. X      }
  331. X   
  332. X      if (!fast) {
  333. X         if (del_count) {
  334. X            if (expl_deleted)
  335. X               printf ("D: deleted file.\n");
  336. X            else {
  337. X               if (del_count == 1)
  338. X                  printf ("There is 1 deleted file.\n");
  339. X               else
  340. X                  printf ("There are %d deleted files.\n", del_count);
  341. X            }
  342. X         }
  343. X      }
  344. X      if (expl_comment && !fast && !verb_list) 
  345. X         printf ("C: file has attached comment.\n");
  346. X      if (expl_ver && !fast)
  347. X         printf ("V: minimum version of Zoo needed to extract this file.\n");
  348. X      if (expl_star && !fast)
  349. X         printf ("*: directory entry may be corrupted.\n");
  350. X      if (!file_count)
  351. X         printf ("Zoo:  %s", no_match);
  352. X      
  353. X      if (!entrycount && !fiz_ofs)
  354. X         printf ("(The archive is empty.)\n");
  355. X   } /* end if (show_name) */
  356. Xloop_end:            /* jump here on badly structured archive */
  357. X   fclose (zoo_file);
  358. X} /* end for */
  359. X
  360. Xif (show_name) {
  361. X   if (file_count) {
  362. X      tot_sf = cfactor (tot_org_siz, tot_siz_now);
  363. X      printf (tot_line);
  364. X      printf (tot_fmt, tot_org_siz, tot_sf, tot_siz_now, file_count);
  365. X        if (file_count > 1)
  366. X            printf ("s\n");
  367. X        else
  368. X            printf ("\n");
  369. X   } 
  370. X}
  371. X
  372. Xif (!file_count)
  373. X   exit (1);            /* Consider it an error if there were no files */
  374. X} /* zoolist() */
  375. X
  376. SHAR_EOF
  377. fi
  378. if test -f 'zoomem.h'
  379. then
  380.     echo shar: "will not over-write existing file 'zoomem.h'"
  381. else
  382. sed 's/^X//' << \SHAR_EOF > 'zoomem.h'
  383. X/* @(#) zoomem.h 1.2 87/05/03 16:02:44 */
  384. X
  385. X/*
  386. XThe contents of this file are hereby released to the public domain.
  387. X
  388. X                           -- Rahul Dhesi 1986/11/14
  389. X
  390. XDefines parameters used for memory allocation.  
  391. X
  392. X   Xenix notes:  Under Xenix release 3.0 on an Intel 310 machine with an
  393. X   80286 cpu, memory is very tight when the small memory model is used. 
  394. X   Ooz won't fit if the buffers are 2 K for input and 6 K for output.  
  395. X   It does fit if both input and output buffers are 1 K each.  Under
  396. X   the large memory model there is no problem.  Zoo requires the large
  397. X   memory model.
  398. X
  399. X   AT&T 3B2:  There seem to be no problem at all.  Buffers can always
  400. X   be 8192 each.
  401. X*/
  402. X
  403. X#ifdef OOZ
  404. X#define  IN_BUF_SIZE       8192
  405. X#define  OUT_BUF_SIZE      8192
  406. X#else
  407. X#define  IN_BUF_SIZE       8192
  408. X#define  OUT_BUF_SIZE      8192
  409. X#endif
  410. X
  411. X#define  MEM_BLOCK_SIZE    (IN_BUF_SIZE + OUT_BUF_SIZE)
  412. X
  413. X/* 
  414. XLIST_SIZE is the size of the list built by Zoo to hold all filenames
  415. Xencountered in an archive.  This is used to know when to replace an
  416. Xalready existing file.  The date and time stored with the filename is
  417. Xused in comparisons when an archive update has been requested.  To 
  418. Xadd a file to an archive, the archive must not already have more than
  419. XLIST_SIZE files in it.
  420. X
  421. XZOOCOUNT is the number of archive names that may be matched by the
  422. Xarchive filespec specified for a list.
  423. X
  424. XMAXADD is the number of filenames that may be added to an archive
  425. Xat one go.  The total number of files that an archive may contain
  426. Xis not determined by MAXADD but is determined by LIST_SIZE.
  427. X
  428. XIf USE_MALLOC is defined it tells the memory allocation routine 
  429. Xemalloc() not to bother with maintaining its own memory blocks but just to 
  430. Xpass on requests to the library function malloc().  If USE_MALLOC is not 
  431. Xdefined, emalloc() does its own memory management to save overhead on a 
  432. Xmachine with limited memory.
  433. X*/
  434. X
  435. X#ifdef   SMALL_MEM
  436. X#define  LIST_SIZE  (200)
  437. X#define  ZOOCOUNT   (30)
  438. X#define  MAXADD     (100)
  439. X#define  USE_MALLOC
  440. X#endif
  441. X
  442. X#ifdef   MED_MEM
  443. X#define  LIST_SIZE  (400)
  444. X#define  ZOOCOUNT   (50)
  445. X#define  MAXADD     (200)
  446. X#define  USE_MALLOC
  447. X#endif
  448. X
  449. X#ifdef   BIG_MEM
  450. X#define  LIST_SIZE  (4000)
  451. X#define  ZOOCOUNT   (400)
  452. X#define  MAXADD     (4000)
  453. X#define  USE_MALLOC
  454. X#endif
  455. X
  456. X/* Customizable sizes */
  457. X#ifdef   SPEC_MEM
  458. X#define  LIST_SIZE   (600)
  459. X#define  ZOOCOUNT    (100)
  460. X#define  MAXADD      (400)
  461. X#endif
  462. X
  463. Xextern char *out_buf_adr;              /* global I/O buffer */
  464. SHAR_EOF
  465. fi
  466. if test -f 'zoopack.c'
  467. then
  468.     echo shar: "will not over-write existing file 'zoopack.c'"
  469. else
  470. sed 's/^X//' << \SHAR_EOF > 'zoopack.c'
  471. X#ifndef LINT
  472. X/* @(#) zoopack.c 1.12 87/05/29 12:56:31 */
  473. Xstatic char sccsid[]="@(#) zoopack.c 1.12 87/05/29 12:56:31";
  474. X#endif /* LINT */
  475. X
  476. X/*
  477. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  478. X*/
  479. X#include "options.h"
  480. X/* Packs an archive.  The sequence is:
  481. X   1. Copy all files from current archive to new one.
  482. X   2. If the user didn't want a backup, delete the old archive
  483. X      else rename it to same name with extension of .BAK.
  484. X   3. Rename temporary archive to old name.
  485. X*/
  486. X
  487. X/* define this to make packing noisless except for dots */
  488. X#define QUIETPACK 1
  489. X
  490. X
  491. X#include "portable.h"
  492. X#include <stdio.h>
  493. X#include "various.h"
  494. X#include "zoo.h"
  495. X#include "zoofns.h"
  496. X#include "errors.i"
  497. X#ifndef NOSIGNAL
  498. X#include <signal.h>
  499. X#endif
  500. X
  501. X#ifdef FLAT
  502. X#include <types.h>
  503. X#include <stat.h>
  504. X#else
  505. X#include <sys/types.h>
  506. X#include <sys/stat.h>
  507. X#endif
  508. X
  509. X#ifdef NOFCNTL
  510. X#include <file.h>
  511. X#else
  512. X#include <fcntl.h>
  513. X#endif
  514. X
  515. Xstruct zoo_header zoo_header = {
  516. X   TEXT,
  517. X   ZOO_TAG,
  518. X   (long) SIZ_ZOOH,
  519. X   (long) (-SIZ_ZOOH),
  520. X   MAJOR_VER,
  521. X   MINOR_VER
  522. X};
  523. Xchar file_leader[] = FILE_LEADER;
  524. Xextern int quiet;
  525. Xint break_hit;
  526. X
  527. X#ifdef LINT_ARGS
  528. Xint ver_too_high (struct zoo_header *);
  529. X#else
  530. Xint ver_too_high();
  531. X#endif
  532. X
  533. Xvoid zoopack(zoo_path, option)
  534. Xchar *zoo_path, *option;
  535. X{
  536. Xstatic char temp_file[PATHSIZE] = "XXXXXX";
  537. X#ifndef NOSIGNAL
  538. Xint (*oldsignal)();
  539. X#endif
  540. Xregister int zoo_han;                     /* handle for open archive */
  541. Xregister FILE *zoo_file;                  /* stream for open archive */
  542. Xint new_han;                              /* handle of destination archive */
  543. Xlong next_ptr;                            /* pointer to within archive */
  544. Xlong new_dir_pos;                         /* ditto */
  545. Xstruct direntry direntry;                 /* directory entry */
  546. Xstruct zoo_header old_zoo_header;         /* just for reading old header */
  547. Xint status;                               /* error status */
  548. Xint nobackup = 0;                         /* keep backup */
  549. Xint force = 0;                            /* force overwrite of old backup */
  550. Xint extcount = 0;                         /* how many files moved */
  551. Xchar backup_name[PATHSIZE];               /* name of backup */
  552. Xint bad_header = 0;                       /* if archive has bad header */
  553. Xint latest_date = 0;                      /* latest date on any file moved */
  554. Xint latest_time = 0;                      /*  ...likewise */
  555. Xint curr_dir = 0;                                    /* create backup in curr dir */
  556. Xstatic char partial_msg[] =
  557. X   "Partially packed archive left in %s.\n";
  558. X
  559. Xwhile (*option) {
  560. X   switch (*option) {
  561. X      case 'P': force++; break;
  562. X      case 'E': nobackup++; break;
  563. X      case 'q': quiet++; break;
  564. X        case '.': curr_dir++; break;
  565. X      default:
  566. X         prterror ('f', inv_option, *option);
  567. X   }
  568. X   option++;
  569. X}
  570. Xif (force == 1)         /* force only if P was doubled */
  571. X   force--;
  572. X
  573. Xzoo_path = addext (zoo_path, EXT_DFLT);      /* add default extension */
  574. X
  575. X/* Create a backup name by replacing any extension by backup extension. */
  576. Xstrcpy (backup_name, zoo_path);
  577. X{
  578. X   char *temp;
  579. X   if (temp = strrchr (backup_name,EXT_CH))      /* if dot found */
  580. X      strcpy (temp, BACKUP_EXT);                /* replace old extension */
  581. X   else
  582. X      strcat (backup_name, BACKUP_EXT);         /* else just append */
  583. X}
  584. X
  585. X/* Open original archive for read-only access */
  586. Xzoo_file = fopen(zoo_path, FRDSTR);
  587. Xzoo_han = OPEN(zoo_path, F_READ);    /* different open */
  588. X
  589. Xif (zoo_file == NULL || zoo_han == -1)
  590. X   prterror ('f', could_not_open, zoo_path);
  591. X
  592. X/* Read the header of the old archive. */
  593. Xfrd_zooh(&old_zoo_header, zoo_file);
  594. X/* fread ((char *) &old_zoo_header, sizeof(old_zoo_header), 1, zoo_file); */
  595. X
  596. Xif ((old_zoo_header.zoo_start + old_zoo_header.zoo_minus) != 0L) {
  597. X   prterror ('w', failed_consistency);
  598. X   ++bad_header;                    /* remember for future error message */
  599. X}
  600. X
  601. X/* Refuse to pack it if its version number is higher than we can accept */
  602. Xif (ver_too_high (&old_zoo_header))
  603. X   prterror ('f', wrong_version, old_zoo_header.major_ver,
  604. X                                    old_zoo_header.minor_ver);
  605. X
  606. Xfseek (zoo_file, old_zoo_header.zoo_start, 0); /* seek to where data begins */
  607. X
  608. X/* Now see if the archive already exists with the backup extension.  If so,
  609. X   give an error message and abort.  However, we skip this test if the user
  610. X   specified overwriting the backup */
  611. X
  612. Xif (!force) {
  613. X   if (exists (backup_name))
  614. X      prterror ('f', "File %s already exists.  Delete it or use PP option.\n",
  615. X                      backup_name);
  616. X}
  617. X
  618. X/*
  619. XOpen the new archive by a temporary name.  If not otherwise specified,
  620. Xwe open the new archive in the same directory as the original.  But if
  621. Xthe curr_dir switch was given, we leave temp_file unchanged, and it
  622. Xwas already initialized to be just the template XXXXXX.
  623. X*/
  624. Xif (!curr_dir) {
  625. X    strcpy (temp_file, zoo_path);          /* original archive name */
  626. X    *nameptr (temp_file) = '\0';           /* ... minus original filename */
  627. X    strcat (temp_file, "XXXXXX");          /* ... plus XXXXXX */
  628. X}
  629. Xmktemp (temp_file);                    /* ... and make unique */
  630. X
  631. Xnew_han = CREATE(temp_file, F_RDWR);
  632. Xif (new_han == -1)
  633. X   prterror ('f', "Could not create temporary file %s.\n", temp_file);
  634. X
  635. X/* Write the header of the new archive, updated with our own data */
  636. Xwr_zooh (&zoo_header, new_han);
  637. X/* write (new_han, (char *) &zoo_header, sizeof(zoo_header)); */
  638. Xlseek (new_han, zoo_header.zoo_start, 0);       /* position to add files */
  639. X
  640. X/* Now we loop through the old archive's files and add each to the new
  641. Xarchive.  The only changes needed are to update the .next and .offset
  642. Xfields of the directory entry. */
  643. X
  644. Xwhile (1) {
  645. X
  646. X   frd_dir(&direntry, zoo_file);
  647. X/* fread ((char *) &direntry, sizeof (direntry), 1, zoo_file); */
  648. X
  649. X   if (direntry.zoo_tag != ZOO_TAG) {
  650. X      long currpos, zoolength;
  651. X      prterror ('F', bad_directory);
  652. X      if (bad_header) {    /* bad headers means don't save temp file */
  653. X         close (new_han);
  654. X         unlink (temp_file);
  655. X      } else {
  656. X         writenull (new_han, MAXDIRSIZE);    /* write final null entry */
  657. X         printf (partial_msg, temp_file);
  658. X         if ((currpos = ftell (zoo_file)) != -1L)
  659. X            if (fseek (zoo_file, 0L, 2) == 0)
  660. X               if ((zoolength = ftell (zoo_file)) != -1L)
  661. X                  printf (cant_process, zoolength - currpos);
  662. X      }
  663. X      exit (1);
  664. X   }
  665. X   if (direntry.next == 0L) {                /* END OF CHAIN */
  666. X      break;                                 /* EXIT on end of chain */
  667. X   }
  668. X   next_ptr = direntry.next;                 /* ptr to next dir entry */
  669. X
  670. X   if (!direntry.deleted) {
  671. X#ifdef QUIETPACK
  672. X/* nothing */
  673. X#else
  674. X      prterror ('m', "%-14s -- ",
  675. X         direntry.namlen > 0 ? direntry.lfname : direntry.fname);
  676. X#endif
  677. X
  678. X      if (lseek (zoo_han, direntry.offset, 0) == -1L) {
  679. X         prterror ('f', "Could not seek to file data.\n");
  680. X      } else {
  681. X         extcount++;          /* update count of files extracted */
  682. X
  683. X         /* write a directory entry for this file */
  684. X         new_dir_pos = tell (new_han);   /* new direntry pos in new archive */
  685. X
  686. X         /*
  687. X         Write a null directory entry to preserve integrity in case of
  688. X         program being interrupted.  Note:  I don't think it is
  689. X         necessary to save direntry.next but I haven't checked.
  690. X
  691. X         Old code was:
  692. X         writenull(new_han, SIZ_DIRL + direntry.var_dir_len);
  693. X         */
  694. X         {
  695. X            long oldnext;
  696. X            oldnext = direntry.next;
  697. X            direntry.next = 0L;
  698. X            wr_dir(&direntry, new_han);
  699. X            direntry.next = oldnext;
  700. X         }
  701. X
  702. X         lseek (zoo_han, direntry.offset, 0);     /* where to start copying */
  703. X         /* Write file leader and remember position of new file data */
  704. X         write (new_han, file_leader, SIZ_FLDR);
  705. X         direntry.offset = tell(new_han);
  706. X         status = getfile (zoo_han, new_han, direntry.size_now, 0);
  707. X         /* if no error copy any comment attached to file */
  708. X         if (status == 0 && direntry.cmt_size != 0) {
  709. X            lseek (zoo_han, direntry.comment, 0);  /* seek to old comment  */
  710. X            direntry.comment = tell (new_han);  /* location of new comment */
  711. X            status = getfile (zoo_han, new_han,
  712. X                                 (long) direntry.cmt_size, 0);
  713. X         }
  714. X
  715. X         if (status != 0) {
  716. X            if (status == 1) {
  717. X               memerr();
  718. X            } else
  719. X               if (status == 2 || status == 3) {
  720. X                  prterror ('F', disk_full);
  721. X                  printf (partial_msg, temp_file);
  722. X                  exit (1);
  723. X               } else
  724. X                  prterror ('f', internal_error);
  725. X         } else {
  726. X            if (latest_date < direntry.date ||
  727. X                     (latest_date == direntry.date &&
  728. X                           latest_time < direntry.time))  {
  729. X               latest_date = direntry.date;
  730. X               latest_time = direntry.time;
  731. X            }
  732. X         }
  733. X         direntry.next = tell (new_han);
  734. X         lseek (new_han, new_dir_pos, 0);    /* position to write direntry */
  735. X
  736. X         break_hit = 0;
  737. X#ifndef NOSIGNAL
  738. X         oldsignal = signal (SIGINT, SIG_IGN);
  739. X         if (oldsignal != SIG_IGN)
  740. X            signal (SIGINT, handle_break);
  741. X#endif
  742. X
  743. X         if (wr_dir (&direntry, new_han) != -1 &&
  744. X            write (new_han, file_leader, SIZ_FLDR) != -1) {
  745. X#ifdef QUIETPACK
  746. X            /* prterror ('M', "."); */ ;
  747. X#else
  748. X            prterror ('M', "moved\n");
  749. X#endif
  750. X         } else
  751. X            prterror ('f', "Write to temporary packed archive %s failed.\n", temp_file);
  752. X#ifndef NOSIGNAL
  753. X         signal (SIGINT, oldsignal);
  754. X#endif
  755. X         if (break_hit)
  756. X            exit (1);
  757. X
  758. X         lseek (new_han, direntry.next, 0);  /* back to end of new archive */
  759. X      }  /* end if (lseek ... */
  760. X   } /* end if (!direntry.deleted) */
  761. X
  762. Xfseek (zoo_file, next_ptr, 0);   /* ..seek to next dir entry */
  763. X} /* end while */
  764. X
  765. Xfclose (zoo_file);
  766. X
  767. X/* write a final null entry */
  768. Xwritenull (new_han, MAXDIRSIZE);
  769. X
  770. X#ifdef NIXTIME
  771. Xclose (new_han);
  772. Xsetutime (temp_file, latest_date, latest_time);
  773. X#else
  774. Xsettime (new_han, latest_date, latest_time);    /* adjust its time */
  775. Xclose (new_han);
  776. X#endif
  777. X
  778. X/* Important note:  At this point, it is assumed that the archive was
  779. X   packed and written to a new file without error.  If control reaches
  780. X   here without the new archive having been written properly, then
  781. X   loss of data due to deletion of the original file could occur.  In
  782. X   other words, if something went wrong, execution MUST NOT reach here. */
  783. X
  784. Xif (extcount == 0) {
  785. X   unlink (temp_file);
  786. X   prterror ('m', "No files moved.\n");
  787. X} else {
  788. X   char new_name[FNAMESIZE];
  789. X   /* (a) if user requested, delete original, else rename it to
  790. X   *.bak.  (b) rename temp file to same base name as zoo_file. */
  791. X
  792. X#ifdef QUIETPACK
  793. X   /* prterror('M', "\n"); */
  794. X#endif
  795. X
  796. X   unlink (backup_name);    /* remove any previous backup in any case */
  797. X   if (nobackup)
  798. X      unlink (zoo_path);
  799. X   else
  800. X      chname (backup_name, zoo_path);
  801. X
  802. X    /* if we are packing into current directory, we will rename temp file
  803. X        to same basename but without the preceding pathname */
  804. X    if (curr_dir)
  805. X        zoo_path = nameptr (zoo_path);        /* strip pathname */
  806. X
  807. X   if (chname (zoo_path, temp_file)) {
  808. X      prterror ('w', "Renaming error.  Packed archive is now in %s.\n", temp_file);
  809. X      exit (1);
  810. X   }
  811. X} /* end if */
  812. X
  813. X} /* end zoopack() */
  814. X
  815. X
  816. X/* handle_break() */
  817. X/* Sets break_hit to 1 when called */
  818. Xint handle_break()
  819. X{
  820. X#ifndef NOSIGNAL
  821. X   signal (SIGINT, SIG_IGN);     /* ignore future control ^Cs for now */
  822. X   break_hit = 1;
  823. X#endif
  824. X}
  825. X
  826. SHAR_EOF
  827. fi
  828. exit 0
  829. #    End of shell archive
  830. -- 
  831. Rahul Dhesi         UUCP:  {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi
  832.  
  833. -- 
  834.  
  835. Rich $alz
  836. Cronus Project, BBN Labs            rsalz@bbn.com
  837. Moderator, comp.sources.unix            sources@uunet.uu.net
  838.