diff --git a/bin/pax/extern.h b/bin/pax/extern.h index 2b062cbde300..5f7625e7b4c8 100644 --- a/bin/pax/extern.h +++ b/bin/pax/extern.h @@ -1,286 +1,285 @@ /*- * Copyright (c) 1992 Keith Muller. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Keith Muller of the University of California, San Diego. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)extern.h 8.2 (Berkeley) 4/18/94 * $FreeBSD$ */ /* * External references from each source file */ #include /* * ar_io.c */ extern char *arcname; int ar_open __P((char *)); void ar_close __P((void)); void ar_drain __P((void)); int ar_set_wr __P((void)); int ar_app_ok __P((void)); int ar_read __P((register char *, register int)); int ar_write __P((register char *, register int)); int ar_rdsync __P((void)); int ar_fow __P((off_t, off_t *)); int ar_rev __P((off_t )); int ar_next __P((void)); /* * ar_subs.c */ extern u_long flcnt; void list __P((void)); void extract __P((void)); void append __P((void)); void archive __P((void)); void copy __P((void)); /* * buf_subs.c */ extern int blksz; extern int wrblksz; extern int maxflt; extern int rdblksz; extern off_t wrlimit; extern off_t rdcnt; extern off_t wrcnt; int wr_start __P((void)); int rd_start __P((void)); void cp_start __P((void)); int appnd_start __P((off_t)); int rd_sync __P((void)); void pback __P((char *, int)); int rd_skip __P((off_t)); void wr_fin __P((void)); int wr_rdbuf __P((register char *, register int)); int rd_wrbuf __P((register char *, register int)); int wr_skip __P((off_t)); int wr_rdfile __P((ARCHD *, int, off_t *)); int rd_wrfile __P((ARCHD *, int, off_t *)); void cp_file __P((ARCHD *, int, int)); int buf_fill __P((void)); int buf_flush __P((register int)); /* * cache.c */ int uidtb_start __P((void)); int gidtb_start __P((void)); int usrtb_start __P((void)); int grptb_start __P((void)); char * name_uid __P((uid_t, int)); char * name_gid __P((gid_t, int)); int uid_name __P((char *, uid_t *)); int gid_name __P((char *, gid_t *)); /* * cpio.c */ int cpio_strd __P((void)); int cpio_trail __P((register ARCHD *)); int cpio_endwr __P((void)); int cpio_id __P((char *, int)); int cpio_rd __P((register ARCHD *, register char *)); off_t cpio_endrd __P((void)); int cpio_stwr __P((void)); int cpio_wr __P((register ARCHD *)); int vcpio_id __P((char *, int)); int crc_id __P((char *, int)); int crc_strd __P((void)); int vcpio_rd __P((register ARCHD *, register char *)); off_t vcpio_endrd __P((void)); int crc_stwr __P((void)); int vcpio_wr __P((register ARCHD *)); int bcpio_id __P((char *, int)); int bcpio_rd __P((register ARCHD *, register char *)); off_t bcpio_endrd __P((void)); int bcpio_wr __P((register ARCHD *)); /* * file_subs.c */ int file_creat __P((register ARCHD *)); void file_close __P((register ARCHD *, int)); int lnk_creat __P((register ARCHD *)); int cross_lnk __P((register ARCHD *)); int chk_same __P((register ARCHD *)); int node_creat __P((register ARCHD *)); int unlnk_exist __P((register char *, register int)); int chk_path __P((register char *, uid_t, gid_t)); void set_ftime __P((char *fnm, time_t mtime, time_t atime, int frc)); int set_ids __P((char *, uid_t, gid_t)); void set_pmode __P((char *, mode_t)); int file_write __P((int, char *, register int, int *, int *, int, char *)); void file_flush __P((int, char *, int)); void rdfile_close __P((register ARCHD *, register int *)); int set_crc __P((register ARCHD *, register int)); /* * ftree.c */ int ftree_start __P((void)); int ftree_add __P((register char *)); void ftree_sel __P((register ARCHD *)); void ftree_chk __P((void)); int next_file __P((register ARCHD *)); /* * gen_subs.c */ void ls_list __P((register ARCHD *, time_t)); void ls_tty __P((register ARCHD *)); void zf_strncpy __P((register char *, register char *, int)); int l_strncpy __P((register char *, register char *, int)); u_long asc_ul __P((register char *, int, register int)); int ul_asc __P((u_long, register char *, register int, register int)); #ifndef NET2_STAT u_quad_t asc_uqd __P((register char *, int, register int)); int uqd_asc __P((u_quad_t, register char *, register int, register int)); #endif /* * options.c */ extern FSUB fsub[]; extern int ford[]; void options __P((register int, register char **)); OPLIST * opt_next __P((void)); int opt_add __P((register char *)); int bad_opt __P((void)); /* * pat_rep.c */ int rep_add __P((register char *)); int pat_add __P((char *)); void pat_chk __P((void)); int pat_sel __P((register ARCHD *)); int pat_match __P((register ARCHD *)); int mod_name __P((register ARCHD *)); int set_dest __P((register ARCHD *, char *, int)); /* * pax.c */ extern int act; extern FSUB *frmt; extern int cflag; extern int dflag; extern int iflag; extern int kflag; extern int lflag; extern int nflag; extern int tflag; extern int uflag; extern int vflag; extern int Dflag; extern int Hflag; extern int Lflag; extern int Xflag; extern int Yflag; extern int Zflag; extern int vfpart; extern int patime; extern int pmtime; extern int pmode; extern int pids; extern int exit_val; extern int docrc; extern char *dirptr; -extern char *ltmfrmt; extern char *argv0; int main __P((int, char **)); void sig_cleanup __P((int)); /* * sel_subs.c */ int sel_chk __P((register ARCHD *)); int grp_add __P((register char *)); int usr_add __P((register char *)); int trng_add __P((register char *)); /* * tables.c */ int lnk_start __P((void)); int chk_lnk __P((register ARCHD *)); void purg_lnk __P((register ARCHD *)); void lnk_end __P((void)); int ftime_start __P((void)); int chk_ftime __P((register ARCHD *)); int name_start __P((void)); int add_name __P((register char *, int, char *)); void sub_name __P((register char *, int *)); int dev_start __P((void)); int add_dev __P((register ARCHD *)); int map_dev __P((register ARCHD *, u_long, u_long)); int atdir_start __P((void)); void atdir_end __P((void)); void add_atdir __P((char *, dev_t, ino_t, time_t, time_t)); int get_atdir __P((dev_t, ino_t, time_t *, time_t *)); int dir_start __P((void)); void add_dir __P((char *, int, struct stat *, int)); void proc_dir __P((void)); u_int st_hash __P((char *, int, int)); /* * tar.c */ int tar_endwr __P((void)); off_t tar_endrd __P((void)); int tar_trail __P((register char *, register int, register int *)); int tar_id __P((register char *, int)); int tar_opt __P((void)); int tar_rd __P((register ARCHD *, register char *)); int tar_wr __P((register ARCHD *)); int ustar_strd __P((void)); int ustar_stwr __P((void)); int ustar_id __P((char *, int)); int ustar_rd __P((register ARCHD *, register char *)); int ustar_wr __P((register ARCHD *)); /* * tty_subs.c */ int tty_init __P((void)); void tty_prnt __P((char *, ...)); int tty_read __P((char *, int)); void pax_warn __P((int, char *, ...)); void sys_warn __P((int, int, char *, ...)); diff --git a/bin/pax/gen_subs.c b/bin/pax/gen_subs.c index 83cfdc5355fd..bd04aa88657f 100644 --- a/bin/pax/gen_subs.c +++ b/bin/pax/gen_subs.c @@ -1,489 +1,479 @@ /*- * Copyright (c) 1992 Keith Muller. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Keith Muller of the University of California, San Diego. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include "pax.h" #include "extern.h" /* * a collection of general purpose subroutines used by pax */ /* * constants used by ls_list() when printing out archive members */ #define MODELEN 20 #define DATELEN 64 #define SIXMONTHS ((365 / 2) * 86400) #define CURFRMT "%Ef %H:%M" #define OLDFRMT "%Ef %Y" #ifndef UT_NAMESIZE #define UT_NAMESIZE 8 #endif #define UT_GRPSIZE 6 /* * ls_list() * list the members of an archive in ls format */ #if __STDC__ void ls_list(register ARCHD *arcn, time_t now) #else void ls_list(arcn, now) register ARCHD *arcn; time_t now; #endif { register struct stat *sbp; char f_mode[MODELEN]; char f_date[DATELEN]; char *timefrmt; /* * if not verbose, just print the file name */ if (!vflag) { (void)printf("%s\n", arcn->name); (void)fflush(stdout); return; } /* * user wants long mode */ sbp = &(arcn->sb); strmode(sbp->st_mode, f_mode); - if (ltmfrmt == NULL) { - /* - * no locale specified format. time format based on age - * compared to the time pax was started. - */ - if ((sbp->st_mtime + SIXMONTHS) <= now) - timefrmt = OLDFRMT; - else - timefrmt = CURFRMT; - } else - timefrmt = ltmfrmt; + /* + * time format based on age compared to the time pax was started. + */ + if ((sbp->st_mtime + SIXMONTHS) <= now) + timefrmt = OLDFRMT; + else + timefrmt = CURFRMT; /* * print file mode, link count, uid, gid and time */ if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0) f_date[0] = '\0'; (void)printf("%s%2u %-*s %-*s ", f_mode, sbp->st_nlink, UT_NAMESIZE, name_uid(sbp->st_uid, 1), UT_GRPSIZE, name_gid(sbp->st_gid, 1)); /* * print device id's for devices, or sizes for other nodes */ if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK)) # ifdef NET2_STAT (void)printf("%4u,%4u ", MAJOR(sbp->st_rdev), MINOR(sbp->st_rdev)); # else (void)printf("%4lu,%4lu ", (unsigned long)MAJOR(sbp->st_rdev), (unsigned long)MINOR(sbp->st_rdev)); # endif else { # ifdef NET2_STAT (void)printf("%9lu ", sbp->st_size); # else (void)printf("%9qu ", sbp->st_size); # endif } /* * print name and link info for hard and soft links */ (void)printf("%s %s", f_date, arcn->name); if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) (void)printf(" == %s\n", arcn->ln_name); else if (arcn->type == PAX_SLK) (void)printf(" => %s\n", arcn->ln_name); else (void)putchar('\n'); (void)fflush(stdout); return; } /* * tty_ls() * print a short summary of file to tty. */ #if __STDC__ void ls_tty(register ARCHD *arcn) #else void ls_tty(arcn) register ARCHD *arcn; #endif { char f_date[DATELEN]; char f_mode[MODELEN]; char *timefrmt; - if (ltmfrmt == NULL) { - /* - * no locale specified format - */ - if ((arcn->sb.st_mtime + SIXMONTHS) <= time((time_t *)NULL)) - timefrmt = OLDFRMT; - else - timefrmt = CURFRMT; - } else - timefrmt = ltmfrmt; + if ((arcn->sb.st_mtime + SIXMONTHS) <= time((time_t *)NULL)) + timefrmt = OLDFRMT; + else + timefrmt = CURFRMT; /* * convert time to string, and print */ if (strftime(f_date, DATELEN, timefrmt, localtime(&(arcn->sb.st_mtime))) == 0) f_date[0] = '\0'; strmode(arcn->sb.st_mode, f_mode); tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name); return; } /* * zf_strncpy() * copy src to dest up to len chars (stopping at first '\0'), when src is * shorter than len, pads to len with '\0'. big performance win (and * a lot easier to code) over strncpy(), then a strlen() then a * bzero(). (or doing the bzero() first). */ #if __STDC__ void zf_strncpy(register char *dest, register char *src, int len) #else void zf_strncpy(dest, src, len) register char *dest; register char *src; int len; #endif { register char *stop; stop = dest + len; while ((dest < stop) && (*src != '\0')) *dest++ = *src++; while (dest < stop) *dest++ = '\0'; return; } /* * l_strncpy() * copy src to dest up to len chars (stopping at first '\0') * Return: * number of chars copied. (Note this is a real performance win over * doing a strncpy() then a strlen() */ #if __STDC__ int l_strncpy(register char *dest, register char *src, int len) #else int l_strncpy(dest, src, len) register char *dest; register char *src; int len; #endif { register char *stop; register char *start; stop = dest + len; start = dest; while ((dest < stop) && (*src != '\0')) *dest++ = *src++; if (dest < stop) *dest = '\0'; return(dest - start); } /* * asc_ul() * convert hex/octal character string into a u_long. We do not have to * check for overflow! (the headers in all supported formats are not large * enough to create an overflow). * NOTE: strings passed to us are NOT TERMINATED. * Return: * unsigned long value */ #if __STDC__ u_long asc_ul(register char *str, int len, register int base) #else u_long asc_ul(str, len, base) register char *str; int len; register int base; #endif { register char *stop; u_long tval = 0; stop = str + len; /* * skip over leading blanks and zeros */ while ((str < stop) && ((*str == ' ') || (*str == '0'))) ++str; /* * for each valid digit, shift running value (tval) over to next digit * and add next digit */ if (base == HEX) { while (str < stop) { if ((*str >= '0') && (*str <= '9')) tval = (tval << 4) + (*str++ - '0'); else if ((*str >= 'A') && (*str <= 'F')) tval = (tval << 4) + 10 + (*str++ - 'A'); else if ((*str >= 'a') && (*str <= 'f')) tval = (tval << 4) + 10 + (*str++ - 'a'); else break; } } else { while ((str < stop) && (*str >= '0') && (*str <= '7')) tval = (tval << 3) + (*str++ - '0'); } return(tval); } /* * ul_asc() * convert an unsigned long into an hex/oct ascii string. pads with LEADING * ascii 0's to fill string completely * NOTE: the string created is NOT TERMINATED. */ #if __STDC__ int ul_asc(u_long val, register char *str, register int len, register int base) #else int ul_asc(val, str, len, base) u_long val; register char *str; register int len; register int base; #endif { register char *pt; u_long digit; /* * WARNING str is not '\0' terminated by this routine */ pt = str + len - 1; /* * do a tailwise conversion (start at right most end of string to place * least significant digit). Keep shifting until conversion value goes * to zero (all digits were converted) */ if (base == HEX) { while (pt >= str) { if ((digit = (val & 0xf)) < 10) *pt-- = '0' + (char)digit; else *pt-- = 'a' + (char)(digit - 10); if ((val = (val >> 4)) == (u_long)0) break; } } else { while (pt >= str) { *pt-- = '0' + (char)(val & 0x7); if ((val = (val >> 3)) == (u_long)0) break; } } /* * pad with leading ascii ZEROS. We return -1 if we ran out of space. */ while (pt >= str) *pt-- = '0'; if (val != (u_long)0) return(-1); return(0); } #ifndef NET2_STAT /* * asc_uqd() * convert hex/octal character string into a u_quad_t. We do not have to * check for overflow! (the headers in all supported formats are not large * enough to create an overflow). * NOTE: strings passed to us are NOT TERMINATED. * Return: * u_quad_t value */ #if __STDC__ u_quad_t asc_uqd(register char *str, int len, register int base) #else u_quad_t asc_uqd(str, len, base) register char *str; int len; register int base; #endif { register char *stop; u_quad_t tval = 0; stop = str + len; /* * skip over leading blanks and zeros */ while ((str < stop) && ((*str == ' ') || (*str == '0'))) ++str; /* * for each valid digit, shift running value (tval) over to next digit * and add next digit */ if (base == HEX) { while (str < stop) { if ((*str >= '0') && (*str <= '9')) tval = (tval << 4) + (*str++ - '0'); else if ((*str >= 'A') && (*str <= 'F')) tval = (tval << 4) + 10 + (*str++ - 'A'); else if ((*str >= 'a') && (*str <= 'f')) tval = (tval << 4) + 10 + (*str++ - 'a'); else break; } } else { while ((str < stop) && (*str >= '0') && (*str <= '7')) tval = (tval << 3) + (*str++ - '0'); } return(tval); } /* * uqd_asc() * convert an u_quad_t into a hex/oct ascii string. pads with LEADING * ascii 0's to fill string completely * NOTE: the string created is NOT TERMINATED. */ #if __STDC__ int uqd_asc(u_quad_t val, register char *str, register int len, register int base) #else int uqd_asc(val, str, len, base) u_quad_t val; register char *str; register int len; register int base; #endif { register char *pt; u_quad_t digit; /* * WARNING str is not '\0' terminated by this routine */ pt = str + len - 1; /* * do a tailwise conversion (start at right most end of string to place * least significant digit). Keep shifting until conversion value goes * to zero (all digits were converted) */ if (base == HEX) { while (pt >= str) { if ((digit = (val & 0xf)) < 10) *pt-- = '0' + (char)digit; else *pt-- = 'a' + (char)(digit - 10); if ((val = (val >> 4)) == (u_quad_t)0) break; } } else { while (pt >= str) { *pt-- = '0' + (char)(val & 0x7); if ((val = (val >> 3)) == (u_quad_t)0) break; } } /* * pad with leading ascii ZEROS. We return -1 if we ran out of space. */ while (pt >= str) *pt-- = '0'; if (val != (u_quad_t)0) return(-1); return(0); } #endif diff --git a/bin/pax/pax.c b/bin/pax/pax.c index 7bcc81e7ad0b..641d53fab0c7 100644 --- a/bin/pax/pax.c +++ b/bin/pax/pax.c @@ -1,410 +1,402 @@ /*- * Copyright (c) 1992 Keith Muller. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Keith Muller of the University of California, San Diego. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1992, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include "pax.h" #include "extern.h" static int gen_init __P((void)); /* * PAX main routines, general globals and some simple start up routines */ /* * Variables that can be accessed by any routine within pax */ int act = DEFOP; /* read/write/append/copy */ FSUB *frmt = NULL; /* archive format type */ int cflag; /* match all EXCEPT pattern/file */ int dflag; /* directory member match only */ int iflag; /* interactive file/archive rename */ int kflag; /* do not overwrite existing files */ int lflag; /* use hard links when possible */ int nflag; /* select first archive member match */ int tflag; /* restore access time after read */ int uflag; /* ignore older modification time files */ int vflag; /* produce verbose output */ int Dflag; /* same as uflag except inode change time */ int Hflag; /* follow command line symlinks (write only) */ int Lflag; /* follow symlinks when writing */ int Xflag; /* archive files with same device id only */ int Yflag; /* same as Dflg except after name mode */ int Zflag; /* same as uflg except after name mode */ int vfpart; /* is partial verbose output in progress */ int patime = 1; /* preserve file access time */ int pmtime = 1; /* preserve file modification times */ int pmode; /* preserve file mode bits */ int pids; /* preserve file uid/gid */ int exit_val; /* exit value */ int docrc; /* check/create file crc */ char *dirptr; /* destination dir in a copy */ -char *ltmfrmt; /* -v locale time format (if any) */ char *argv0; /* root of argv[0] */ sigset_t s_mask; /* signal mask for cleanup critical sect */ /* * PAX - Portable Archive Interchange * * A utility to read, write, and write lists of the members of archive * files and copy directory hierarchies. A variety of archive formats * are supported (some are described in POSIX 1003.1 10.1): * * ustar - 10.1.1 extended tar interchange format * cpio - 10.1.2 extended cpio interchange format * tar - old BSD 4.3 tar format * binary cpio - old cpio with binary header format * sysVR4 cpio - with and without CRC * * This version is a superset of IEEE Std 1003.2b-d3 * * Summary of Extensions to the IEEE Standard: * * 1 READ ENHANCEMENTS * 1.1 Operations which read archives will continue to operate even when * processing archives which may be damaged, truncated, or fail to meet * format specs in several different ways. Damaged sections of archives * are detected and avoided if possible. Attempts will be made to resync * archive read operations even with badly damaged media. * 1.2 Blocksize requirements are not strictly enforced on archive read. * Tapes which have variable sized records can be read without errors. * 1.3 The user can specify via the non-standard option flag -E if error * resync operation should stop on a media error, try a specified number * of times to correct, or try to correct forever. * 1.4 Sparse files (lseek holes) stored on the archive (but stored with blocks * of all zeros will be restored with holes appropriate for the target * filesystem * 1.5 The user is notified whenever something is found during archive * read operations which violates spec (but the read will continue). * 1.6 Multiple archive volumes can be read and may span over different * archive devices * 1.7 Rigidly restores all file attributes exactly as they are stored on the * archive. * 1.8 Modification change time ranges can be specified via multiple -T * options. These allow a user to select files whose modification time * lies within a specific time range. * 1.9 Files can be selected based on owner (user name or uid) via one or more * -U options. * 1.10 Files can be selected based on group (group name or gid) via one o * more -G options. * 1.11 File modification time can be checked against existing file after * name modification (-Z) * * 2 WRITE ENHANCEMENTS * 2.1 Write operation will stop instead of allowing a user to create a flawed * flawed archive (due to any problem). * 2.2 Archives written by pax are forced to strictly conform to both the * archive and pax the specific format specifications. * 2.3 Blocking size and format is rigidly enforced on writes. * 2.4 Formats which may exhibit header overflow problems (they have fields * too small for large file systems, such as inode number storage), use * routines designed to repair this problem. These techniques still * conform to both pax and format specifications, but no longer truncate * these fields. This removes any restrictions on using these archive * formats on large file systems. * 2.5 Multiple archive volumes can be written and may span over different * archive devices * 2.6 A archive volume record limit allows the user to specify the number * of bytes stored on an archive volume. When reached the user is * prompted for the next archive volume. This is specified with the * non-standard -B flag. The limit is rounded up to the next blocksize. * 2.7 All archive padding during write use zero filled sections. This makes * it much easier to pull data out of flawed archive during read * operations. * 2.8 Access time reset with the -t applies to all file nodes (including * directories). * 2.9 Symbolic links can be followed with -L (optional in the spec). * 2.10 Modification or inode change time ranges can be specified via * multiple -T options. These allow a user to select files whose * modification or inode change time lies within a specific time range. * 2.11 Files can be selected based on owner (user name or uid) via one or more * -U options. * 2.12 Files can be selected based on group (group name or gid) via one o * more -G options. * 2.13 Symlinks which appear on the command line can be followed (without * following other symlinks; -H flag) * * 3 COPY ENHANCEMENTS * 3.1 Sparse files (lseek holes) can be copied without expanding the holes * into zero filled blocks. The file copy is created with holes which are * appropriate for the target filesystem * 3.2 Access time as well as modification time on copied file trees can be * preserved with the appropriate -p options. * 3.3 Access time reset with the -t applies to all file nodes (including * directories). * 3.4 Symbolic links can be followed with -L (optional in the spec). * 3.5 Modification or inode change time ranges can be specified via * multiple -T options. These allow a user to select files whose * modification or inode change time lies within a specific time range. * 3.6 Files can be selected based on owner (user name or uid) via one or more * -U options. * 3.7 Files can be selected based on group (group name or gid) via one o * more -G options. * 3.8 Symlinks which appear on the command line can be followed (without * following other symlinks; -H flag) * 3.9 File inode change time can be checked against existing file before * name modification (-D) * 3.10 File inode change time can be checked against existing file after * name modification (-Y) * 3.11 File modification time can be checked against existing file after * name modification (-Z) * * 4 GENERAL ENHANCEMENTS * 4.1 Internal structure is designed to isolate format dependent and * independent functions. Formats are selected via a format driver table. * This encourages the addition of new archive formats by only having to * write those routines which id, read and write the archive header. */ /* * main() * parse options, set up and operate as specified by the user. * any operational flaw will set exit_val to non-zero * Return: 0 if ok, 1 otherwise */ #if __STDC__ int main(int argc, char **argv) #else int main(argc, argv) int argc; char **argv; #endif { (void) setlocale(LC_ALL, ""); /* * parse options, determine operational mode, general init */ options(argc, argv); if ((gen_init() < 0) || (tty_init() < 0)) return(exit_val); /* * select a primary operation mode */ switch(act) { case EXTRACT: extract(); break; case ARCHIVE: archive(); break; case APPND: append(); break; case COPY: copy(); break; default: case LIST: list(); break; } return(exit_val); } /* * sig_cleanup() * when interrupted we try to do whatever delayed processing we can. * This is not critical, but we really ought to limit our damage when we * are aborted by the user. * Return: * never.... */ #if __STDC__ void sig_cleanup(int which_sig) #else void sig_cleanup(which_sig) int which_sig; #endif { /* * restore modes and times for any dirs we may have created * or any dirs we may have read. Set vflag and vfpart so the user * will clearly see the message on a line by itself. */ vflag = vfpart = 1; if (which_sig == SIGXCPU) pax_warn(0, "Cpu time limit reached, cleaning up."); else pax_warn(0, "Signal caught, cleaning up."); ar_close(); proc_dir(); if (tflag) atdir_end(); exit(1); } /* * gen_init() * general setup routines. Not all are required, but they really help * when dealing with a medium to large sized archives. */ #if __STDC__ static int gen_init(void) #else static int gen_init() #endif { struct rlimit reslimit; struct sigaction n_hand; struct sigaction o_hand; /* * Really needed to handle large archives. We can run out of memory for * internal tables really fast when we have a whole lot of files... */ if (getrlimit(RLIMIT_DATA , &reslimit) == 0){ reslimit.rlim_cur = reslimit.rlim_max; (void)setrlimit(RLIMIT_DATA , &reslimit); } /* * should file size limits be waived? if the os limits us, this is * needed if we want to write a large archive */ if (getrlimit(RLIMIT_FSIZE , &reslimit) == 0){ reslimit.rlim_cur = reslimit.rlim_max; (void)setrlimit(RLIMIT_FSIZE , &reslimit); } /* * increase the size the stack can grow to */ if (getrlimit(RLIMIT_STACK , &reslimit) == 0){ reslimit.rlim_cur = reslimit.rlim_max; (void)setrlimit(RLIMIT_STACK , &reslimit); } /* * not really needed, but doesn't hurt */ if (getrlimit(RLIMIT_RSS , &reslimit) == 0){ reslimit.rlim_cur = reslimit.rlim_max; (void)setrlimit(RLIMIT_RSS , &reslimit); } - /* - * Handle posix locale - * - * set user defines time printing format for -v option - */ - ltmfrmt = getenv("LC_TIME"); - /* * signal handling to reset stored directory times and modes. Since * we deal with broken pipes via failed writes we ignore it. We also * deal with any file size limit thorugh failed writes. Cpu time * limits are caught and a cleanup is forced. */ if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) || (sigaddset(&s_mask,SIGINT) < 0)||(sigaddset(&s_mask,SIGHUP) < 0) || (sigaddset(&s_mask,SIGPIPE) < 0)||(sigaddset(&s_mask,SIGQUIT)<0) || (sigaddset(&s_mask,SIGXCPU) < 0)||(sigaddset(&s_mask,SIGXFSZ)<0)) { pax_warn(1, "Unable to set up signal mask"); return(-1); } n_hand.sa_mask = s_mask; n_hand.sa_flags = 0; n_hand.sa_handler = sig_cleanup; if ((sigaction(SIGHUP, &n_hand, &o_hand) < 0) && (o_hand.sa_handler == SIG_IGN) && (sigaction(SIGHUP, &o_hand, &o_hand) < 0)) goto out; if ((sigaction(SIGTERM, &n_hand, &o_hand) < 0) && (o_hand.sa_handler == SIG_IGN) && (sigaction(SIGTERM, &o_hand, &o_hand) < 0)) goto out; if ((sigaction(SIGINT, &n_hand, &o_hand) < 0) && (o_hand.sa_handler == SIG_IGN) && (sigaction(SIGINT, &o_hand, &o_hand) < 0)) goto out; if ((sigaction(SIGQUIT, &n_hand, &o_hand) < 0) && (o_hand.sa_handler == SIG_IGN) && (sigaction(SIGQUIT, &o_hand, &o_hand) < 0)) goto out; if ((sigaction(SIGXCPU, &n_hand, &o_hand) < 0) && (o_hand.sa_handler == SIG_IGN) && (sigaction(SIGXCPU, &o_hand, &o_hand) < 0)) goto out; n_hand.sa_handler = SIG_IGN; if ((sigaction(SIGPIPE, &n_hand, &o_hand) < 0) || (sigaction(SIGXFSZ, &n_hand, &o_hand) < 0)) goto out; return(0); out: sys_warn(1, errno, "Unable to set up signal handler"); return(-1); }