ar_subs.c revision 76019
11553Srgrimes/*- 21553Srgrimes * Copyright (c) 1992 Keith Muller. 31553Srgrimes * Copyright (c) 1992, 1993 41553Srgrimes * The Regents of the University of California. All rights reserved. 51553Srgrimes * 61553Srgrimes * This code is derived from software contributed to Berkeley by 71553Srgrimes * Keith Muller of the University of California, San Diego. 81553Srgrimes * 91553Srgrimes * Redistribution and use in source and binary forms, with or without 101553Srgrimes * modification, are permitted provided that the following conditions 111553Srgrimes * are met: 121553Srgrimes * 1. Redistributions of source code must retain the above copyright 131553Srgrimes * notice, this list of conditions and the following disclaimer. 141553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151553Srgrimes * notice, this list of conditions and the following disclaimer in the 161553Srgrimes * documentation and/or other materials provided with the distribution. 171553Srgrimes * 3. All advertising materials mentioning features or use of this software 181553Srgrimes * must display the following acknowledgement: 191553Srgrimes * This product includes software developed by the University of 201553Srgrimes * California, Berkeley and its contributors. 211553Srgrimes * 4. Neither the name of the University nor the names of its contributors 221553Srgrimes * may be used to endorse or promote products derived from this software 231553Srgrimes * without specific prior written permission. 241553Srgrimes * 251553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3529451Scharnier * SUCH DAMAGE. 361553Srgrimes */ 3729451Scharnier 3829451Scharnier#ifndef lint 3950479Speter#if 0 401553Srgrimesstatic char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94"; 411553Srgrimes#endif 421553Srgrimesstatic const char rcsid[] = 431553Srgrimes "$FreeBSD: head/bin/pax/ar_subs.c 76019 2001-04-26 09:22:28Z kris $"; 441553Srgrimes#endif /* not lint */ 451553Srgrimes 461553Srgrimes#include <sys/types.h> 471553Srgrimes#include <sys/time.h> 4829451Scharnier#include <sys/stat.h> 4929451Scharnier#include <signal.h> 501553Srgrimes#include <string.h> 5120458Sjoerg#include <stdio.h> 5269004Simp#include <fcntl.h> 5316073Sphk#include <errno.h> 541553Srgrimes#include <unistd.h> 5530638Speter#include <stdlib.h> 561553Srgrimes#include "pax.h" 571553Srgrimes#include "extern.h" 5861640Speter 591553Srgrimesstatic void wr_archive __P((register ARCHD *, int is_app)); 601553Srgrimesstatic int get_arc __P((void)); 611553Srgrimesstatic int next_head __P((register ARCHD *)); 621553Srgrimesextern sigset_t s_mask; 631553Srgrimes 641553Srgrimes/* 6561640Speter * Routines which control the overall operation modes of pax as specified by 661553Srgrimes * the user: list, append, read ... 671553Srgrimes */ 681553Srgrimes 691553Srgrimesstatic char hdbuf[BLKMULT]; /* space for archive header on read */ 701553Srgrimesu_long flcnt; /* number of files processed */ 711553Srgrimes 7245744Speter/* 731553Srgrimes * list() 7461640Speter * list the contents of an archive which match user supplied pattern(s) 7561640Speter * (no pattern matches all). 7661640Speter */ 7769135Speter 7861640Speter#ifdef __STDC__ 7961640Spetervoid 8072684Speterlist(void) 8161640Speter#else 8229451Scharniervoid 831553Srgrimeslist() 841553Srgrimes#endif 851553Srgrimes{ 8645744Speter register ARCHD *arcn; 8761640Speter register int res; 881553Srgrimes ARCHD archd; 8961640Speter time_t now; 901553Srgrimes 911553Srgrimes arcn = &archd; 921553Srgrimes /* 931553Srgrimes * figure out archive type; pass any format specific options to the 941553Srgrimes * archive option processing routine; call the format init routine. We 951553Srgrimes * also save current time for ls_list() so we do not make a system 961553Srgrimes * call for each file we need to print. If verbose (vflag) start up 971553Srgrimes * the name and group caches. 981553Srgrimes */ 991553Srgrimes if ((get_arc() < 0) || ((*frmt->options)() < 0) || 1001553Srgrimes ((*frmt->st_rd)() < 0)) 10145744Speter return; 10261640Speter 1031553Srgrimes if (vflag && ((uidtb_start() < 0) || (gidtb_start() < 0))) 10461640Speter return; 1051553Srgrimes 1061553Srgrimes now = time(NULL); 1071553Srgrimes 1081553Srgrimes /* 1091553Srgrimes * step through the archive until the format says it is done 1101553Srgrimes */ 1111553Srgrimes while (next_head(arcn) == 0) { 1121553Srgrimes /* 1131553Srgrimes * check for pattern, and user specified options match. 1141553Srgrimes * When all patterns are matched we are done. 1151553Srgrimes */ 1161553Srgrimes if ((res = pat_match(arcn)) < 0) 1171553Srgrimes break; 1181553Srgrimes 11929451Scharnier if ((res == 0) && (sel_chk(arcn) == 0)) { 12061640Speter /* 1211553Srgrimes * pattern resulted in a selected file 1221553Srgrimes */ 1231553Srgrimes if (pat_sel(arcn) < 0) 1241553Srgrimes break; 12530638Speter 12661640Speter /* 1271553Srgrimes * modify the name as requested by the user if name 1281553Srgrimes * survives modification, do a listing of the file 12955614Speter */ 1301553Srgrimes if ((res = mod_name(arcn)) < 0) 13155614Speter break; 13255614Speter if (res == 0) 13355614Speter ls_list(arcn, now); 13455614Speter } 13529451Scharnier 13629451Scharnier /* 13713400Speter * skip to next archive format header using values calculated 13829451Scharnier * by the format header read routine 13929451Scharnier */ 14045744Speter if (rd_skip(arcn->skip + arcn->pad) == 1) 14111711Sdg break; 14220395Sbde } 1431553Srgrimes 14412772Speter /* 1451553Srgrimes * all done, let format have a chance to cleanup, and make sure that 1461553Srgrimes * the patterns supplied by the user were all matched 1471553Srgrimes */ 1481553Srgrimes (void)(*frmt->end_rd)(); 1491553Srgrimes (void)sigprocmask(SIG_BLOCK, &s_mask, NULL); 1501553Srgrimes ar_close(); 1511553Srgrimes pat_chk(); 1521553Srgrimes} 1531553Srgrimes 15420395Sbde/* 1551553Srgrimes * extract() 15620395Sbde * extract the member(s) of an archive as specified by user supplied 15720395Sbde * pattern(s) (no patterns extracts all members) 15852653Smarcel */ 15952653Smarcel 1601553Srgrimes#ifdef __STDC__ 1611553Srgrimesvoid 1621553Srgrimesextract(void) 1631553Srgrimes#else 1641553Srgrimesvoid 1655325Sgibbsextract() 1665325Sgibbs#endif 1675325Sgibbs{ 1681553Srgrimes register ARCHD *arcn; 16969135Speter register int res; 17069135Speter off_t cnt; 1711553Srgrimes ARCHD archd; 1721553Srgrimes struct stat sb; 1736803Sgibbs int fd; 1746803Sgibbs 17530638Speter arcn = &archd; 17630638Speter /* 17730638Speter * figure out archive type; pass any format specific options to the 17871363Speter * archive option processing routine; call the format init routine; 17930638Speter * start up the directory modification time and access mode database 18037129Sjkh */ 18137129Sjkh if ((get_arc() < 0) || ((*frmt->options)() < 0) || 18237129Sjkh ((*frmt->st_rd)() < 0) || (dir_start() < 0)) 18337129Sjkh return; 18439307Sgibbs 18539307Sgibbs /* 18639307Sgibbs * When we are doing interactive rename, we store the mapping of names 18739307Sgibbs * so we can fix up hard links files later in the archive. 18871363Speter */ 18930638Speter if (iflag && (name_start() < 0)) 19030638Speter return; 1911553Srgrimes 1921553Srgrimes /* 1931553Srgrimes * step through each entry on the archive until the format read routine 1941553Srgrimes * says it is done 1951553Srgrimes */ 1961553Srgrimes while (next_head(arcn) == 0) { 19713400Speter 19834619Seivind /* 19961640Speter * check for pattern, and user specified options match. When 20061640Speter * all the patterns are matched we are done 20161640Speter */ 20261640Speter if ((res = pat_match(arcn)) < 0) 20361640Speter break; 20461640Speter 20561640Speter if ((res > 0) || (sel_chk(arcn) != 0)) { 20661640Speter /* 20761640Speter * file is not selected. skip past any file data and 20861640Speter * padding and go back for the next archive member 20965091Speter */ 21061640Speter (void)rd_skip(arcn->skip + arcn->pad); 21161640Speter continue; 21261640Speter } 21361640Speter 21461640Speter /* 21561640Speter * with -u or -D only extract when the archive member is newer 21661640Speter * than the file with the same name in the file system (nos 21761640Speter * test of being the same type is required). 21861640Speter * NOTE: this test is done BEFORE name modifications as 21961640Speter * specified by pax. this operation can be confusing to the 22061640Speter * user who might expect the test to be done on an existing 22161640Speter * file AFTER the name mod. In honesty the pax spec is probably 22261640Speter * flawed in this respect. 22361640Speter */ 22461640Speter if ((uflag || Dflag) && ((lstat(arcn->name, &sb) == 0))) { 22561640Speter if (uflag && Dflag) { 22661640Speter if ((arcn->sb.st_mtime <= sb.st_mtime) && 22761640Speter (arcn->sb.st_ctime <= sb.st_ctime)) { 22861640Speter (void)rd_skip(arcn->skip + arcn->pad); 22961640Speter continue; 23061640Speter } 23161640Speter } else if (Dflag) { 23261640Speter if (arcn->sb.st_ctime <= sb.st_ctime) { 23361640Speter (void)rd_skip(arcn->skip + arcn->pad); 23461640Speter continue; 23561640Speter } 23661640Speter } else if (arcn->sb.st_mtime <= sb.st_mtime) { 23761640Speter (void)rd_skip(arcn->skip + arcn->pad); 23861652Speter continue; 23961640Speter } 24061640Speter } 24161640Speter 24261640Speter /* 24361640Speter * this archive member is now been selected. modify the name. 24461640Speter */ 24561640Speter if ((pat_sel(arcn) < 0) || ((res = mod_name(arcn)) < 0)) 24661640Speter break; 24782393Speter if (res > 0) { 24882393Speter /* 24982393Speter * a bad name mod, skip and purge name from link table 25082393Speter */ 25182393Speter purg_lnk(arcn); 25282393Speter (void)rd_skip(arcn->skip + arcn->pad); 25382393Speter continue; 25482393Speter } 25582393Speter 25682393Speter /* 25782393Speter * Non standard -Y and -Z flag. When the existing file is 25882393Speter * same age or newer skip 25982393Speter */ 26082393Speter if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) { 26182393Speter if (Yflag && Zflag) { 26282393Speter if ((arcn->sb.st_mtime <= sb.st_mtime) && 26382393Speter (arcn->sb.st_ctime <= sb.st_ctime)) { 26482393Speter (void)rd_skip(arcn->skip + arcn->pad); 26582393Speter continue; 26682393Speter } 26782393Speter } else if (Yflag) { 26882393Speter if (arcn->sb.st_ctime <= sb.st_ctime) { 26982393Speter (void)rd_skip(arcn->skip + arcn->pad); 27082393Speter continue; 27182393Speter } 27282393Speter } else if (arcn->sb.st_mtime <= sb.st_mtime) { 27382393Speter (void)rd_skip(arcn->skip + arcn->pad); 27482393Speter continue; 27582393Speter } 27682393Speter } 27782393Speter 27882393Speter if (vflag) { 27982393Speter (void)fputs(arcn->name, stderr); 28082393Speter vfpart = 1; 28182393Speter } 28282393Speter 28382393Speter /* 28482393Speter * all ok, extract this member based on type 28582393Speter */ 28682393Speter if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) { 28782393Speter /* 28882393Speter * process archive members that are not regular files. 28982393Speter * throw out padding and any data that might follow the 29082393Speter * header (as determined by the format). 29182393Speter */ 29282393Speter if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) 29382393Speter res = lnk_creat(arcn); 29482393Speter else 29582393Speter res = node_creat(arcn); 2961553Srgrimes 2971553Srgrimes (void)rd_skip(arcn->skip + arcn->pad); 2981553Srgrimes if (res < 0) 2991553Srgrimes purg_lnk(arcn); 3001553Srgrimes 3011553Srgrimes if (vflag && vfpart) { 30245744Speter (void)putc('\n', stderr); 30361640Speter vfpart = 0; 3041553Srgrimes } 3051553Srgrimes continue; 30661640Speter } 30761640Speter /* 30861640Speter * we have a file with data here. If we can not create it, skip 30973199Speter * over the data and purge the name from hard link table 31069004Simp */ 31173204Speter if ((fd = file_creat(arcn)) < 0) { 31261523Speter (void)rd_skip(arcn->skip + arcn->pad); 3131553Srgrimes purg_lnk(arcn); 3141553Srgrimes continue; 31555614Speter } 31655614Speter /* 31755614Speter * extract the file from the archive and skip over padding and 31855614Speter * any unprocessed data 31969004Simp */ 3201553Srgrimes res = (*frmt->rd_data)(arcn, fd, &cnt); 3211553Srgrimes file_close(arcn, fd); 32229451Scharnier if (vflag && vfpart) { 32329451Scharnier (void)putc('\n', stderr); 3241553Srgrimes vfpart = 0; 3251553Srgrimes } 32661640Speter if (!res) 32748525Speter (void)rd_skip(cnt + arcn->pad); 3288857Srgrimes } 3296803Sgibbs 33054490Speter /* 3311553Srgrimes * all done, restore directory modes and times as required; make sure 3321553Srgrimes * all patterns supplied by the user were matched; block off signals 3331553Srgrimes * to avoid chance for multiple entry into the cleanup code. 3341553Srgrimes */ 3351553Srgrimes (void)(*frmt->end_rd)(); 33655614Speter (void)sigprocmask(SIG_BLOCK, &s_mask, NULL); 33769004Simp ar_close(); 33869004Simp proc_dir(); 33955614Speter pat_chk(); 34055614Speter} 34155614Speter 34269004Simp/* 34369004Simp * wr_archive() 3441553Srgrimes * Write an archive. used in both creating a new archive and appends on 3451553Srgrimes * previously written archive. 3461553Srgrimes */ 3471553Srgrimes 3481553Srgrimes#ifdef __STDC__ 3491553Srgrimesstatic void 35052098Speterwr_archive(register ARCHD *arcn, int is_app) 3511566Srgrimes#else 35252098Speterstatic void 35352098Speterwr_archive(arcn, is_app) 3541566Srgrimes register ARCHD *arcn; 3551566Srgrimes int is_app; 3561553Srgrimes#endif 3571553Srgrimes{ 3581553Srgrimes register int res; 3591553Srgrimes register int hlk; 3601553Srgrimes register int wr_one; 3611553Srgrimes off_t cnt; 3621553Srgrimes int (*wrf)(); 3631553Srgrimes int fd = -1; 36461523Speter 3651553Srgrimes /* 3661553Srgrimes * if this format supports hard link storage, start up the database 3671553Srgrimes * that detects them. 3681553Srgrimes */ 36973199Speter if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0)) 3704571Sgibbs return; 3716803Sgibbs 37272684Speter /* 3731553Srgrimes * start up the file traversal code and format specific write 37430796Sjoerg */ 3754571Sgibbs if ((ftree_start() < 0) || ((*frmt->st_wr)() < 0)) 3764571Sgibbs return; 37761523Speter wrf = frmt->wr; 3785325Sgibbs 3791553Srgrimes /* 38061523Speter * When we are doing interactive rename, we store the mapping of names 3811553Srgrimes * so we can fix up hard links files later in the archive. 38230796Sjoerg */ 38330796Sjoerg if (iflag && (name_start() < 0)) 38430796Sjoerg return; 38530796Sjoerg 38630796Sjoerg /* 38761523Speter * if this not append, and there are no files, we do no write a trailer 38830796Sjoerg */ 38961523Speter wr_one = is_app; 39061523Speter 39161523Speter /* 39261523Speter * while there are files to archive, process them one at at time 39330796Sjoerg */ 3941553Srgrimes while (next_file(arcn) == 0) { 3951553Srgrimes /* 3961553Srgrimes * check if this file meets user specified options match. 3971553Srgrimes */ 3981553Srgrimes if (sel_chk(arcn) != 0) 3991553Srgrimes continue; 4004571Sgibbs fd = -1; 4014571Sgibbs if (uflag) { 4024571Sgibbs /* 4034571Sgibbs * only archive if this file is newer than a file with 4044571Sgibbs * the same name that is already stored on the archive 40573199Speter */ 4064571Sgibbs if ((res = chk_ftime(arcn)) < 0) 4074571Sgibbs break; 4084571Sgibbs if (res > 0) 4094571Sgibbs continue; 4104571Sgibbs } 4114571Sgibbs 4124571Sgibbs /* 4135325Sgibbs * this file is considered selected now. see if this is a hard 4145325Sgibbs * link to a file already stored 4155325Sgibbs */ 4165325Sgibbs ftree_sel(arcn); 4176803Sgibbs if (hlk && (chk_lnk(arcn) < 0)) 4184571Sgibbs break; 4194571Sgibbs 4204571Sgibbs if ((arcn->type == PAX_REG) || (arcn->type == PAX_HRG) || 4218520Srgrimes (arcn->type == PAX_CTG)) { 4224571Sgibbs /* 4234571Sgibbs * we will have to read this file. by opening it now we 4244571Sgibbs * can avoid writing a header to the archive for a file 4254571Sgibbs * we were later unable to read (we also purge it from 4264571Sgibbs * the link table). 4276803Sgibbs */ 4285325Sgibbs if ((fd = open(arcn->org_name, O_RDONLY, 0)) < 0) { 4295325Sgibbs syswarn(1,errno, "Unable to open %s to read", 4306803Sgibbs arcn->org_name); 4318520Srgrimes purg_lnk(arcn); 4325325Sgibbs continue; 4335325Sgibbs } 4346803Sgibbs } 4355325Sgibbs 4365325Sgibbs /* 4371553Srgrimes * Now modify the name as requested by the user 4381553Srgrimes */ 4391553Srgrimes if ((res = mod_name(arcn)) < 0) { 4401553Srgrimes /* 4418520Srgrimes * name modification says to skip this file, close the 4421553Srgrimes * file and purge link table entry 4431553Srgrimes */ 44473199Speter rdfile_close(arcn, &fd); 4451553Srgrimes purg_lnk(arcn); 4461553Srgrimes break; 44754490Speter } 44854490Speter 44954490Speter if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) { 45054490Speter /* 45154490Speter * unable to obtain the crc we need, close the file, 45254490Speter * purge link table entry 45354490Speter */ 45472684Speter rdfile_close(arcn, &fd); 45554490Speter purg_lnk(arcn); 45654490Speter continue; 4571553Srgrimes } 45838782Snsouch 45938782Snsouch if (vflag) { 46038782Snsouch (void)fputs(arcn->name, stderr); 46138782Snsouch vfpart = 1; 46238782Snsouch } 46338782Snsouch ++flcnt; 46438782Snsouch 46538782Snsouch /* 4661553Srgrimes * looks safe to store the file, have the format specific 4671553Srgrimes * routine write routine store the file header on the archive 4681553Srgrimes */ 4691553Srgrimes if ((res = (*wrf)(arcn)) < 0) { 4701553Srgrimes rdfile_close(arcn, &fd); 4711553Srgrimes break; 4721553Srgrimes } 4731553Srgrimes wr_one = 1; 47473193Speter if (res > 0) { 4751553Srgrimes /* 47671879Speter * format write says no file data needs to be stored 47752098Speter * so we are done messing with this file 4781553Srgrimes */ 4791553Srgrimes if (vflag && vfpart) { 48030796Sjoerg (void)putc('\n', stderr); 48130796Sjoerg vfpart = 0; 48230796Sjoerg } 48330796Sjoerg rdfile_close(arcn, &fd); 48430796Sjoerg continue; 4851553Srgrimes } 48673193Speter 48773193Speter /* 48873193Speter * Add file data to the archive, quit on write error. if we 4891553Srgrimes * cannot write the entire file contents to the archive we 4901553Srgrimes * must pad the archive to replace the missing file data 4911553Srgrimes * (otherwise during an extract the file header for the file 4921553Srgrimes * which FOLLOWS this one will not be where we expect it to 4931553Srgrimes * be). 4941553Srgrimes */ 4951553Srgrimes res = (*frmt->wr_data)(arcn, fd, &cnt); 4961553Srgrimes rdfile_close(arcn, &fd); 4971553Srgrimes if (vflag && vfpart) { 4981553Srgrimes (void)putc('\n', stderr); 4991553Srgrimes vfpart = 0; 5001553Srgrimes } 5011553Srgrimes if (res < 0) 5021553Srgrimes break; 5031553Srgrimes 5041553Srgrimes /* 5051553Srgrimes * pad as required, cnt is number of bytes not written 50661523Speter */ 50761523Speter if (((cnt > 0) && (wr_skip(cnt) < 0)) || 50861523Speter ((arcn->pad > 0) && (wr_skip(arcn->pad) < 0))) 50973199Speter break; 5104571Sgibbs } 5116803Sgibbs 51272684Speter /* 5131553Srgrimes * tell format to write trailer; pad to block boundary; reset directory 5141553Srgrimes * mode/access times, and check if all patterns supplied by the user 5151553Srgrimes * were matched. block off signals to avoid chance for multiple entry 5161553Srgrimes * into the cleanup code 5171553Srgrimes */ 5181553Srgrimes if (wr_one) { 5191553Srgrimes (*frmt->end_wr)(); 5201553Srgrimes wr_fin(); 5211553Srgrimes } 5221553Srgrimes (void)sigprocmask(SIG_BLOCK, &s_mask, NULL); 5231553Srgrimes ar_close(); 5241553Srgrimes if (tflag) 5251553Srgrimes proc_dir(); 5261553Srgrimes ftree_chk(); 5271553Srgrimes} 5281553Srgrimes 5291553Srgrimes/* 5301553Srgrimes * append() 5311553Srgrimes * Add file to previously written archive. Archive format specified by the 5321553Srgrimes * user must agree with archive. The archive is read first to collect 53361523Speter * modification times (if -u) and locate the archive trailer. The archive 5344571Sgibbs * is positioned in front of the record with the trailer and wr_archive() 5354571Sgibbs * is called to add the new members. 5364571Sgibbs * PAX IMPLEMENTATION DETAIL NOTE: 5374571Sgibbs * -u is implemented by adding the new members to the end of the archive. 5385325Sgibbs * Care is taken so that these do not end up as links to the older 5395325Sgibbs * version of the same file already stored in the archive. It is expected 54061523Speter * when extraction occurs these newer versions will over-write the older 54161523Speter * ones stored "earlier" in the archive (this may be a bad assumption as 5421553Srgrimes * it depends on the implementation of the program doing the extraction). 54373199Speter * It is really difficult to splice in members without either re-writing 5444571Sgibbs * the entire archive (from the point were the old version was), or having 5456803Sgibbs * assistance of the format specification in terms of a special update 54672684Speter * header that invalidates a previous archive record. The POSIX spec left 5471553Srgrimes * the method used to implement -u unspecified. This pax is able to 54861523Speter * over write existing files that it creates. 5491553Srgrimes */ 5501553Srgrimes 5511553Srgrimes#ifdef __STDC__ 55245744Spetervoid 55372684Speterappend(void) 5541553Srgrimes#else 5551553Srgrimesvoid 5561553Srgrimesappend() 5571553Srgrimes#endif 5581553Srgrimes{ 5591553Srgrimes register ARCHD *arcn; 5601553Srgrimes register int res; 5611553Srgrimes ARCHD archd; 5621553Srgrimes FSUB *orgfrmt; 5631553Srgrimes int udev; 5641553Srgrimes off_t tlen; 5651553Srgrimes 5661553Srgrimes arcn = &archd; 5671553Srgrimes orgfrmt = frmt; 5681553Srgrimes 56945744Speter /* 57061640Speter * Do not allow an append operation if the actual archive is of a 5715325Sgibbs * different format than the user specified format. 57261640Speter */ 57361640Speter if (get_arc() < 0) 5745325Sgibbs return; 5755325Sgibbs if ((orgfrmt != NULL) && (orgfrmt != frmt)) { 5765325Sgibbs paxwarn(1, "Cannot mix current archive format %s with %s", 5775325Sgibbs frmt->name, orgfrmt->name); 5785325Sgibbs return; 5795325Sgibbs } 5805325Sgibbs 5815325Sgibbs /* 5825325Sgibbs * pass the format any options and start up format 5835325Sgibbs */ 5845325Sgibbs if (((*frmt->options)() < 0) || ((*frmt->st_rd)() < 0)) 5855325Sgibbs return; 5865325Sgibbs 5875325Sgibbs /* 5885325Sgibbs * if we only are adding members that are newer, we need to save the 5895325Sgibbs * mod times for all files we see. 5905325Sgibbs */ 5915325Sgibbs if (uflag && (ftime_start() < 0)) 5925325Sgibbs return; 5935325Sgibbs 59445744Speter /* 59561640Speter * some archive formats encode hard links by recording the device and 5961553Srgrimes * file serial number (inode) but copy the file anyway (multiple times) 59761640Speter * to the archive. When we append, we run the risk that newly added 59861640Speter * files may have the same device and inode numbers as those recorded 59961640Speter * on the archive but during a previous run. If this happens, when the 6001553Srgrimes * archive is extracted we get INCORRECT hard links. We avoid this by 6011553Srgrimes * remapping the device numbers so that newly added files will never 6021553Srgrimes * use the same device number as one found on the archive. remapping 6031553Srgrimes * allows new members to safely have links among themselves. remapping 6044571Sgibbs * also avoids problems with file inode (serial number) truncations 6051553Srgrimes * when the inode number is larger than storage space in the archive 6061553Srgrimes * header. See the remap routines for more details. 6071553Srgrimes */ 6081553Srgrimes if ((udev = frmt->udev) && (dev_start() < 0)) 6091553Srgrimes return; 6101553Srgrimes 6111553Srgrimes /* 6121553Srgrimes * reading the archive may take a long time. If verbose tell the user 6131553Srgrimes */ 6141553Srgrimes if (vflag) { 6151553Srgrimes (void)fprintf(stderr, 6161553Srgrimes "%s: Reading archive to position at the end...", argv0); 6171553Srgrimes vfpart = 1; 6181553Srgrimes } 6191553Srgrimes 6201553Srgrimes /* 6211553Srgrimes * step through the archive until the format says it is done 62245744Speter */ 62369135Speter while (next_head(arcn) == 0) { 6241553Srgrimes /* 62561640Speter * check if this file meets user specified options. 62669135Speter */ 62769135Speter if (sel_chk(arcn) != 0) { 6281553Srgrimes if (rd_skip(arcn->skip + arcn->pad) == 1) 62969135Speter break; 63069135Speter continue; 63169135Speter } 63269135Speter 63369135Speter if (uflag) { 63469135Speter /* 63569135Speter * see if this is the newest version of this file has 63669135Speter * already been seen, if so skip. 63769135Speter */ 6381553Srgrimes if ((res = chk_ftime(arcn)) < 0) 6391553Srgrimes break; 64038782Snsouch if (res > 0) { 6411553Srgrimes if (rd_skip(arcn->skip + arcn->pad) == 1) 64269135Speter break; 6431553Srgrimes continue; 64469135Speter } 64569135Speter } 6461553Srgrimes 6471553Srgrimes /* 6481553Srgrimes * Store this device number. Device numbers seen during the 6491553Srgrimes * read phase of append will cause newly appended files with a 65038782Snsouch * device number seen in the old part of the archive to be 65138782Snsouch * remapped to an unused device number. 65238782Snsouch */ 65338782Snsouch if ((udev && (add_dev(arcn) < 0)) || 6541553Srgrimes (rd_skip(arcn->skip + arcn->pad) == 1)) 6551553Srgrimes break; 6561553Srgrimes } 6571553Srgrimes 6581553Srgrimes /* 6591553Srgrimes * done, finish up read and get the number of bytes to back up so we 66045744Speter * can add new members. The format might have used the hard link table, 66161640Speter * purge it. 6621553Srgrimes */ 66361640Speter tlen = (*frmt->end_rd)(); 6641553Srgrimes lnk_end(); 6651553Srgrimes 6661553Srgrimes /* 6671553Srgrimes * try to position for write, if this fails quit. if any error occurs, 6681553Srgrimes * we will refuse to write 6691553Srgrimes */ 6701553Srgrimes if (appnd_start(tlen) < 0) 6711553Srgrimes return; 6721553Srgrimes 6731553Srgrimes /* 6741553Srgrimes * tell the user we are done reading. 67545744Speter */ 67661640Speter if (vflag && vfpart) { 6771553Srgrimes (void)fputs("done.\n", stderr); 67861640Speter vfpart = 0; 67961640Speter } 68073199Speter 6811553Srgrimes /* 6821553Srgrimes * go to the writing phase to add the new members 6831553Srgrimes */ 6841553Srgrimes wr_archive(arcn, 1); 68554490Speter} 68654490Speter 6871553Srgrimes/* 6881553Srgrimes * archive() 6894571Sgibbs * write a new archive 6904571Sgibbs */ 69152098Speter 6924571Sgibbs#ifdef __STDC__ 69352098Spetervoid 6941553Srgrimesarchive(void) 6954571Sgibbs#else 6964571Sgibbsvoid 6974571Sgibbsarchive() 6988857Srgrimes#endif 6994571Sgibbs{ 7004571Sgibbs ARCHD archd; 7014571Sgibbs 7024571Sgibbs /* 7038857Srgrimes * if we only are adding members that are newer, we need to save the 7044571Sgibbs * mod times for all files; set up for writing; pass the format any 7054571Sgibbs * options write the archive 7068857Srgrimes */ 7074571Sgibbs if ((uflag && (ftime_start() < 0)) || (wr_start() < 0)) 7084571Sgibbs return; 7091553Srgrimes if ((*frmt->options)() < 0) 71073199Speter return; 71173199Speter 71272684Speter wr_archive(&archd, 0); 7131553Srgrimes} 7141553Srgrimes 7151553Srgrimes/* 7161553Srgrimes * copy() 7171553Srgrimes * copy files from one part of the file system to another. this does not 7181553Srgrimes * use any archive storage. The EFFECT OF THE COPY IS THE SAME as if an 7191553Srgrimes * archive was written and then extracted in the destination directory 7201553Srgrimes * (except the files are forced to be under the destination directory). 7211553Srgrimes */ 7221553Srgrimes 7231553Srgrimes#ifdef __STDC__ 7241553Srgrimesvoid 7251553Srgrimescopy(void) 7261553Srgrimes#else 7271553Srgrimesvoid 7281553Srgrimescopy() 7291553Srgrimes#endif 7301553Srgrimes{ 73173204Speter register ARCHD *arcn; 73273204Speter register int res; 73373199Speter register int fddest; 7341553Srgrimes register char *dest_pt; 7351553Srgrimes register int dlen; 73673199Speter register int drem; 7371553Srgrimes int fdsrc = -1; 7381553Srgrimes struct stat sb; 7391553Srgrimes ARCHD archd; 74045744Speter char dirbuf[PAXPATHLEN+1]; 74161640Speter 7426803Sgibbs arcn = &archd; 74361640Speter /* 74461640Speter * set up the destination dir path and make sure it is a directory. We 7456803Sgibbs * make sure we have a trailing / on the destination 7466803Sgibbs */ 7476803Sgibbs dlen = l_strncpy(dirbuf, dirptr, sizeof(dirbuf) - 1); 7486803Sgibbs dest_pt = dirbuf + dlen; 7496803Sgibbs if (*(dest_pt-1) != '/') { 7506803Sgibbs *dest_pt++ = '/'; 7516803Sgibbs ++dlen; 7526803Sgibbs } 7536803Sgibbs *dest_pt = '\0'; 7546803Sgibbs drem = PAXPATHLEN - dlen; 7556803Sgibbs 7566803Sgibbs if (stat(dirptr, &sb) < 0) { 7576803Sgibbs syswarn(1, errno, "Cannot access destination directory %s", 7586803Sgibbs dirptr); 7596803Sgibbs return; 7606803Sgibbs } 7616803Sgibbs if (!S_ISDIR(sb.st_mode)) { 7621553Srgrimes paxwarn(1, "Destination is not a directory %s", dirptr); 76361640Speter return; 7641553Srgrimes } 76561640Speter 7661553Srgrimes /* 7671553Srgrimes * start up the hard link table; file traversal routines and the 7681553Srgrimes * modification time and access mode database 7691553Srgrimes */ 7701553Srgrimes if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0)) 7711553Srgrimes return; 7721553Srgrimes 7731553Srgrimes /* 774 * When we are doing interactive rename, we store the mapping of names 775 * so we can fix up hard links files later in the archive. 776 */ 777 if (iflag && (name_start() < 0)) 778 return; 779 780 /* 781 * set up to cp file trees 782 */ 783 cp_start(); 784 785 /* 786 * while there are files to archive, process them 787 */ 788 while (next_file(arcn) == 0) { 789 fdsrc = -1; 790 791 /* 792 * check if this file meets user specified options 793 */ 794 if (sel_chk(arcn) != 0) 795 continue; 796 797 /* 798 * if there is already a file in the destination directory with 799 * the same name and it is newer, skip the one stored on the 800 * archive. 801 * NOTE: this test is done BEFORE name modifications as 802 * specified by pax. this can be confusing to the user who 803 * might expect the test to be done on an existing file AFTER 804 * the name mod. In honesty the pax spec is probably flawed in 805 * this respect 806 */ 807 if (uflag || Dflag) { 808 /* 809 * create the destination name 810 */ 811 if (*(arcn->name) == '/') 812 res = 1; 813 else 814 res = 0; 815 if ((arcn->nlen - res) > drem) { 816 paxwarn(1, "Destination pathname too long %s", 817 arcn->name); 818 continue; 819 } 820 (void)strncpy(dest_pt, arcn->name + res, drem); 821 dirbuf[PAXPATHLEN] = '\0'; 822 823 /* 824 * if existing file is same age or newer skip 825 */ 826 res = lstat(dirbuf, &sb); 827 *dest_pt = '\0'; 828 829 if (res == 0) { 830 if (uflag && Dflag) { 831 if ((arcn->sb.st_mtime<=sb.st_mtime) && 832 (arcn->sb.st_ctime<=sb.st_ctime)) 833 continue; 834 } else if (Dflag) { 835 if (arcn->sb.st_ctime <= sb.st_ctime) 836 continue; 837 } else if (arcn->sb.st_mtime <= sb.st_mtime) 838 continue; 839 } 840 } 841 842 /* 843 * this file is considered selected. See if this is a hard link 844 * to a previous file; modify the name as requested by the 845 * user; set the final destination. 846 */ 847 ftree_sel(arcn); 848 if ((chk_lnk(arcn) < 0) || ((res = mod_name(arcn)) < 0)) 849 break; 850 if ((res > 0) || (set_dest(arcn, dirbuf, dlen) < 0)) { 851 /* 852 * skip file, purge from link table 853 */ 854 purg_lnk(arcn); 855 continue; 856 } 857 858 /* 859 * Non standard -Y and -Z flag. When the exisiting file is 860 * same age or newer skip 861 */ 862 if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) { 863 if (Yflag && Zflag) { 864 if ((arcn->sb.st_mtime <= sb.st_mtime) && 865 (arcn->sb.st_ctime <= sb.st_ctime)) 866 continue; 867 } else if (Yflag) { 868 if (arcn->sb.st_ctime <= sb.st_ctime) 869 continue; 870 } else if (arcn->sb.st_mtime <= sb.st_mtime) 871 continue; 872 } 873 874 if (vflag) { 875 (void)fputs(arcn->name, stderr); 876 vfpart = 1; 877 } 878 ++flcnt; 879 880 /* 881 * try to create a hard link to the src file if requested 882 * but make sure we are not trying to overwrite ourselves. 883 */ 884 if (lflag) 885 res = cross_lnk(arcn); 886 else 887 res = chk_same(arcn); 888 if (res <= 0) { 889 if (vflag && vfpart) { 890 (void)putc('\n', stderr); 891 vfpart = 0; 892 } 893 continue; 894 } 895 896 /* 897 * have to create a new file 898 */ 899 if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) { 900 /* 901 * create a link or special file 902 */ 903 if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) 904 res = lnk_creat(arcn); 905 else 906 res = node_creat(arcn); 907 if (res < 0) 908 purg_lnk(arcn); 909 if (vflag && vfpart) { 910 (void)putc('\n', stderr); 911 vfpart = 0; 912 } 913 continue; 914 } 915 916 /* 917 * have to copy a regular file to the destination directory. 918 * first open source file and then create the destination file 919 */ 920 if ((fdsrc = open(arcn->org_name, O_RDONLY, 0)) < 0) { 921 syswarn(1, errno, "Unable to open %s to read", 922 arcn->org_name); 923 purg_lnk(arcn); 924 continue; 925 } 926 if ((fddest = file_creat(arcn)) < 0) { 927 rdfile_close(arcn, &fdsrc); 928 purg_lnk(arcn); 929 continue; 930 } 931 932 /* 933 * copy source file data to the destination file 934 */ 935 cp_file(arcn, fdsrc, fddest); 936 file_close(arcn, fddest); 937 rdfile_close(arcn, &fdsrc); 938 939 if (vflag && vfpart) { 940 (void)putc('\n', stderr); 941 vfpart = 0; 942 } 943 } 944 945 /* 946 * restore directory modes and times as required; make sure all 947 * patterns were selected block off signals to avoid chance for 948 * multiple entry into the cleanup code. 949 */ 950 (void)sigprocmask(SIG_BLOCK, &s_mask, NULL); 951 ar_close(); 952 proc_dir(); 953 ftree_chk(); 954} 955 956/* 957 * next_head() 958 * try to find a valid header in the archive. Uses format specific 959 * routines to extract the header and id the trailer. Trailers may be 960 * located within a valid header or in an invalid header (the location 961 * is format specific. The inhead field from the option table tells us 962 * where to look for the trailer). 963 * We keep reading (and resyncing) until we get enough contiguous data 964 * to check for a header. If we cannot find one, we shift by a byte 965 * add a new byte from the archive to the end of the buffer and try again. 966 * If we get a read error, we throw out what we have (as we must have 967 * contiguous data) and start over again. 968 * ASSUMED: headers fit within a BLKMULT header. 969 * Return: 970 * 0 if we got a header, -1 if we are unable to ever find another one 971 * (we reached the end of input, or we reached the limit on retries. see 972 * the specs for rd_wrbuf() for more details) 973 */ 974 975#ifdef __STDC__ 976static int 977next_head(register ARCHD *arcn) 978#else 979static int 980next_head(arcn) 981 register ARCHD *arcn; 982#endif 983{ 984 register int ret; 985 register char *hdend; 986 register int res; 987 register int shftsz; 988 register int hsz; 989 register int in_resync = 0; /* set when we are in resync mode */ 990 int cnt = 0; /* counter for trailer function */ 991 992 /* 993 * set up initial conditions, we want a whole frmt->hsz block as we 994 * have no data yet. 995 */ 996 res = hsz = frmt->hsz; 997 hdend = hdbuf; 998 shftsz = hsz - 1; 999 for(;;) { 1000 /* 1001 * keep looping until we get a contiguous FULL buffer 1002 * (frmt->hsz is the proper size) 1003 */ 1004 for (;;) { 1005 if ((ret = rd_wrbuf(hdend, res)) == res) 1006 break; 1007 1008 /* 1009 * some kind of archive read problem, try to resync the 1010 * storage device, better give the user the bad news. 1011 */ 1012 if ((ret == 0) || (rd_sync() < 0)) { 1013 paxwarn(1,"Premature end of file on archive read"); 1014 return(-1); 1015 } 1016 if (!in_resync) { 1017 if (act == APPND) { 1018 paxwarn(1, 1019 "Archive I/O error, cannot continue"); 1020 return(-1); 1021 } 1022 paxwarn(1,"Archive I/O error. Trying to recover."); 1023 ++in_resync; 1024 } 1025 1026 /* 1027 * oh well, throw it all out and start over 1028 */ 1029 res = hsz; 1030 hdend = hdbuf; 1031 } 1032 1033 /* 1034 * ok we have a contiguous buffer of the right size. Call the 1035 * format read routine. If this was not a valid header and this 1036 * format stores trailers outside of the header, call the 1037 * format specific trailer routine to check for a trailer. We 1038 * have to watch out that we do not mis-identify file data or 1039 * block padding as a header or trailer. Format specific 1040 * trailer functions must NOT check for the trailer while we 1041 * are running in resync mode. Some trailer functions may tell 1042 * us that this block cannot contain a valid header either, so 1043 * we then throw out the entire block and start over. 1044 */ 1045 if ((*frmt->rd)(arcn, hdbuf) == 0) 1046 break; 1047 1048 if (!frmt->inhead) { 1049 /* 1050 * this format has trailers outside of valid headers 1051 */ 1052 if ((ret = (*frmt->trail)(hdbuf,in_resync,&cnt)) == 0){ 1053 /* 1054 * valid trailer found, drain input as required 1055 */ 1056 ar_drain(); 1057 return(-1); 1058 } 1059 1060 if (ret == 1) { 1061 /* 1062 * we are in resync and we were told to throw 1063 * the whole block out because none of the 1064 * bytes in this block can be used to form a 1065 * valid header 1066 */ 1067 res = hsz; 1068 hdend = hdbuf; 1069 continue; 1070 } 1071 } 1072 1073 /* 1074 * Brute force section. 1075 * not a valid header. We may be able to find a header yet. So 1076 * we shift over by one byte, and set up to read one byte at a 1077 * time from the archive and place it at the end of the buffer. 1078 * We will keep moving byte at a time until we find a header or 1079 * get a read error and have to start over. 1080 */ 1081 if (!in_resync) { 1082 if (act == APPND) { 1083 paxwarn(1,"Unable to append, archive header flaw"); 1084 return(-1); 1085 } 1086 paxwarn(1,"Invalid header, starting valid header search."); 1087 ++in_resync; 1088 } 1089 memmove(hdbuf, hdbuf+1, shftsz); 1090 res = 1; 1091 hdend = hdbuf + shftsz; 1092 } 1093 1094 /* 1095 * ok got a valid header, check for trailer if format encodes it in the 1096 * the header. NOTE: the parameters are different than trailer routines 1097 * which encode trailers outside of the header! 1098 */ 1099 if (frmt->inhead && ((*frmt->trail)(arcn) == 0)) { 1100 /* 1101 * valid trailer found, drain input as required 1102 */ 1103 ar_drain(); 1104 return(-1); 1105 } 1106 1107 ++flcnt; 1108 return(0); 1109} 1110 1111/* 1112 * get_arc() 1113 * Figure out what format an archive is. Handles archive with flaws by 1114 * brute force searches for a legal header in any supported format. The 1115 * format id routines have to be careful to NOT mis-identify a format. 1116 * ASSUMED: headers fit within a BLKMULT header. 1117 * Return: 1118 * 0 if archive found -1 otherwise 1119 */ 1120 1121#ifdef __STDC__ 1122static int 1123get_arc(void) 1124#else 1125static int 1126get_arc() 1127#endif 1128{ 1129 register int i; 1130 register int hdsz = 0; 1131 register int res; 1132 register int minhd = BLKMULT; 1133 char *hdend; 1134 int notice = 0; 1135 1136 /* 1137 * find the smallest header size in all archive formats and then set up 1138 * to read the archive. 1139 */ 1140 for (i = 0; ford[i] >= 0; ++i) { 1141 if (fsub[ford[i]].hsz < minhd) 1142 minhd = fsub[ford[i]].hsz; 1143 } 1144 if (rd_start() < 0) 1145 return(-1); 1146 res = BLKMULT; 1147 hdsz = 0; 1148 hdend = hdbuf; 1149 for(;;) { 1150 for (;;) { 1151 /* 1152 * fill the buffer with at least the smallest header 1153 */ 1154 i = rd_wrbuf(hdend, res); 1155 if (i > 0) 1156 hdsz += i; 1157 if (hdsz >= minhd) 1158 break; 1159 1160 /* 1161 * if we cannot recover from a read error quit 1162 */ 1163 if ((i == 0) || (rd_sync() < 0)) 1164 goto out; 1165 1166 /* 1167 * when we get an error none of the data we already 1168 * have can be used to create a legal header (we just 1169 * got an error in the middle), so we throw it all out 1170 * and refill the buffer with fresh data. 1171 */ 1172 res = BLKMULT; 1173 hdsz = 0; 1174 hdend = hdbuf; 1175 if (!notice) { 1176 if (act == APPND) 1177 return(-1); 1178 paxwarn(1,"Cannot identify format. Searching..."); 1179 ++notice; 1180 } 1181 } 1182 1183 /* 1184 * we have at least the size of the smallest header in any 1185 * archive format. Look to see if we have a match. The array 1186 * ford[] is used to specify the header id order to reduce the 1187 * chance of incorrectly id'ing a valid header (some formats 1188 * may be subsets of each other and the order would then be 1189 * important). 1190 */ 1191 for (i = 0; ford[i] >= 0; ++i) { 1192 if ((*fsub[ford[i]].id)(hdbuf, hdsz) < 0) 1193 continue; 1194 frmt = &(fsub[ford[i]]); 1195 /* 1196 * yuck, to avoid slow special case code in the extract 1197 * routines, just push this header back as if it was 1198 * not seen. We have left extra space at start of the 1199 * buffer for this purpose. This is a bit ugly, but 1200 * adding all the special case code is far worse. 1201 */ 1202 pback(hdbuf, hdsz); 1203 return(0); 1204 } 1205 1206 /* 1207 * We have a flawed archive, no match. we start searching, but 1208 * we never allow additions to flawed archives 1209 */ 1210 if (!notice) { 1211 if (act == APPND) 1212 return(-1); 1213 paxwarn(1, "Cannot identify format. Searching..."); 1214 ++notice; 1215 } 1216 1217 /* 1218 * brute force search for a header that we can id. 1219 * we shift through byte at a time. this is slow, but we cannot 1220 * determine the nature of the flaw in the archive in a 1221 * portable manner 1222 */ 1223 if (--hdsz > 0) { 1224 memmove(hdbuf, hdbuf+1, hdsz); 1225 res = BLKMULT - hdsz; 1226 hdend = hdbuf + hdsz; 1227 } else { 1228 res = BLKMULT; 1229 hdend = hdbuf; 1230 hdsz = 0; 1231 } 1232 } 1233 1234 out: 1235 /* 1236 * we cannot find a header, bow, apologize and quit 1237 */ 1238 paxwarn(1, "Sorry, unable to determine archive format."); 1239 return(-1); 1240} 1241