+-+-+-+ Beginning of part 24 +-+-+-+ X#ifdef GETUTIME V`009`009getutime (zoo_path, &zoo_date, &zoo_time);`009/* save archive timestamp X */ X#else X`009`009gettime (zoo_file, &zoo_date, &zoo_time); X#endif X`009`009if (zoo_header.type == 0) X`009`009`009prterror ('f', packfirst); X`009`009if (action == ADJ_LIM)`009`123 X`009`009`009unsigned newgencount;`009 X`009`009`009if (subopt == SET) X`009`009`009`009newgencount = (unsigned) gencount; V`009`009`009else`009`009`009`009`009`009`009`009`009`009`009`009`009`009`009`00 X9`009`009/* INC */ V`009`009`009`009newgencount = (zoo_header.vdata & VFL_GEN) + (unsigned) gencoun Xt; X`009`009`009newgencount &= VFL_GEN;`009`009`009/* reduce to allowed bits */ X`009`009`009zoo_header.vdata &= (`126VFL_GEN); X`009`009`009zoo_header.vdata `124= newgencount; V`009`009`009prterror ('M', "Archive generation limit is now %u\n", newgencount) X; X`009`009`125 else if (action == GEN_ON) `123 X`009`009`009zoo_header.vdata `124= VFL_ON; X`009`009`009prterror ('M', "Archive generations on\n"); X`009`009`125 else if (action == GEN_OFF) `123 X`009`009`009zoo_header.vdata &= (`126VFL_ON); X`009`009`009prterror ('M', "Archive generations off\n"); X`009`009`125 else`032 X`009`009`009prterror ('f', garbled); X`009`009zooseek (zoo_file, 0L, 0);`009`009/* back to begining of file */ X`009`009fwr_zooh (&zoo_header, zoo_file); X#ifdef NIXTIME X`009`009zooclose (zoo_file); V`009`009setutime (zoo_path, zoo_date, zoo_time);`009/* restore archive timestam Xp */ X#else X`009`009settime (zoo_file, zoo_date, zoo_time); X`009`009zooclose (zoo_file); X#endif X`009`009return; X`009`125 X X zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */ X X done = 0; /* loop not done yet */ X while (1) `123 X long this_dir_offset; V this_dir_offset = zootell (zoo_file); /* save pos'n of this dir entry * X/ X frd_dir (&direntry, zoo_file); X if (direntry.zoo_tag != ZOO_TAG) `123 X prterror ('f', bad_directory); X `125 X if (direntry.next == 0L) `123 /* END OF CHAIN */ X break; /* EXIT on end of chain */ X `125 X X`009`009/* select directory entry if it matches criteria */ X`009`009selected = ( X`009`009`009`009`009`009 (action == DEL_UNDEL && direntry.deleted != choice) X `124`124 X`009`009`009`009`009`009 (action != DEL_UNDEL && X `009(dodel && direntry.deleted `124`124 X `009`009`009(dodel < 2 && !direntry.deleted)) X`009`009`009`009`009`009 ) X`009`009`009`009`009 ); X X`009`009/* WARNING: convention of choice=1 for deleted entry must be same as X`009`009in direntry definition in zoo.h */ X`009 X`009`009/* Test for "done" so if "one" option requested, [un]del only 1 file */ X`009`009/* But we go through the whole archive to adjust archive time */ X V`009`009strcpy (matchname, fullpath (&direntry));`009`009/* get full pathname * X/ X`009`009if (zoo_header.vdata & VFL_ON) V`009`009`009add_version (matchname, &direntry);`009`009`009/* add version suffi Xx */ X V`009`009if (!done && selected && needed(matchname, &direntry, &zoo_header)) `12 X3 X`009`009`009prterror ('m', "%-14s -- ", matchname); X`009`009`009delcount++; X`009`009`009if (action == DEL_UNDEL) `123 X`009`009`009`009direntry.deleted = choice; X`009`009`009`009if (choice) V`009`009`009`009`009file_deleted++; /* remember if any files actually dele Xted */ V`009`009`009`125 else `123`009`009`009`009`009`009`009/* ADJ_LIM or ADJ_GENCNT X */ V`009`009`009`009if (direntry.vflag & VFL_ON) `123`009`009/* skip if no versions X */ X`009`009`009`009`009if (action == ADJ_LIM) `123 X`009`009`009`009`009`009unsigned newgencount; X`009`009`009`009`009`009if (subopt == SET) X`009`009`009`009`009`009`009newgencount = (unsigned) gencount; V`009`009`009`009`009`009else `009`009`009`009`009`009`009`009`009`009`009`009`0 X09/* INC */ X`009`009`009`009`009`009`009newgencount = V`009`009`009`009`009`009`009`009(int) (direntry.vflag & VFL_GEN) + (int) gencou Xnt; X`009`009`009`009`009`009newgencount &= VFL_GEN; X`009`009`009`009`009`009direntry.vflag &= (`126VFL_GEN); X`009`009`009`009`009`009direntry.vflag `124= newgencount; X`009`009`009`009`009`009valtoshow = newgencount; V`009`009`009`009`009`125 else `123`009`009`009`009`009`009`009`009`009`009`009` X009`009/* ADJ_GCNT */ X`009`009`009`009`009`009if (subopt == SET) X`009`009`009`009`009`009`009direntry.version_no = (unsigned) gencount; V`009`009`009`009`009`009else `009`009`009`009`009`009`009`009`009`009`009`009`0 X09/* INC */ X`009`009`009`009`009`009`009direntry.version_no += (int) gencount; X`009`009`009`009`009`009direntry.version_no &= VER_MASK; /* avoid extra bits */ X`009`009`009`009`009`009valtoshow = direntry.version_no; X`009`009`009`009`009`125 X`009`009`009`009`125 X`009`009`009`125 X X`009`009`009zooseek (zoo_file, this_dir_offset, 0); X X#ifndef NOSIGNAL V`009`009`009oldsignal = signal (SIGINT, SIG_IGN); /* disable `094C for write * X/ X#endif X`009`009`009if (fwr_dir (&direntry, zoo_file) == -1) X`009`009`009`009prterror ('f', "Could not write to archive\n"); X#ifndef NOSIGNAL X`009`009`009signal (SIGINT, oldsignal); X#endif X`009`009`009if (action == DEL_UNDEL) X`009`009`009`009prterror ('M', choice ? "deleted\n" : "undeleted\n"); X`009`009`009else `123 X`009`009`009`009if (direntry.vflag & VFL_ON) X`009`009`009`009`009prterror ('M', "adjusted to %u\n", valtoshow); X`009`009`009`009else X`009`009`009`009`009prterror ('M', "no generations\n"); X`009`009`009`125 X`009`009`009if (one) X`009`009`009`009done = 1; /* if 1 option, done after 1 file */ X`009`009`125 X X /* remember most recent date and time if entry is not deleted */ X if (!direntry.deleted) X if (direntry.date > latest_date `124`124 X (direntry.date == latest_date && direntry.time > latest_time)) `123 X latest_date = direntry.date; X latest_time = direntry.time; X `125 X zooseek (zoo_file, direntry.next, 0); /* ..seek to next dir entry */ X `125 /* endwhile */ X X if (!delcount) X printf ("Zoo: No files matched.\n"); X else `123 X#ifdef NIXTIME X zooclose (zoo_file); X setutime (zoo_path, latest_date, latest_time); X#else X#if 0 X fflush (zoo_file); /* superstition: might help time stamp */ X#endif X settime (zoo_file, latest_date, latest_time); X#endif X `125 X X#ifndef NIXTIME Xzooclose (zoo_file); X#endif X Vif (file_deleted && pack) `123 /* pack if files were deleted and user asked * X/ X prterror ('M', "-----\nPacking..."); X zoopack (zoo_path, "PP"); X prterror ('M', "done\n"); X`125 X X`125 $ GOSUB UNPACK_FILE $ FILE_IS = "ZOOEXT.C" $ CHECKSUM_IS = 58136946 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X#ifndef LINT X/* @(#) zooext.c 2.21 88/08/24 02:39:04 */ Xstatic char sccsid[]="@(#) zooext.c 2.21 88/08/24 02:39:04"; X#endif /* LINT */ X X/* XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved X(C) Copyright 1988 Rahul Dhesi -- All rights reserved X*/ X#include "options.h" X/* Extract file from archive. Extracts files specified in parameter-list X from archive zoo_path. If none specified, extracts all files from X archive. */ X X#include "zoo.h" X#include "parse.h" /* defines struct for parse() */ X X#include "portable.h" /* portable I/O definitions */ X#include "machine.h" /* machine-specific declarations */ X X#include "zooio.h" X#include "various.h" X X#ifndef NOSIGNAL X#include X#endif X X#include "zoofns.h" X X#ifdef LINT_ARGS Xint makepath (char *); Xint needed (char *, struct direntry *, struct zoo_header *); Xvoid putstr (char *); X#else Xint needed (); Xint makepath (); Xvoid putstr (); X#endif X X#ifdef FATTR Xint setfattr PARMS ((char *, unsigned long)); X#endif /* FATTR */ X Xextern int quiet; X X#include "errors.i" X X/* Following two are used by ctrl_c() also, hence declared here */ Xchar extfname[LFNAMESIZE]; /* filename of extracted file */ Xchar prtfname[LFNAMESIZE]; /* name of extracted file on screen */ Xstatic ZOOFILE this_file; /* file to extract */ X Xstatic int tofile; /* true if not pipe or null device */ Xextern unsigned int crccode; Xextern char *out_buf_adr; /* address of output buffer */ X Xvoid zooext(zoo_path, option) Xchar *zoo_path, *option; X`123 Xchar *whichname; /* which name to extract */ Xchar matchname[PATHSIZE]; /* for pattern matching only */ X#ifndef NOSIGNAL Xint (*oldsignal)(); /* to save previous SIGINT handler */ X#endif XZOOFILE zoo_file; /* open archive */ Xlong next_ptr; /* pointer to within archive */ Xstruct zoo_header zoo_header; /* header for archive */ Xint status; /* error status */ Xint exit_status = 0;`009`009`009`009`009`009`009`009/* exit status */ Vint error_message;`009`009`009`009`009`009`009`009/* Whether to give error mess Xage */ Xunsigned long disk_space; /* disk space left */ Xint matched = 0; /* Any files matched? */ Xint overwrite = 0; /* force overwrite of files? */ Xint supersede = 0;`009`009`009`009`009`009`009`009/* supersede newer files? */ Xint needdel = 0; /* extract deleted files too */ Xint usepath = 0; /* use path for extraction */ Xint todot = 0; /* extract relative to . */ Xint badcrc_count = 0; /* how many files with bad CRC */ Vint bad_header = 0; /* to avoid spurious messages later * X/ Xlong fiz_ofs = 0; /* offset where to start */ Vlong dat_ofs = 0;`009`009`009`009`009`009`009`009`009/* .. and offset of file d Xata */ Xint pipe = 0; /* are we piping output? */ Xint null_device = 0; /* are we sending to null device? */ X#ifndef PORTABLE Xint fast_ext = 0; /* fast extract as *.?Z? */ Xint alloc_size; /* disk allocation unit size */ X#endif Xstruct direntry direntry; /* directory entry */ Xint first_dir = 1;`009`009`009`009`009`009`009`009/* first dir entry seen? */ X Xstatic char extract_ver[] = "Zoo %d.%d is needed to extract %s.\n"; Xstatic char no_space[] = "Insufficient disk space to extract %s.\n"; X Xwhile (*option) `123 X switch (*option) `123 X#ifndef PORTABLE X case 'z': fast_ext++; break; X#endif X case 'x': X case 'e': break; X case 'N': null_device++; break; X case 'O': overwrite += 2; break; X case 'o': overwrite++; break; X case 'p': pipe++; break; X`009`009case 'S': supersede++; break; X case 'd': needdel++; break; X case 'q': quiet++; break; X case '/': usepath++; break; X case '.': todot++; break; X case '@': `009/* if @m,n specified, fiz_ofs = m, dat_ofs = n */ X`009`009`009`123 X`009`009`009`009char *comma_pos; X`009`009`009`009++option; X`009`009`009`009comma_pos = strchr(option, ','); X`009`009`009`009if (comma_pos != NULL) `123 X`009`009`009`009`009dat_ofs = calc_ofs (comma_pos + 1); X`009`009`009`009`009*comma_pos = '\0'; X`009`009`009`009`125 X`009`009`009`009fiz_ofs = calc_ofs(option);`032 X`009`009`009`009goto no_more; X`009`009`009`125 X default: X prterror ('f', inv_option, *option); X /* break; */ X `125 X option++; X`125 X Xno_more: /* come from exit in while loop above */ X X Xif (overwrite == 1) /* must be at least 2 to begin with */ X overwrite--; X Xif (null_device && pipe) `123 X prterror ('f', inv_option, 'p'); X pipe = 0; X`125 X Xif (overwrite && pipe) X prterror ('w', option_ignored, 'O'); X X#ifndef PORTABLE Xif (null_device && fast_ext) `123 X prterror ('w', inv_option, 'N'); X null_device = 0; X`125 X#endif X Xtofile = !pipe && !null_device; /* sending to actual file */ X Xzoo_file = zooopen(zoo_path, Z_READ); X Xif (zoo_file == NOFILE) X prterror ('f', could_not_open, zoo_path); X Xif (fiz_ofs != 0L) `123 /* if offset specified, start there */ X`009prterror ('m', start_ofs, fiz_ofs, dat_ofs); X zooseek (zoo_file, fiz_ofs, 0); X`125 else `123 X /* read header */ X frd_zooh (&zoo_header, zoo_file); X if ((zoo_header.zoo_start + zoo_header.zoo_minus) != 0L) `123 X prterror ('w', failed_consistency); X bad_header++; X`009`009exit_status = 1; X `125 X zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */ X`125 X X#ifndef PORTABLE Xdisk_space = space (0, &alloc_size); /* remember disk space left */ X#else Xdisk_space = MAXLONG; /* infinite disk space */ X#endif X X/* if piping output we open the output device just once */ Xif (null_device) `123 X this_file = NULLFILE; X`125 else if (pipe) X this_file = STDOUT; /* standard output */ X Xwhile (1) `123 X frd_dir (&direntry, zoo_file); X if (direntry.zoo_tag != ZOO_TAG) `123 X long currpos, zoolength; X`009`009prterror ('F', invalid_header); X X`009`009/* Note: if header was bad, there's no point trying to find X`009`009`009how many more bytes aren't processed -- our seek position is X`009`009`009likely very wrong */ X X`009`009if (!bad_header) X`009`009`009if ((currpos = zootell (zoo_file)) != -1L) X`009`009`009`009if (zooseek (zoo_file, 0L, 2) != -1) X`009`009`009`009`009if ((zoolength = zootell (zoo_file)) != -1L) V`009`009`009`009`009`009printf (cant_process, zoolength - currpos); `032 X `032 X`009`009zooexit (1); X `125 X if (direntry.next == 0L) `123 /* END OF CHAIN */ X break; /* EXIT on end of chain */ X `125 V`009/* when first direntry read, change dat_ofs from abs. pos. to rel. offset * X/ X`009if (first_dir && dat_ofs != 0) `123 X`009`009dat_ofs -= direntry.offset; X`009`009first_dir = 0; X`009`125 X next_ptr = direntry.next + dat_ofs; /* ptr to next dir entry */ X X whichname = choosefname(&direntry); /* which filename */ X`009whichname = strdup(whichname);`009`009`009`009/* bug fix */ X fixfname(whichname); /* fix syntax */ X`009strcpy (matchname, fullpath (&direntry));`009/* get full pathname */ X`009if (zoo_header.vdata & VFL_ON) X`009`009add_version (matchname, &direntry);`009`009/* add version suffix */ X X/* if extraction to subtree rooted at curr dir, modify pathname */ X#if 0 X#ifdef DIR_LBRACK X if (todot && direntry.dirname[0] == *DIR_LBRACK && X direntry.dirname[1] != *CUR_DIR) `123 X char tmpstr[PATHSIZE]; X strcpy (tmpstr, DIR_LBRACK); X strcat (tmpstr, CUR_DIR); X strcat (tmpstr, &direntry.dirname[1]); X strcpy (direntry.dirname, tmpstr); X `125 X#endif X#endif X X /* hard-coded '/' should be eventually removed */ X if (todot && *direntry.dirname == '/') `123`032 X char tmpstr[PATHSIZE]; X strcpy(tmpstr, direntry.dirname); X strcpy(direntry.dirname,CUR_DIR); X strcat(direntry.dirname, tmpstr); X `125 X X /* matchname now holds the full pathname for pattern matching */ X X if ( ( (needdel && direntry.deleted) `124`124 X (needdel < 2 && !direntry.deleted) X ) && needed(matchname, &direntry, &zoo_header)) `123 X matched++; /* update count of files extracted */ X X if (direntry.major_ver > MAJOR_EXT_VER `124`124 X (direntry.major_ver == MAJOR_EXT_VER &&`032 X direntry.minor_ver > MINOR_EXT_VER)) `123 X prterror ('e', extract_ver, direntry.major_ver,`032 X direntry.minor_ver, whichname); X`009`009`009`009exit_status = 1; X goto loop_again; X `125 X X /*`032 X If extracting to null device, or if user requested extraction X of entire path, include any directory name in filename. X If extraction to current directory requested, and if extfname X begins with path separator, fix it */ X X strcpy (extfname, whichname); X if ((usepath `124`124 null_device) && direntry.dirlen != 0) `123 X combine(extfname, direntry.dirname, whichname); X if (usepath > 1 && !null_device) X makepath(direntry.dirname); /* make dir prefix */ X `125 X X`009`009strcpy(prtfname, extfname); X`009`009if (zoo_header.vdata & VFL_ON) X`009`009`009add_version (prtfname, &direntry); X X if (tofile) `123 X int present = 0; X X#ifndef PORTABLE X /*`032 X if Z format (fast) extraction, extension is created as X follows: for no current extension, new extension is "zzz"; X for current extension "a", new extension is "azz"; for`032 X current extension "ab", new extension is "azb"; and for X current extension "abc", new extension is "azc". X */ X `032 X if (fast_ext) `123 X int length; X struct path_st path_st; X parse (&path_st, extfname); /* split filename */ X strcpy (extfname, path_st.fname); /* just root filename */ X length = strlen (path_st.ext); X strcat (extfname, "."); X if (length == 0) X strcat (extfname, "zzz"); /* no ext -> .zzz */ X else if (length == 1) `123 X strcat (extfname, path_st.ext); X strcat (extfname, "zz"); /* *.? -> *.?zz */ X `125 else `123 /* length is 2 or 3 */ X if (length == 2) /* allow .aa, .ab, etc. */ X path_st.ext[2] = path_st.ext[1]; X path_st.ext[1] = 'z'; X strcat (extfname, path_st.ext); /* *.?? -> *.?z? */ X `125 X`009`009`009`009strcpy(prtfname, direntry.fname); X`009`009`009`009add_version (prtfname, &direntry); X `125 X#endif /* ifndef PORTABLE */ X X`009`009`009/* don't extract if archived file is older than disk copy */ X`009`009`009if (!supersede && exists(extfname)) `123 X`009`009`009`009unsigned int ddate, dtime; X#ifdef GETUTIME X`009`009`009`009getutime (extfname, &ddate, &dtime); X#else X`009`009`009`009ZOOFILE tfile; X`009`009`009`009ddate = dtime = 0xffff;`009`009`009`009`009/* assume maximum */ X`009`009`009`009tfile = zooopen(extfname, Z_READ); X`009`009`009`009if (tfile == NOFILE) X`009`009`009`009`009goto loop_again; X`009`009`009`009gettime (tfile, &ddate, &dtime); X`009`009`009`009zooclose (tfile); X#endif V`009`009`009`009if (cmpnum (direntry.date, direntry.time, ddate, dtime) <= 0) ` X123 X`009`009`009`009`009prterror ('m', "%-14s -- skipped\n", prtfname); X`009`009`009`009`009goto loop_again; X`009`009`009`009`125 X`009`009`009`125 X X if (overwrite) `123 X this_file = zoocreate (extfname); X#ifdef FATTR X`009`009`009`009/* if can't open file, and OO option, make it writable first */ X`009`009`009`009if (this_file == NOFILE && overwrite >= 4 &&`032 X`009`009`009`009`009`009(direntry.fattr >> 22) == 1 && exists(extfname)) `123 V`009`009`009`009`009setfattr (extfname, (unsigned long) (1L << 7) `124 direntry X.fattr); X`009`009`009`009`009this_file = zoocreate (extfname); X`009`009`009`009`125 X#endif /* FATTR */ X `125 else `123 X if (exists (extfname)) `123 X present = 1; X this_file = NOFILE; X `125 else X this_file = zoocreate (extfname); -+-+-+-+-+ End of part 24 +-+-+-+-+-