157266Smuller /*- 257266Smuller * Copyright (c) 1992 Keith Muller. 357266Smuller * Copyright (c) 1992 The Regents of the University of California. 457266Smuller * All rights reserved. 557266Smuller * 657266Smuller * This code is derived from software contributed to Berkeley by 757266Smuller * Keith Muller of the University of California, San Diego. 857266Smuller * 957266Smuller * %sccs.include.redist.c% 1057266Smuller */ 1157266Smuller 1257266Smuller #ifndef lint 13*58652Smuller static char sccsid[] = "@(#)ar_subs.c 1.5 (Berkeley) 03/12/93"; 1457266Smuller #endif /* not lint */ 1557266Smuller 1657266Smuller #include <sys/types.h> 1757266Smuller #include <sys/time.h> 1857266Smuller #include <sys/stat.h> 1957266Smuller #include <sys/param.h> 2057266Smuller #include <signal.h> 2157266Smuller #include <string.h> 2257266Smuller #include <stdio.h> 2357266Smuller #include <ctype.h> 2457266Smuller #include <fcntl.h> 2557266Smuller #include <errno.h> 2657266Smuller #include <unistd.h> 2757266Smuller #include <stdlib.h> 2857266Smuller #include "pax.h" 2957266Smuller #include "extern.h" 3057266Smuller 3157583Smuller static void wr_archive __P((register ARCHD *, int is_app)); 3257266Smuller static int get_arc __P((void)); 3357266Smuller static int next_head __P((register ARCHD *)); 3457266Smuller extern sigset_t s_mask; 3557266Smuller 3657266Smuller /* 3757266Smuller * Routines which control the overall operation modes of pax as specified by 3857266Smuller * the user: list, append, read ... 3957266Smuller */ 4057266Smuller 4157266Smuller static char hdbuf[BLKMULT]; /* space for archive header on read */ 4257266Smuller u_long flcnt; /* number of files processed */ 4357266Smuller 4457266Smuller /* 4557266Smuller * list() 4657266Smuller * list the contents of an archive which match user supplied pattern(s) 4757266Smuller * (no pattern matches all). 4857266Smuller */ 4957266Smuller 5057266Smuller #if __STDC__ 5157266Smuller void 5257266Smuller list(void) 5357266Smuller #else 5457266Smuller void 5557266Smuller list() 5657266Smuller #endif 5757266Smuller { 5857266Smuller register ARCHD *arcn; 5957266Smuller register int res; 6057266Smuller ARCHD archd; 6157266Smuller time_t now; 6257266Smuller 6357266Smuller arcn = &archd; 6457266Smuller /* 6557266Smuller * figure out archive type; pass any format specific options to the 6657266Smuller * archive option processing routine; call the format init routine. We 6757266Smuller * also save current time for ls_list() so we do not make a system 6857266Smuller * call for each file we need to print. If verbose (vflag) start up 6957266Smuller * the name and group caches. 7057266Smuller */ 7157266Smuller if ((get_arc() < 0) || ((*frmt->options)() < 0) || 7257266Smuller ((*frmt->st_rd)() < 0)) 7357266Smuller return; 7457266Smuller 7557266Smuller if (vflag && ((uidtb_start() < 0) || (gidtb_start() < 0))) 7657266Smuller return; 7757266Smuller 7857266Smuller now = time((time_t *)NULL); 7957266Smuller 8057266Smuller /* 8157266Smuller * step through the archive until the format says it is done 8257266Smuller */ 8357266Smuller while (next_head(arcn) == 0) { 8457266Smuller /* 8557266Smuller * check for pattern, and user specified options match. 8657266Smuller * When all patterns are matched we are done. 8757266Smuller */ 8857266Smuller if ((res = pat_match(arcn)) < 0) 8957266Smuller break; 9057266Smuller 9157266Smuller if ((res == 0) && (sel_chk(arcn) == 0)) { 9257266Smuller /* 9357266Smuller * pattern resulted in a selected file 9457266Smuller */ 9557266Smuller if (pat_sel(arcn) < 0) 9657266Smuller break; 9757266Smuller 9857266Smuller /* 9957266Smuller * modify the name as requested by the user if name 10057266Smuller * survives modification, do a listing of the file 10157266Smuller */ 10257266Smuller if ((res = mod_name(arcn)) < 0) 10357266Smuller break; 10457266Smuller if (res == 0) 10557266Smuller ls_list(arcn, now); 10657266Smuller } 10757266Smuller 10857266Smuller /* 10957266Smuller * skip to next archive format header using values calculated 11057266Smuller * by the format header read routine 11157266Smuller */ 11257266Smuller if (rd_skip(arcn->skip + arcn->pad) == 1) 11357266Smuller break; 11457266Smuller } 11557266Smuller 11657266Smuller /* 11757266Smuller * all done, let format have a chance to cleanup, and make sure that 11857266Smuller * the patterns supplied by the user were all matched 11957266Smuller */ 12057266Smuller (void)(*frmt->end_rd)(); 12157266Smuller (void)sigprocmask(SIG_BLOCK, &s_mask, (sigset_t *)NULL); 12257266Smuller ar_close(); 12357266Smuller pat_chk(); 12457266Smuller } 12557266Smuller 12657266Smuller /* 12757266Smuller * extract() 12857266Smuller * extract the member(s) of an archive as specified by user supplied 12957266Smuller * pattern(s) (no patterns extracts all members) 13057266Smuller */ 13157266Smuller 13257266Smuller #if __STDC__ 13357266Smuller void 13457266Smuller extract(void) 13557266Smuller #else 13657266Smuller void 13757266Smuller extract() 13857266Smuller #endif 13957266Smuller { 14057266Smuller register ARCHD *arcn; 14157266Smuller register int res; 14257266Smuller off_t cnt; 14357266Smuller ARCHD archd; 14457266Smuller struct stat sb; 14557266Smuller int fd; 14657266Smuller 14757266Smuller arcn = &archd; 14857266Smuller /* 14957266Smuller * figure out archive type; pass any format specific options to the 15057266Smuller * archive option processing routine; call the format init routine; 15157266Smuller * start up the directory modification time and access mode database 15257266Smuller */ 15357266Smuller if ((get_arc() < 0) || ((*frmt->options)() < 0) || 15457266Smuller ((*frmt->st_rd)() < 0) || (dir_start() < 0)) 15557266Smuller return; 15657266Smuller 15757266Smuller /* 15857266Smuller * When we are doing interactive rename, we store the mapping of names 15957266Smuller * so we can fix up hard links files later in the archive. 16057266Smuller */ 16157266Smuller if (iflag && (name_start() < 0)) 16257266Smuller return; 16357266Smuller 16457266Smuller /* 16557266Smuller * step through each entry on the archive until the format read routine 16657266Smuller * says it is done 16757266Smuller */ 16857266Smuller while (next_head(arcn) == 0) { 16957266Smuller 17057266Smuller /* 17157266Smuller * check for pattern, and user specified options match. When 17257266Smuller * all the patterns are matched we are done 17357266Smuller */ 17457266Smuller if ((res = pat_match(arcn)) < 0) 17557266Smuller break; 17657266Smuller 17757266Smuller if ((res > 0) || (sel_chk(arcn) != 0)) { 17857266Smuller /* 17957266Smuller * file is not selected. skip past any file data and 18057266Smuller * padding and go back for the next archive member 18157266Smuller */ 18257266Smuller (void)rd_skip(arcn->skip + arcn->pad); 18357266Smuller continue; 18457266Smuller } 18557266Smuller 18657266Smuller /* 18757536Smuller * with -u or -D only extract when the archive member is newer 18857536Smuller * than the file with the same name in the file system (nos 18957536Smuller * test of being the same type is required). 19057266Smuller * NOTE: this test is done BEFORE name modifications as 19157266Smuller * specified by pax. this operation can be confusing to the 19257266Smuller * user who might expect the test to be done on an existing 19357266Smuller * file AFTER the name mod. In honesty the pax spec is probably 19457266Smuller * flawed in this respect. 19557266Smuller */ 19657536Smuller if ((uflag || Dflag) && ((lstat(arcn->name, &sb) == 0))) { 19757536Smuller if (uflag && Dflag) { 19857536Smuller if ((arcn->sb.st_mtime <= sb.st_mtime) && 19957536Smuller (arcn->sb.st_ctime <= sb.st_ctime)) { 20057536Smuller (void)rd_skip(arcn->skip + arcn->pad); 20157536Smuller continue; 20257536Smuller } 20357536Smuller } else if (Dflag) { 20457536Smuller if (arcn->sb.st_ctime <= sb.st_ctime) { 20557536Smuller (void)rd_skip(arcn->skip + arcn->pad); 20657536Smuller continue; 20757536Smuller } 20857536Smuller } else if (arcn->sb.st_mtime <= sb.st_mtime) { 20957536Smuller (void)rd_skip(arcn->skip + arcn->pad); 21057536Smuller continue; 21157536Smuller } 21257266Smuller } 21357266Smuller 21457266Smuller /* 21557266Smuller * this archive member is now been selected. modify the name. 21657266Smuller */ 21757536Smuller if ((pat_sel(arcn) < 0) || ((res = mod_name(arcn)) < 0)) 21857266Smuller break; 21957266Smuller if (res > 0) { 22057266Smuller /* 22157266Smuller * a bad name mod, skip and purge name from link table 22257266Smuller */ 22357266Smuller purg_lnk(arcn); 22457266Smuller (void)rd_skip(arcn->skip + arcn->pad); 22557266Smuller continue; 22657266Smuller } 22757266Smuller 22857266Smuller /* 22957536Smuller * Non standard -Y and -Z flag. When the exisiting file is 23057536Smuller * same age or newer skip 23157266Smuller */ 23257536Smuller if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) { 23357536Smuller if (Yflag && Zflag) { 23457536Smuller if ((arcn->sb.st_mtime <= sb.st_mtime) && 23557536Smuller (arcn->sb.st_ctime <= sb.st_ctime)) { 23657536Smuller (void)rd_skip(arcn->skip + arcn->pad); 23757536Smuller continue; 23857536Smuller } 23957536Smuller } else if (Yflag) { 24057536Smuller if (arcn->sb.st_ctime <= sb.st_ctime) { 24157536Smuller (void)rd_skip(arcn->skip + arcn->pad); 24257536Smuller continue; 24357536Smuller } 24457536Smuller } else if (arcn->sb.st_mtime <= sb.st_mtime) { 24557536Smuller (void)rd_skip(arcn->skip + arcn->pad); 24657536Smuller continue; 24757536Smuller } 24857266Smuller } 24957266Smuller 25057266Smuller if (vflag) { 25157266Smuller (void)fputs(arcn->name, stderr); 25257266Smuller vfpart = 1; 25357266Smuller } 25457266Smuller 25557266Smuller /* 25657266Smuller * all ok, extract this member based on type 25757266Smuller */ 25857266Smuller if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) { 25957266Smuller /* 26057266Smuller * process archive members that are not regular files. 26157266Smuller * throw out padding and any data that might follow the 26257266Smuller * header (as determined by the format). 26357266Smuller */ 26457266Smuller if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) 26557266Smuller res = lnk_creat(arcn); 26657266Smuller else 26757266Smuller res = node_creat(arcn); 26857266Smuller 26957266Smuller (void)rd_skip(arcn->skip + arcn->pad); 27057266Smuller if (res < 0) 27157266Smuller purg_lnk(arcn); 27257266Smuller 27357266Smuller if (vflag && vfpart) { 27457266Smuller (void)putc('\n', stderr); 27557266Smuller vfpart = 0; 27657266Smuller } 27757266Smuller continue; 27857266Smuller } 27957266Smuller /* 28057266Smuller * we have a file with data here. If we can not create it, skip 28157266Smuller * over the data and purge the name from hard link table 28257266Smuller */ 28357266Smuller if ((fd = file_creat(arcn)) < 0) { 28457266Smuller (void)rd_skip(arcn->skip + arcn->pad); 28557266Smuller purg_lnk(arcn); 28657266Smuller continue; 28757266Smuller } 28857266Smuller /* 28957266Smuller * extract the file from the archive and skip over padding and 29057266Smuller * any unprocessed data 29157266Smuller */ 29257266Smuller res = (*frmt->rd_data)(arcn, fd, &cnt); 29357266Smuller file_close(arcn, fd); 29457266Smuller if (vflag && vfpart) { 29557266Smuller (void)putc('\n', stderr); 29657266Smuller vfpart = 0; 29757266Smuller } 29857266Smuller if (!res) 29957266Smuller (void)rd_skip(cnt + arcn->pad); 30057266Smuller } 30157266Smuller 30257266Smuller /* 30357266Smuller * all done, restore directory modes and times as required; make sure 30457266Smuller * all patterns supplied by the user were matched; block off signals 30557266Smuller * to avoid chance for multiple entry into the cleanup code. 30657266Smuller */ 30757266Smuller (void)(*frmt->end_rd)(); 30857266Smuller (void)sigprocmask(SIG_BLOCK, &s_mask, (sigset_t *)NULL); 30957266Smuller ar_close(); 31057266Smuller proc_dir(); 31157266Smuller pat_chk(); 31257266Smuller } 31357266Smuller 31457266Smuller /* 31557266Smuller * wr_archive() 31657266Smuller * Write an archive. used in both creating a new archive and appends on 31757266Smuller * previously written archive. 31857266Smuller */ 31957266Smuller 32057266Smuller #if __STDC__ 32157266Smuller static void 32257583Smuller wr_archive(register ARCHD *arcn, int is_app) 32357266Smuller #else 32457266Smuller static void 32557583Smuller wr_archive(arcn, is_app) 32657266Smuller register ARCHD *arcn; 32757583Smuller int is_app; 32857266Smuller #endif 32957266Smuller { 33057266Smuller register int res; 33157266Smuller register int hlk; 33257583Smuller register int wr_one; 33357266Smuller off_t cnt; 33457266Smuller int (*wrf)(); 33557266Smuller int fd = -1; 33657266Smuller 33757266Smuller /* 33857266Smuller * if this format supports hard link storage, start up the database 33957266Smuller * that detects them. 34057266Smuller */ 34157266Smuller if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0)) 34257266Smuller return; 34357266Smuller 34457266Smuller /* 34557266Smuller * start up the file traversal code and format specific write 34657266Smuller */ 34757266Smuller if ((ftree_start() < 0) || ((*frmt->st_wr)() < 0)) 34857266Smuller return; 34957266Smuller wrf = frmt->wr; 35057266Smuller 35157266Smuller /* 35257266Smuller * When we are doing interactive rename, we store the mapping of names 35357266Smuller * so we can fix up hard links files later in the archive. 35457266Smuller */ 35557266Smuller if (iflag && (name_start() < 0)) 35657266Smuller return; 35757266Smuller 35857266Smuller /* 35957583Smuller * if this not append, and there are no files, we do no write a trailer 36057583Smuller */ 36157583Smuller wr_one = is_app; 36257583Smuller 36357583Smuller /* 36457266Smuller * while there are files to archive, process them one at at time 36557266Smuller */ 36657266Smuller while (next_file(arcn) == 0) { 36757266Smuller /* 36857266Smuller * check if this file meets user specified options match. 36957266Smuller */ 37057266Smuller if (sel_chk(arcn) != 0) 37157266Smuller continue; 37257266Smuller fd = -1; 37357266Smuller if (uflag) { 37457266Smuller /* 37557266Smuller * only archive if this file is newer than a file with 37657266Smuller * the same name that is already stored on the archive 37757266Smuller */ 37857266Smuller if ((res = chk_ftime(arcn)) < 0) 37957266Smuller break; 38057266Smuller if (res > 0) 38157266Smuller continue; 38257266Smuller } 38357266Smuller 38457266Smuller /* 38557266Smuller * this file is considered selected now. see if this is a hard 38657266Smuller * link to a file already stored 38757266Smuller */ 38857266Smuller ftree_sel(arcn); 38957266Smuller if (hlk && (chk_lnk(arcn) < 0)) 39057266Smuller break; 39157266Smuller 39257266Smuller if ((arcn->type == PAX_REG) || (arcn->type == PAX_HRG) || 39357266Smuller (arcn->type == PAX_CTG)) { 39457266Smuller /* 39557266Smuller * we will have to read this file. by opening it now we 39657266Smuller * can avoid writing a header to the archive for a file 39757266Smuller * we were later unable to read (we also purge it from 39857266Smuller * the link table). 39957266Smuller */ 40057266Smuller if ((fd = open(arcn->org_name, O_RDONLY, 0)) < 0) { 40157266Smuller syswarn(1,errno, "Unable to open %s to read", 40257266Smuller arcn->org_name); 40357266Smuller purg_lnk(arcn); 40457266Smuller continue; 40557266Smuller } 40657266Smuller } 40757266Smuller 40857266Smuller /* 40957266Smuller * Now modify the name as requested by the user 41057266Smuller */ 41157266Smuller if ((res = mod_name(arcn)) < 0) { 41257266Smuller /* 41357266Smuller * name modification says to skip this file, close the 41457266Smuller * file and purge link table entry 41557266Smuller */ 41657266Smuller rdfile_close(arcn, &fd); 41757266Smuller purg_lnk(arcn); 41857266Smuller break; 41957266Smuller } 42057266Smuller 42157266Smuller if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) { 42257266Smuller /* 42357266Smuller * unable to obtain the crc we need, close the file, 42457266Smuller * purge link table entry 42557266Smuller */ 42657266Smuller rdfile_close(arcn, &fd); 42757266Smuller purg_lnk(arcn); 42857266Smuller continue; 42957266Smuller } 43057266Smuller 43157266Smuller if (vflag) { 43257266Smuller (void)fputs(arcn->name, stderr); 43357266Smuller vfpart = 1; 43457266Smuller } 43557266Smuller ++flcnt; 43657266Smuller 43757266Smuller /* 43857266Smuller * looks safe to store the file, have the format specific 43957266Smuller * routine write routine store the file header on the archive 44057266Smuller */ 44157266Smuller if ((res = (*wrf)(arcn)) < 0) { 44257266Smuller rdfile_close(arcn, &fd); 44357266Smuller break; 44457266Smuller } 44557583Smuller wr_one = 1; 44657266Smuller if (res > 0) { 44757266Smuller /* 44857266Smuller * format write says no file data needs to be stored 44957266Smuller * so we are done messing with this file 45057266Smuller */ 45157266Smuller if (vflag && vfpart) { 45257266Smuller (void)putc('\n', stderr); 45357266Smuller vfpart = 0; 45457266Smuller } 45557266Smuller rdfile_close(arcn, &fd); 45657266Smuller continue; 45757266Smuller } 45857266Smuller 45957266Smuller /* 46057266Smuller * Add file data to the archive, quit on write error. if we 46157266Smuller * cannot write the entire file contents to the archive we 46257266Smuller * must pad the archive to replace the missing file data 46357266Smuller * (otherwise during an extract the file header for the file 46457266Smuller * which FOLLOWS this one will not be where we expect it to 46557266Smuller * be). 46657266Smuller */ 46757266Smuller res = (*frmt->wr_data)(arcn, fd, &cnt); 46857266Smuller rdfile_close(arcn, &fd); 46957266Smuller if (vflag && vfpart) { 47057266Smuller (void)putc('\n', stderr); 47157266Smuller vfpart = 0; 47257266Smuller } 47357266Smuller if (res < 0) 47457266Smuller break; 47557266Smuller 47657266Smuller /* 47757266Smuller * pad as required, cnt is number of bytes not written 47857266Smuller */ 47957266Smuller if (((cnt > 0) && (wr_skip(cnt) < 0)) || 48057266Smuller ((arcn->pad > 0) && (wr_skip(arcn->pad) < 0))) 48157266Smuller break; 48257266Smuller } 48357266Smuller 48457266Smuller /* 48557266Smuller * tell format to write trailer; pad to block boundry; reset directory 48657266Smuller * mode/access times, and check if all patterns supplied by the user 48757266Smuller * were matched. block off signals to avoid chance for multiple entry 48857266Smuller * into the cleanup code 48957266Smuller */ 49057583Smuller if (wr_one) { 49157583Smuller (*frmt->end_wr)(); 49257583Smuller wr_fin(); 49357583Smuller } 49457266Smuller (void)sigprocmask(SIG_BLOCK, &s_mask, (sigset_t *)NULL); 49557266Smuller ar_close(); 49657266Smuller if (tflag) 49757266Smuller proc_dir(); 49857266Smuller ftree_chk(); 49957266Smuller } 50057266Smuller 50157266Smuller /* 50257266Smuller * append() 50357266Smuller * Add file to previously written archive. Archive format specified by the 50457266Smuller * user must agree with archive. The archive is read first to collect 50557266Smuller * modification times (if -u) and locate the archive trailer. The archive 50657266Smuller * is positioned in front of the record with the trailer and wr_archive() 50757266Smuller * is called to add the new members. 50857266Smuller * PAX IMPLEMENTATION DETAIL NOTE: 50957266Smuller * -u is implemented by adding the new members to the end of the archive. 51057266Smuller * Care is taken so that these do not end up as links to the older 51157266Smuller * version of the same file already stored in the archive. It is expected 51257266Smuller * when extraction occurs these newer versions will over-write the older 51357266Smuller * ones stored "earlier" in the archive (this may be a bad assumption as 51457266Smuller * it depends on the implementation of the program doing the extraction). 51557266Smuller * It is really difficult to splice in members without either re-writing 51657266Smuller * the entire archive (from the point were the old version was), or having 51757266Smuller * assistance of the format specification in terms of a special update 51857266Smuller * header that invalidates a previous archive record. The posix spec left 51957266Smuller * the method used to implement -u unspecified. This pax is able to 52057266Smuller * over write existing files that it creates. 52157266Smuller */ 52257266Smuller 52357266Smuller #if __STDC__ 52457266Smuller void 52557266Smuller append(void) 52657266Smuller #else 52757266Smuller void 52857266Smuller append() 52957266Smuller #endif 53057266Smuller { 53157266Smuller register ARCHD *arcn; 53257266Smuller register int res; 53357266Smuller ARCHD archd; 53457266Smuller FSUB *orgfrmt; 53557266Smuller int udev; 53657266Smuller off_t tlen; 53757266Smuller 53857266Smuller arcn = &archd; 53957266Smuller orgfrmt = frmt; 54057266Smuller 54157266Smuller /* 54257266Smuller * Do not allow an append operation if the actual archive is of a 54357266Smuller * different format than the user specified foramt. 54457266Smuller */ 54557266Smuller if (get_arc() < 0) 54657266Smuller return; 54757266Smuller if ((orgfrmt != NULL) && (orgfrmt != frmt)) { 54857266Smuller warn(1, "Cannot mix current archive format %s with %s", 54957266Smuller frmt->name, orgfrmt->name); 55057266Smuller return; 55157266Smuller } 55257266Smuller 55357266Smuller /* 55457266Smuller * pass the format any options and start up format 55557266Smuller */ 55657266Smuller if (((*frmt->options)() < 0) || ((*frmt->st_rd)() < 0)) 55757266Smuller return; 55857266Smuller 55957266Smuller /* 56057266Smuller * if we only are adding members that are newer, we need to save the 56157266Smuller * mod times for all files we see. 56257266Smuller */ 56357266Smuller if (uflag && (ftime_start() < 0)) 56457266Smuller return; 56557266Smuller 56657266Smuller /* 56757266Smuller * some archive formats encode hard links by recording the device and 56857266Smuller * file serial number (inode) but copy the file anyway (multiple times) 56957266Smuller * to the archive. When we append, we run the risk that newly added 57057266Smuller * files may have the same device and inode numbers as those recorded 57157266Smuller * on the archive but during a previous run. If this happens, when the 57257266Smuller * archive is extracted we get INCORRECT hard links. We avoid this by 57357266Smuller * remapping the device numbers so that newly added files will never 57457266Smuller * use the same device number as one found on the archive. remapping 57557266Smuller * allows new members to safely have links among themselves. remapping 57657266Smuller * also avoids problems with file inode (serial number) truncations 57757266Smuller * when the inode number is larger than storage space in the archive 57857266Smuller * header. See the remap routines for more details. 57957266Smuller */ 58057266Smuller if ((udev = frmt->udev) && (dev_start() < 0)) 58157266Smuller return; 58257266Smuller 58357266Smuller /* 58457577Smuller * reading the archive may take a long time. If verbose tell the user 58557577Smuller */ 58657577Smuller if (vflag) { 58757577Smuller (void)fputs("pax: Reading archive to position at the end...", 58857577Smuller stderr); 58957577Smuller vfpart = 1; 59057577Smuller } 59157577Smuller 59257577Smuller /* 59357266Smuller * step through the archive until the format says it is done 59457266Smuller */ 59557266Smuller while (next_head(arcn) == 0) { 59657266Smuller /* 59757266Smuller * check if this file meets user specified options. 59857266Smuller */ 59957266Smuller if (sel_chk(arcn) != 0) { 60057266Smuller if (rd_skip(arcn->skip + arcn->pad) == 1) 60157266Smuller break; 60257266Smuller continue; 60357266Smuller } 60457577Smuller 60557266Smuller if (uflag) { 60657266Smuller /* 60757266Smuller * see if this is the newest version of this file has 60857266Smuller * already been seen, if so skip. 60957266Smuller */ 61057266Smuller if ((res = chk_ftime(arcn)) < 0) 61157266Smuller break; 61257266Smuller if (res > 0) { 61357266Smuller if (rd_skip(arcn->skip + arcn->pad) == 1) 61457266Smuller break; 61557266Smuller continue; 61657266Smuller } 61757266Smuller } 61857266Smuller 61957266Smuller /* 62057266Smuller * Store this device number. Device numbers seen during the 62157266Smuller * read phase of append will cause newly appended files with a 62257266Smuller * device number seen in the old part of the archive to be 62357266Smuller * remapped to an unused device number. 62457266Smuller */ 62557266Smuller if ((udev && (add_dev(arcn) < 0)) || 62657266Smuller (rd_skip(arcn->skip + arcn->pad) == 1)) 62757266Smuller break; 62857266Smuller } 62957266Smuller 63057266Smuller /* 63157266Smuller * done, finish up read and get the number of bytes to back up so we 63257266Smuller * can add new members. The format might have used the hard link table, 63357266Smuller * purge it. 63457266Smuller */ 63557266Smuller tlen = (*frmt->end_rd)(); 63657266Smuller lnk_end(); 63757266Smuller 63857266Smuller /* 63957266Smuller * try to postion for write, if this fails quit. if any error occurs, 64057266Smuller * we will refuse to write 64157266Smuller */ 64257536Smuller if (appnd_start(tlen) < 0) 64357266Smuller return; 64457266Smuller 64557266Smuller /* 64657577Smuller * tell the user we are done reading. 64757577Smuller */ 64857577Smuller if (vflag && vfpart) { 64957577Smuller (void)fputs("done.\n", stderr); 65057577Smuller vfpart = 0; 65157577Smuller } 65257577Smuller 65357577Smuller /* 65457266Smuller * go to the writing phase to add the new members 65557266Smuller */ 65657583Smuller wr_archive(arcn, 1); 65757266Smuller } 65857266Smuller 65957266Smuller /* 66057266Smuller * archive() 66157266Smuller * write a new archive 66257266Smuller */ 66357266Smuller 66457266Smuller #if __STDC__ 66557266Smuller void 66657266Smuller archive(void) 66757266Smuller #else 66857266Smuller void 66957266Smuller archive() 67057266Smuller #endif 67157266Smuller { 67257266Smuller ARCHD archd; 67357266Smuller 67457266Smuller /* 67557266Smuller * if we only are adding members that are newer, we need to save the 67657266Smuller * mod times for all files; set up for writing; pass the format any 67757266Smuller * options write the archive 67857266Smuller */ 67957266Smuller if ((uflag && (ftime_start() < 0)) || (wr_start() < 0)) 68057266Smuller return; 68157266Smuller if ((*frmt->options)() < 0) 68257266Smuller return; 68357266Smuller 68457583Smuller wr_archive(&archd, 0); 68557266Smuller } 68657266Smuller 68757266Smuller /* 68857266Smuller * copy() 68957266Smuller * copy files from one part of the file system to another. this does not 69057266Smuller * use any archive storage. The EFFECT OF THE COPY IS THE SAME as if an 69157266Smuller * archive was written and then extracted in the destination directory 69257266Smuller * (except the files are forced to be under the destination directory). 69357266Smuller */ 69457266Smuller 69557266Smuller #if __STDC__ 69657266Smuller void 69757266Smuller copy(void) 69857266Smuller #else 69957266Smuller void 70057266Smuller copy() 70157266Smuller #endif 70257266Smuller { 70357266Smuller register ARCHD *arcn; 70457266Smuller register int res; 70557266Smuller register int fddest; 70657266Smuller register char *dest_pt; 70757266Smuller register int dlen; 70857266Smuller register int drem; 70957266Smuller int fdsrc = -1; 71057266Smuller struct stat sb; 71157266Smuller ARCHD archd; 71257266Smuller char dirbuf[PAXPATHLEN+1]; 71357266Smuller 71457266Smuller arcn = &archd; 71557266Smuller /* 71657266Smuller * set up the destination dir path and make sure it is a directory. We 71757266Smuller * make sure we have a trailing / on the destination 71857266Smuller */ 71957266Smuller dlen = l_strncpy(dirbuf, dirptr, PAXPATHLEN); 72057266Smuller dest_pt = dirbuf + dlen; 72157266Smuller if (*(dest_pt-1) != '/') { 72257266Smuller *dest_pt++ = '/'; 72357266Smuller ++dlen; 72457266Smuller } 72557266Smuller *dest_pt = '\0'; 72657266Smuller drem = PAXPATHLEN - dlen; 72757266Smuller 72857266Smuller if (stat(dirptr, &sb) < 0) { 72957266Smuller syswarn(1, errno, "Cannot access destination directory %s", 73057536Smuller dirptr); 73157266Smuller return; 73257266Smuller } 73357266Smuller if (!S_ISDIR(sb.st_mode)) { 73457536Smuller warn(1, "Destination is not a directory %s", dirptr); 73557266Smuller return; 73657266Smuller } 73757266Smuller 73857266Smuller /* 73957266Smuller * start up the hard link table; file traversal routines and the 74057266Smuller * modification time and access mode database 74157266Smuller */ 74257266Smuller if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0)) 74357266Smuller return; 74457266Smuller 74557266Smuller /* 74657266Smuller * When we are doing interactive rename, we store the mapping of names 74757266Smuller * so we can fix up hard links files later in the archive. 74857266Smuller */ 74957266Smuller if (iflag && (name_start() < 0)) 75057266Smuller return; 75157266Smuller 75257266Smuller /* 75357266Smuller * set up to cp file trees 75457266Smuller */ 75557266Smuller cp_start(); 75657266Smuller 75757266Smuller /* 75857266Smuller * while there are files to archive, process them 75957266Smuller */ 76057266Smuller while (next_file(arcn) == 0) { 76157266Smuller fdsrc = -1; 76257266Smuller 76357266Smuller /* 76457266Smuller * check if this file meets user specified options 76557266Smuller */ 76657266Smuller if (sel_chk(arcn) != 0) 76757266Smuller continue; 76857266Smuller 76957266Smuller /* 77057266Smuller * if there is already a file in the destination directory with 77157266Smuller * the same name and it is newer, skip the one stored on the 77257266Smuller * archive. 77357266Smuller * NOTE: this test is done BEFORE name modifications as 77457266Smuller * specified by pax. this can be confusing to the user who 77557266Smuller * might expect the test to be done on an existing file AFTER 77657266Smuller * the name mod. In honesty the pax spec is probably flawed in 77757266Smuller * this respect 77857266Smuller */ 77957536Smuller if (uflag || Dflag) { 78057266Smuller /* 78157266Smuller * create the destination name 78257266Smuller */ 78357266Smuller if (*(arcn->name) == '/') 78457266Smuller res = 1; 78557266Smuller else 78657266Smuller res = 0; 78757266Smuller if ((arcn->nlen - res) > drem) { 78857266Smuller warn(1, "Destination pathname too long %s", 78957266Smuller arcn->name); 79057266Smuller continue; 79157266Smuller } 79257266Smuller (void)strncpy(dest_pt, arcn->name + res, drem); 79357266Smuller dirbuf[PAXPATHLEN] = '\0'; 79457266Smuller 79557266Smuller /* 79657266Smuller * if existing file is same age or newer skip 79757266Smuller */ 79857266Smuller res = lstat(dirbuf, &sb); 79957266Smuller *dest_pt = '\0'; 80057266Smuller 80157536Smuller if (res == 0) { 80257536Smuller if (uflag && Dflag) { 80357536Smuller if ((arcn->sb.st_mtime<=sb.st_mtime) && 80457536Smuller (arcn->sb.st_ctime<=sb.st_ctime)) 80557536Smuller continue; 80657536Smuller } else if (Dflag) { 80757536Smuller if (arcn->sb.st_ctime <= sb.st_ctime) 80857536Smuller continue; 80957536Smuller } else if (arcn->sb.st_mtime <= sb.st_mtime) 81057536Smuller continue; 81157536Smuller } 81257266Smuller } 81357266Smuller 81457266Smuller /* 81557266Smuller * this file is considered selected. See if this is a hard link 81657266Smuller * to a previous file; modify the name as requested by the 81757266Smuller * user; set the final destination. 81857266Smuller */ 81957266Smuller ftree_sel(arcn); 82057536Smuller if ((chk_lnk(arcn) < 0) || ((res = mod_name(arcn)) < 0)) 82157266Smuller break; 82257266Smuller if ((res > 0) || (set_dest(arcn, dirbuf, dlen) < 0)) { 82357266Smuller /* 82457266Smuller * skip file, purge from link table 82557266Smuller */ 82657266Smuller purg_lnk(arcn); 82757266Smuller continue; 82857266Smuller } 82957266Smuller 83057266Smuller /* 83157536Smuller * Non standard -Y and -Z flag. When the exisiting file is 83257266Smuller * same age or newer skip 83357266Smuller */ 83457536Smuller if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) { 83557536Smuller if (Yflag && Zflag) { 83657536Smuller if ((arcn->sb.st_mtime <= sb.st_mtime) && 83757536Smuller (arcn->sb.st_ctime <= sb.st_ctime)) 83857536Smuller continue; 83957536Smuller } else if (Yflag) { 84057536Smuller if (arcn->sb.st_ctime <= sb.st_ctime) 84157536Smuller continue; 84257536Smuller } else if (arcn->sb.st_mtime <= sb.st_mtime) 84357536Smuller continue; 84457536Smuller } 84557266Smuller 84657266Smuller if (vflag) { 84757266Smuller (void)fputs(arcn->name, stderr); 84857266Smuller vfpart = 1; 84957266Smuller } 85057266Smuller ++flcnt; 85157266Smuller 85257266Smuller /* 85357266Smuller * try to create a hard link to the src file if requested 85457266Smuller * but make sure we are not trying to overwrite ourselves. 85557266Smuller */ 85657266Smuller if (lflag) 85757266Smuller res = cross_lnk(arcn); 85857266Smuller else 85957266Smuller res = chk_same(arcn); 86057266Smuller if (res <= 0) { 86157266Smuller if (vflag && vfpart) { 86257266Smuller (void)putc('\n', stderr); 86357266Smuller vfpart = 0; 86457266Smuller } 86557266Smuller continue; 86657266Smuller } 86757266Smuller 86857266Smuller /* 86957266Smuller * have to create a new file 87057266Smuller */ 87157266Smuller if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) { 87257266Smuller /* 87357266Smuller * create a link or special file 87457266Smuller */ 87557266Smuller if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) 87657266Smuller res = lnk_creat(arcn); 87757266Smuller else 87857266Smuller res = node_creat(arcn); 87957266Smuller if (res < 0) 88057266Smuller purg_lnk(arcn); 88157266Smuller if (vflag && vfpart) { 88257266Smuller (void)putc('\n', stderr); 88357266Smuller vfpart = 0; 88457266Smuller } 88557266Smuller continue; 88657266Smuller } 88757266Smuller 88857266Smuller /* 88957266Smuller * have to copy a regular file to the destination directory. 89057266Smuller * first open source file and then create the destination file 89157266Smuller */ 89257266Smuller if ((fdsrc = open(arcn->org_name, O_RDONLY, 0)) < 0) { 89357266Smuller syswarn(1, errno, "Unable to open %s to read", 89457266Smuller arcn->org_name); 89557266Smuller purg_lnk(arcn); 89657266Smuller continue; 89757266Smuller } 89857266Smuller if ((fddest = file_creat(arcn)) < 0) { 89957266Smuller rdfile_close(arcn, &fdsrc); 90057266Smuller purg_lnk(arcn); 90157266Smuller continue; 90257266Smuller } 90357266Smuller 90457266Smuller /* 90557266Smuller * copy source file data to the destination file 90657266Smuller */ 90757266Smuller cp_file(arcn, fdsrc, fddest); 90857266Smuller file_close(arcn, fddest); 90957266Smuller rdfile_close(arcn, &fdsrc); 91057266Smuller 91157266Smuller if (vflag && vfpart) { 91257266Smuller (void)putc('\n', stderr); 91357266Smuller vfpart = 0; 91457266Smuller } 91557266Smuller } 91657266Smuller 91757266Smuller /* 91857266Smuller * restore directory modes and times as required; make sure all 91957266Smuller * patterns were selected block off signals to avoid chance for 92057266Smuller * multiple entry into the cleanup code. 92157266Smuller */ 92257266Smuller (void)sigprocmask(SIG_BLOCK, &s_mask, (sigset_t *)NULL); 92357266Smuller ar_close(); 92457266Smuller proc_dir(); 92557266Smuller ftree_chk(); 92657266Smuller } 92757266Smuller 92857266Smuller /* 92957266Smuller * next_head() 93057266Smuller * try to find a valid header in the archive. Uses format specific 93157266Smuller * routines to extract the header and id the trailer. Trailers may be 93257266Smuller * located within a valid header or in an invalid header (the location 93357266Smuller * is format specific. The inhead field from the option table tells us 93457266Smuller * where to look for the trailer). 93557266Smuller * We keep reading (and resyncing) until we get enough contiguous data 93657266Smuller * to check for a header. If we cannot find one, we shift by a byte 93757266Smuller * add a new byte from the archive to the end of the buffer and try again. 93857266Smuller * If we get a read error, we throw out what we have (as we must have 93957266Smuller * contiguous data) and start over again. 94057266Smuller * ASSUMED: headers fit within a BLKMULT header. 94157266Smuller * Return: 94257266Smuller * 0 if we got a header, -1 if we are unable to ever find another one 94357266Smuller * (we reached the end of input, or we reached the limit on retries. see 94457266Smuller * the specs for rd_wrbuf() for more details) 94557266Smuller */ 94657266Smuller 94757266Smuller #if __STDC__ 94857266Smuller static int 94957266Smuller next_head(register ARCHD *arcn) 95057266Smuller #else 95157266Smuller static int 95257266Smuller next_head(arcn) 95357266Smuller register ARCHD *arcn; 95457266Smuller #endif 95557266Smuller { 95657266Smuller register int ret; 95757266Smuller register char *hdend; 95857266Smuller register int res; 95957266Smuller register int shftsz; 96057266Smuller register int hsz; 96157266Smuller register int in_resync = 0; /* set when we are in resync mode */ 96257266Smuller int cnt = 0; /* counter for trailer function */ 96357266Smuller 96457266Smuller /* 96557266Smuller * set up initial conditions, we want a whole frmt->hsz block as we 96657266Smuller * have no data yet. 96757266Smuller */ 96857266Smuller res = hsz = frmt->hsz; 96957266Smuller hdend = hdbuf; 97057266Smuller shftsz = hsz - 1; 97157266Smuller for(;;) { 97257266Smuller /* 97357266Smuller * keep looping until we get a contiguous FULL buffer 97457266Smuller * (frmt->hsz is the proper size) 97557266Smuller */ 97657266Smuller for (;;) { 97757266Smuller if ((ret = rd_wrbuf(hdend, res)) == res) 97857266Smuller break; 97957266Smuller 98057266Smuller /* 98157266Smuller * some kind of archive read problem, try to resync the 98257266Smuller * storage device, better give the user the bad news. 98357266Smuller */ 98457266Smuller if ((ret == 0) || (rd_sync() < 0)) { 98557266Smuller warn(1,"Premature end of file on archive read"); 98657266Smuller return(-1); 98757266Smuller } 98857266Smuller if (!in_resync) { 98957266Smuller if (act == APPND) { 99057266Smuller warn(1, 99157266Smuller "Archive I/O error, cannot continue"); 99257266Smuller return(-1); 99357266Smuller } 99457266Smuller warn(1,"Archive I/O error. Trying to recover."); 99557266Smuller ++in_resync; 99657266Smuller } 99757266Smuller 99857266Smuller /* 99957266Smuller * oh well, throw it all out and start over 100057266Smuller */ 100157266Smuller res = hsz; 100257266Smuller hdend = hdbuf; 100357266Smuller } 100457266Smuller 100557266Smuller /* 100657266Smuller * ok we have a contiguous buffer of the right size. Call the 100757266Smuller * format read routine. If this was not a valid header and this 100857266Smuller * format stores trailers outside of the header, call the 100957266Smuller * format specific trailer routine to check for a trailer. We 101057266Smuller * have to watch out that we do not mis-identify file data or 101157266Smuller * block padding as a header or trailer. Format specific 101257266Smuller * trailer functions must NOT check for the trailer while we 101357266Smuller * are running in resync mode. Some trailer functions may tell 101457266Smuller * us that this block cannot contain a valid header either, so 101557266Smuller * we then throw out the entire block and start over. 101657266Smuller */ 101757266Smuller if ((*frmt->rd)(arcn, hdbuf) == 0) 101857266Smuller break; 101957266Smuller 102057266Smuller if (!frmt->inhead) { 102157266Smuller /* 102257266Smuller * this format has trailers outside of valid headers 102357266Smuller */ 1024*58652Smuller if ((ret = (*frmt->trail)(hdbuf,in_resync,&cnt)) == 0){ 1025*58652Smuller /* 1026*58652Smuller * valid trailer found, drain input as required 1027*58652Smuller */ 1028*58652Smuller ar_drain(); 102957266Smuller return(-1); 1030*58652Smuller } 1031*58652Smuller 103257266Smuller if (ret == 1) { 103357266Smuller /* 103457266Smuller * we are in resync and we were told to throw 103557266Smuller * the whole block out because none of the 103657266Smuller * bytes in this block can be used to form a 103757266Smuller * valid header 103857266Smuller */ 103957266Smuller res = hsz; 104057266Smuller hdend = hdbuf; 104157266Smuller continue; 104257266Smuller } 104357266Smuller } 104457266Smuller 104557266Smuller /* 104657266Smuller * Brute force section. 104757266Smuller * not a valid header. We may be able to find a header yet. So 104857266Smuller * we shift over by one byte, and set up to read one byte at a 104957266Smuller * time from the archive and place it at the end of the buffer. 105057266Smuller * We will keep moving byte at a time until we find a header or 105157266Smuller * get a read error and have to start over. 105257266Smuller */ 105357266Smuller if (!in_resync) { 105457266Smuller if (act == APPND) { 105557266Smuller warn(1,"Unable to append, archive header flaw"); 105657266Smuller return(-1); 105757266Smuller } 105857266Smuller warn(1,"Invalid header, starting valid header search."); 105957266Smuller ++in_resync; 106057266Smuller } 106157266Smuller bcopy(hdbuf+1, hdbuf, shftsz); 106257266Smuller res = 1; 106357266Smuller hdend = hdbuf + shftsz; 106457266Smuller } 106557266Smuller 106657266Smuller /* 106757266Smuller * ok got a valid header, check for trailer if format encodes it in the 106857266Smuller * the header. NOTE: the parameters are different than trailer routines 106957266Smuller * which encode trailers outside of the header! 107057266Smuller */ 1071*58652Smuller if (frmt->inhead && ((*frmt->trail)(arcn) == 0)) { 1072*58652Smuller /* 1073*58652Smuller * valid trailer found, drain input as required 1074*58652Smuller */ 1075*58652Smuller ar_drain(); 107657266Smuller return(-1); 1077*58652Smuller } 1078*58652Smuller 107957266Smuller ++flcnt; 108057266Smuller return(0); 108157266Smuller } 108257266Smuller 108357266Smuller /* 108457266Smuller * get_arc() 108557266Smuller * Figure out what format an archive is. Handles archive with flaws by 108657266Smuller * brute force searches for a legal header in any supported format. The 108757266Smuller * format id routines have to be careful to NOT mis-identify a format. 108857266Smuller * ASSUMED: headers fit within a BLKMULT header. 108957266Smuller * Return: 109057266Smuller * 0 if archive found -1 otherwise 109157266Smuller */ 109257266Smuller 109357266Smuller #if __STDC__ 109457266Smuller static int 109557266Smuller get_arc(void) 109657266Smuller #else 109757266Smuller static int 109857266Smuller get_arc() 109957266Smuller #endif 110057266Smuller { 110157266Smuller register int i; 110257266Smuller register int hdsz = 0; 110357266Smuller register int res; 110457266Smuller register int minhd = BLKMULT; 110557266Smuller char *hdend; 110657266Smuller int notice = 0; 110757266Smuller 110857266Smuller /* 110957266Smuller * find the smallest header size in all archive formats and then set up 111057266Smuller * to read the archive. 111157266Smuller */ 111257266Smuller for (i = 0; ford[i] >= 0; ++i) { 111357266Smuller if (fsub[ford[i]].hsz < minhd) 111457266Smuller minhd = fsub[ford[i]].hsz; 111557266Smuller } 111657266Smuller if (rd_start() < 0) 111757266Smuller return(-1); 111857266Smuller res = BLKMULT; 111957266Smuller hdsz = 0; 112057266Smuller hdend = hdbuf; 112157266Smuller for(;;) { 112257266Smuller for (;;) { 112357266Smuller /* 112457266Smuller * fill the buffer with at least the smallest header 112557266Smuller */ 112657266Smuller i = rd_wrbuf(hdend, res); 112757266Smuller if (i > 0) 112857266Smuller hdsz += i; 112957266Smuller if (hdsz >= minhd) 113057266Smuller break; 113157266Smuller 113257266Smuller /* 113357266Smuller * if we cannot recover from a read error quit 113457266Smuller */ 113557266Smuller if ((i == 0) || (rd_sync() < 0)) 113657266Smuller goto out; 113757266Smuller 113857266Smuller /* 113957266Smuller * when we get an error none of the data we already 114057266Smuller * have can be used to create a legal header (we just 114157266Smuller * got an error in the middle), so we throw it all out 114257266Smuller * and refill the buffer with fresh data. 114357266Smuller */ 114457266Smuller res = BLKMULT; 114557266Smuller hdsz = 0; 114657266Smuller hdend = hdbuf; 114757266Smuller if (!notice) { 114857266Smuller if (act == APPND) 114957266Smuller return(-1); 115057266Smuller warn(1,"Cannot identify format. Searching..."); 115157266Smuller ++notice; 115257266Smuller } 115357266Smuller } 115457266Smuller 115557266Smuller /* 115657266Smuller * we have at least the size of the smallest header in any 115757266Smuller * archive format. Look to see if we have a match. The array 115857266Smuller * ford[] is used to specify the header id order to reduce the 115957266Smuller * chance of incorrectly id'ing a valid header (some formats 116057266Smuller * may be subsets of each other and the order would then be 116157266Smuller * important). 116257266Smuller */ 116357266Smuller for (i = 0; ford[i] >= 0; ++i) { 116457266Smuller if ((*fsub[ford[i]].id)(hdbuf, hdsz) < 0) 116557266Smuller continue; 116657266Smuller frmt = &(fsub[ford[i]]); 116757266Smuller /* 116857266Smuller * yuck, to avoid slow special case code in the extract 116957266Smuller * routines, just push this header back as if it was 117057266Smuller * not seen. We have left extra space at start of the 117157266Smuller * buffer for this purpose. This is a bit ugly, but 117257266Smuller * adding all the special case code is far worse. 117357266Smuller */ 117457266Smuller pback(hdbuf, hdsz); 117557266Smuller return(0); 117657266Smuller } 117757266Smuller 117857266Smuller /* 117957266Smuller * We have a flawed archive, no match. we start searching, but 118057266Smuller * we never allow additions to flawed archives 118157266Smuller */ 118257266Smuller if (!notice) { 118357266Smuller if (act == APPND) 118457266Smuller return(-1); 118557266Smuller warn(1, "Cannot identify format. Searching..."); 118657266Smuller ++notice; 118757266Smuller } 118857266Smuller 118957266Smuller /* 119057266Smuller * brute force search for a header that we can id. 119157266Smuller * we shift through byte at a time. this is slow, but we cannot 119257266Smuller * determine the nature of the flaw in the archive in a 119357266Smuller * portable manner 119457266Smuller */ 119557266Smuller if (--hdsz > 0) { 119657266Smuller bcopy(hdbuf+1, hdbuf, hdsz); 119757266Smuller res = BLKMULT - hdsz; 119857266Smuller hdend = hdbuf + hdsz; 119957266Smuller } else { 120057266Smuller res = BLKMULT; 120157266Smuller hdend = hdbuf; 120257266Smuller hdsz = 0; 120357266Smuller } 120457266Smuller } 120557266Smuller 120657266Smuller out: 120757266Smuller /* 120857266Smuller * we cannot find a header, bow, apologize and quit 120957266Smuller */ 121057266Smuller warn(1, "Sorry, unable to determine archive format."); 121157266Smuller return(-1); 121257266Smuller } 1213