on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
-
+
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
+Tue Jan 16 19:03:05 1996 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * util.c: An I/O error reading a file would cause the last byte
+ of the next file to be corrupted in the archive. Thanks to a
+ buggy NT NFS server for pointing out this problem.
+ * Version 2.4.2 released.
+
+Tue Jan 9 23:19:37 1996 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * copyout.c: missed 1 part of last bug fix.
+
+Mon Jan 8 16:49:01 1996 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * copyout.c, copypass.c: Use result of readlink() as length
+ of link name instead of size from lstat(). On some OS's lstat()
+ doesn't return the true length in size. Bug reported by
+ Robert Joop (rj@rainbow.IN-berlin.DE).
+
+Wed Dec 20 10:52:56 1995 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * rmt.c: Added temporary kludge so make rmt will work on Linux.
+ * configure.in: Only define HAVE_UTIME_H if utime.h declares
+ struct utimbuf.
+ * Makefile.in: Change prefix, exec_prefix and bindir to get their
+ values from configure. Added cpio.info to DISTFILES.
+ * cpio.texi: Added INFO-DIR-ENTRY.
+ * Version 2.4.1 released.
+
+Wed Nov 22 19:37:05 1995 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * cpio.texi: Updated release date and FSF's address.
+ * NEWS: Listed major new features for 2.4.
+ * mt.c, mt.1: Added seek and fsfm commands.
+ * Version 2.4 released.
+
+Tue Jun 27 19:14:27 1995 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * configure.in: fixed for new autoconf. Added check to make
+ sure fnmatch() works.
+ * Makefile.in: changed realclean to maintainer-clean. Added
+ support to handle fnmatch separate from other LIBOBJS.
+ * cpio.texi: More changes for 2.4.
+
+Wed Dec 14 16:14:27 1994 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * copypass.h: When given the -a option, set the access time of
+ the copy to be the access time of the original (instead of the
+ modification time of the original). Reported by
+ karney@pppl.gov (Charles Karney).
+ * cpio.texi: Updated with changes for 2.4.
+
+Wed Nov 3 18:18:07 1994 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * safe-stat.h, Makefile.in: New file used by mkdir.c. This will go
+ away when we get the real safe-xstat.[ch]in for mkdir.c.
+ * main.c: Don't mention [--null] twice in -p's usage message.
+ Changed --no-absolute-paths to --no-absolute-filenames.
+ * cpio.1: Updated man page with new features.
+ * cpio.texi, texinfo.tex, Makefile.in: Added texi documentation
+ from Robert Carleton (rbc@gnu.ai.mit.edu).
+
+Mon Oct 3 00:46:30 1994 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * makefile.pc, system.h: Changes to compile with Borland C++ 4.0.
+
+Thu Sep 29 22:15:50 1994 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * makepath.c: Don't #define index if it is already #defined.
+
+ * mt.c: Check for __hpux defined instead of __hpux__. Reported
+ by ericb@lsid.hp.com (Eric Backus).
+
+Thu Sep 29 11:21:31 1994 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * extern.h, util.c, copyout.c, copypass.c, main.c, global.c:
+ Never mind --ignore-disk-input-errors flag, we'll just always
+ do that, like tar.
+
+ * global.c, extern.h, main.c, copyin.c, copyout.c, copypass.c:
+ Added --quiet flag to supress printing number of blocks copied.
+
+ * global.c, extern.h: If compiled with gcc, make input_bytes
+ and output_bytes `long long' instead of `long'. We need more
+ than 32 bits to keep track of the number of bytes copied to
+ and from tape drives that hold more than 4Gbytes.
+
+ * util.c, copyin.c, main.c, global.c, extern.h: Added
+ --only-verify-crc flag to read a CRC format archive and verify
+ its contents' CRCs.
+
+ * copyout.c: Fixed problem with creating oldc format archives
+ on machines with 16 bit ints. Reported by mpoole@cix.compulink.co.uk
+ (Martin Poole).
+
+ * mt.c: Need to open tape WR_ONLY for erase command (and probably
+ others?). Reported by robert@hst.e.technik.uni-kl.de (Robert
+ Vogelgesan). Accept `eject' as a synonym for `offline'. Accept
+ `-t' as a synonym for `-f' (to be compatible with HPUX mt, which
+ only accepts `-t').
+
+Wed Sep 28 12:01:55 1994 John Oleynick (juo@wombat.gnu.ai.mit.edu)
+ * extern.h, global.c, main.c, util.c: only write sparse files
+ when given --sparse flag.
+ * extern.h, util.c, copyout.c, copypass.c, main.c, global.c:
+ Added support for --ignore-disk-input-errors flag.
+
+Wed Aug 24 12:55:38 1994 David J. MacKenzie (djm@churchy.gnu.ai.mit.edu)
+
+ * configure.in: Replace calls to AC_REMOTE_TAPE and AC_RSH
+ with equivalent code, since those macros are going away.
+
+Sun Feb 13 00:56:48 1994 John Oleynick (juo@goldman.gnu.ai.mit.edu)
+ * extern.h, global.c, main.c, util.c: Added code to
+ tape_buffered_peek() to properly handle large, corrutped
+ archives, without overrunning the allocated buffer and
+ dumping core. Also changed the way the input and output
+ buffers are allocated in initialize_buffers().
+
+Tue Jan 25 01:04:32 1994 John Oleynick (juo@goldman.gnu.ai.mit.edu)
+ * copyin.c, copyout.c, copypass.c, extern.h, main.c, tar.c, util.c:
+ Redid i/o buffer code. Previously, the same routines buffered input and
+ output for accessing the archive and the filesystem. Now there are
+ separate routines for buffering input and output and for buffering the
+ archive and the filesystem. This simplifies much of the buffer code
+ (e.g., only input from the archive has to check for end of tape and
+ allow the tape to be changed, only output to the filesystem has to
+ handle byte and word swapping, etc.; previously one routine had to
+ handle all of these special cases) This is how the routines got split
+ and renamed (old name -> new name):
+
+ clear_rest_of_block -> tape_clear_rest_of_block
+ copy_files -> copy_files_tape_to_disk
+ " -> copy_files_disk_to_disk
+ " -> copy_files_disk_to_tape
+ copy_buf_out -> disk_buffered_write
+ " -> tape_buffered_write
+ copy_in_buf -> tape_buffered_read
+ empty_output_buffer -> tape_empty_output_buffer
+ " -> disk_empty_output_buffer
+ fill_input_buffer -> tape_fill_input_buffer
+ " -> disk_fill_input_buffer
+ pad_output -> tape_pad_output
+ peek_in_buf -> tape_buffered_peek
+ skip_padding -> tape_skip_padding
+ toss_input -> tape_toss_input
+
+ * extern.h, global.c, main.c, util.c: Added support for
+ writing sparse files.
+
+Tue Dec 28 23:01:36 1993 John Oleynick (juo@goldman.gnu.ai.mit.edu)
+ * util.c, system.h, makepath.c, extern.h: don't define chown()
+ and don't typedef uid_t and gid_t if we are being compiled
+ by DJGPP.
+
+ * copyin.c, extern.h, global.c, main.c: Added support for
+ --rename-batch-file.
+
+ * copyin.c, copyout.c, extern.h: Cleaned up to pass gcc -Wall.
+
+Wed Dec 22 02:17:44 1993 John Oleynick (juo@goldman.gnu.ai.mit.edu)
+
+ * makepath.c, copypass.c, copyin.c: If cpio was creating a
+ directory that contained `.' in the pathname (e.g. `foo/./bar'),
+ it would complain that it could not create `.', since it already
+ exists. From schwab@issan.informatik.uni-dortmund.de (Andreas
+ Schwab).
+
+ * mt.c: Added "eject" as a synonym for "offline".
+
+ * util.c: Slight modification to when we lseek with
+ BROKEN_LONG_TAPE_DRIVER (do it every 1Gb, instead
+ of every 2Gb).
+
+ * copyin.c, global.c, extern.h: Added --no-absolute-paths option,
+ to ignore absolute paths in archives.
+
+Tue Dec 21 01:30:59 1993 John Oleynick (juo@goldman.gnu.ai.mit.edu)
+
+ * util.c: Fix for copying new_media_message_after_number. From
+ Christian.Kuehnke@arbi.informatik.uni-oldenburg.de (Christian
+ Kuehnke).
+
+Thu Jul 29 20:35:57 1993 David J. MacKenzie (djm@wookumz.gnu.ai.mit.edu)
+
+ * Makefile.in (config.status): Run config.status --recheck, not
+ configure, to get the right args passed.
+
+Mon Jul 19 23:01:00 1993 David J. MacKenzie (djm@churchy.gnu.ai.mit.edu)
+
+ * Makefile.in (libdir): Use standard GNU value --
+ $(exec_prefix)/lib, not /etc.
+ (.c.o): Put CFLAGS last.
+
+Thu Jul 8 19:43:39 1993 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu)
+
+ * Makefile.in: Add rules for remaking Makefile, configure,
+ config.status.
+
Mon Jul 5 14:54:08 1993 John Oleynick (juo@spiff.gnu.ai.mit.edu)
* cpio.1: Updated man page for 2.3.
-# $OpenBSD: Makefile,v 1.2 1996/08/20 05:14:05 tholo Exp $
+# $OpenBSD: Makefile,v 1.3 1997/01/26 09:35:10 downsj Exp $
# $NetBSD: Makefile,v 1.3 1995/04/23 07:58:27 cgd Exp $
PROG= cpio
-CFLAGS+= -I${.CURDIR} -DRETSIGTYPE=void -DHAVE_SYS_MTIO_H=1 -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DHAVE_FCNTL_H=1 -DHAVE_UTIME_H=1 -DHAVE_STRERROR=1 -DHAVE_VPRINTF=1 -DDIRENT=1
+CFLAGS+= -I${.CURDIR} -DRETSIGTYPE=void -DHAVE_SYS_MTIO_H=1 -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DHAVE_FCNTL_H=1 -DHAVE_UTIME_H=1 -DHAVE_STRERROR=1 -DHAVE_LCHOWN=1 -DHAVE_VPRINTF=1 -DHAVE_ALLOCA=1 -DHAVE_DIRENT_H=1 -DHAVE_SYS_CDEFS_H=1
-SRCS = copyin.c copyout.c copypass.c defer.c dstring.c fnmatch.c global.c \
+MAKEINFO= makeinfo
+
+SRCS= copyin.c copyout.c copypass.c defer.c dstring.c fnmatch.c global.c \
main.c tar.c util.c error.c filemode.c getopt.c getopt1.c version.c \
rtapelib.c dirname.c idcache.c makepath.c xmalloc.c stripslash.c \
userspec.c xstrdup.c
+CLEANFILES+= cpio.info
+
+all: cpio.info
+
+cpio.info: cpio.texi
+ ${MAKEINFO} -I${.CURDIR} ${.CURDIR}/cpio.texi
+
+beforeinstall:
+ ${INSTALL} ${COPY} -m 444 -o ${BINOWN} -g ${BINGRP} *.info* \
+ ${DESTDIR}/usr/share/info
.include <bsd.prog.mk>
\f
+Major changes in version 2.4:
+
+* new texinfo documentation
+* --sparse option to write sparse files
+* --only-verify-crc option to verify a CRC format archive
+* --no-absolute-paths option to ignore absolute paths
+* --quiet option to supress printing number of blocks copied
+* handle disk input errors more gracefully
+\f
Major changes in version 2.3:
* in newc and crc format archives, only store 1 copy of multiply linked files
As of version 2.0, it supports the features of the System V release 4
cpio, including support for tar archives.
+This package also includes rmt, the remote tape server, and mt, a tape
+drive control program; these two programs will only be compiled if
+your system supports remote command execution, and tape drive control
+operations, respectively.
+
+See the file INSTALL for compilation and installation instructions for Unix.
+
+For non-Unix systems:
+
+makefile.pc is a makefile for Turbo C or C++ or Borland C++ on MS-DOS.
+
+makefile.os2 is a makefile for MS C and GNU C (emx/gcc) on OS/2.
+cpio.def is a linker definition file for the MS C OS/2 version.
+
+
The main advantages of GNU cpio over Unix versions are:
* It can access tape drives on other hosts using TCP/IP.
+++ /dev/null
-/* The version number of cpio and mt. -- this is the same as "version.c" */
-char *version_string = "version 2.3\n";
+++ /dev/null
-/* alloca.c -- allocate automatically reclaimed memory
- (Mostly) portable public-domain implementation -- D A Gwyn
-
- This implementation of the PWB library alloca function,
- which is used to allocate space off the run-time stack so
- that it is automatically reclaimed upon procedure exit,
- was inspired by discussions with J. Q. Johnson of Cornell.
- J.Otto Tennant <jot@cray.com> contributed the Cray support.
-
- There are some preprocessor constants that can
- be defined when compiling for your specific system, for
- improved efficiency; however, the defaults should be okay.
-
- The general concept of this implementation is to keep
- track of all alloca-allocated blocks, and reclaim any
- that are found to be deeper in the stack than the current
- invocation. This heuristic does not reclaim storage as
- soon as it becomes invalid, but it will do so eventually.
-
- As a special case, alloca(0) reclaims storage without
- allocating any. It is a good idea to use alloca(0) in
- your main control loop, etc. to force garbage collection. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* If compiling with GCC, this file's not needed. */
-#ifndef alloca
-
-#ifdef emacs
-#ifdef static
-/* actually, only want this if static is defined as ""
- -- this is for usg, in which emacs must undefine static
- in order to make unexec workable
- */
-#ifndef STACK_DIRECTION
-you
-lose
--- must know STACK_DIRECTION at compile-time
-#endif /* STACK_DIRECTION undefined */
-#endif /* static */
-#endif /* emacs */
-
-/* If your stack is a linked list of frames, you have to
- provide an "address metric" ADDRESS_FUNCTION macro. */
-
-#ifdef CRAY
-long i00afunc ();
-#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
-#else
-#define ADDRESS_FUNCTION(arg) &(arg)
-#endif
-
-#if __STDC__
-typedef void *pointer;
-#else
-typedef char *pointer;
-#endif
-
-#define NULL 0
-
-/* Different portions of Emacs need to call different versions of
- malloc. The Emacs executable needs alloca to call xmalloc, because
- ordinary malloc isn't protected from input signals. On the other
- hand, the utilities in lib-src need alloca to call malloc; some of
- them are very simple, and don't have an xmalloc routine.
-
- Non-Emacs programs expect this to call use xmalloc.
-
- Callers below should use malloc. */
-
-#ifndef emacs
-#define malloc xmalloc
-extern pointer xmalloc ();
-#endif
-
-/* Define STACK_DIRECTION if you know the direction of stack
- growth for your system; otherwise it will be automatically
- deduced at run-time.
-
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown */
-
-#ifndef STACK_DIRECTION
-#define STACK_DIRECTION 0 /* Direction unknown. */
-#endif
-
-#if STACK_DIRECTION != 0
-
-#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
-
-#else /* STACK_DIRECTION == 0; need run-time code. */
-
-static int stack_dir; /* 1 or -1 once known. */
-#define STACK_DIR stack_dir
-
-static void
-find_stack_direction ()
-{
- static char *addr = NULL; /* Address of first `dummy', once known. */
- auto char dummy; /* To get stack address. */
-
- if (addr == NULL)
- { /* Initial entry. */
- addr = ADDRESS_FUNCTION (dummy);
-
- find_stack_direction (); /* Recurse once. */
- }
- else
- {
- /* Second entry. */
- if (ADDRESS_FUNCTION (dummy) > addr)
- stack_dir = 1; /* Stack grew upward. */
- else
- stack_dir = -1; /* Stack grew downward. */
- }
-}
-
-#endif /* STACK_DIRECTION == 0 */
-
-/* An "alloca header" is used to:
- (a) chain together all alloca'ed blocks;
- (b) keep track of stack depth.
-
- It is very important that sizeof(header) agree with malloc
- alignment chunk size. The following default should work okay. */
-
-#ifndef ALIGN_SIZE
-#define ALIGN_SIZE sizeof(double)
-#endif
-
-typedef union hdr
-{
- char align[ALIGN_SIZE]; /* To force sizeof(header). */
- struct
- {
- union hdr *next; /* For chaining headers. */
- char *deep; /* For stack depth measure. */
- } h;
-} header;
-
-static header *last_alloca_header = NULL; /* -> last alloca header. */
-
-/* Return a pointer to at least SIZE bytes of storage,
- which will be automatically reclaimed upon exit from
- the procedure that called alloca. Originally, this space
- was supposed to be taken from the current stack frame of the
- caller, but that method cannot be made to work for some
- implementations of C, for example under Gould's UTX/32. */
-
-pointer
-alloca (size)
- unsigned size;
-{
- auto char probe; /* Probes stack depth: */
- register char *depth = ADDRESS_FUNCTION (probe);
-
-#if STACK_DIRECTION == 0
- if (STACK_DIR == 0) /* Unknown growth direction. */
- find_stack_direction ();
-#endif
-
- /* Reclaim garbage, defined as all alloca'd storage that
- was allocated from deeper in the stack than currently. */
-
- {
- register header *hp; /* Traverses linked list. */
-
- for (hp = last_alloca_header; hp != NULL;)
- if ((STACK_DIR > 0 && hp->h.deep > depth)
- || (STACK_DIR < 0 && hp->h.deep < depth))
- {
- register header *np = hp->h.next;
-
- free ((pointer) hp); /* Collect garbage. */
-
- hp = np; /* -> next header. */
- }
- else
- break; /* Rest are not deeper. */
-
- last_alloca_header = hp; /* -> last valid storage. */
- }
-
- if (size == 0)
- return NULL; /* No allocation required. */
-
- /* Allocate combined header + user data storage. */
-
- {
- register pointer new = malloc (sizeof (header) + size);
- /* Address of header. */
-
- ((header *) new)->h.next = last_alloca_header;
- ((header *) new)->h.deep = depth;
-
- last_alloca_header = (header *) new;
-
- /* User storage begins just after header. */
-
- return (pointer) ((char *) new + sizeof (header));
- }
-}
-
-#ifdef CRAY
-
-#ifdef DEBUG_I00AFUNC
-#include <stdio.h>
-#endif
-
-#ifndef CRAY_STACK
-#define CRAY_STACK
-#ifndef CRAY2
-/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
-struct stack_control_header
- {
- long shgrow:32; /* Number of times stack has grown. */
- long shaseg:32; /* Size of increments to stack. */
- long shhwm:32; /* High water mark of stack. */
- long shsize:32; /* Current size of stack (all segments). */
- };
-
-/* The stack segment linkage control information occurs at
- the high-address end of a stack segment. (The stack
- grows from low addresses to high addresses.) The initial
- part of the stack segment linkage control information is
- 0200 (octal) words. This provides for register storage
- for the routine which overflows the stack. */
-
-struct stack_segment_linkage
- {
- long ss[0200]; /* 0200 overflow words. */
- long sssize:32; /* Number of words in this segment. */
- long ssbase:32; /* Offset to stack base. */
- long:32;
- long sspseg:32; /* Offset to linkage control of previous
- segment of stack. */
- long:32;
- long sstcpt:32; /* Pointer to task common address block. */
- long sscsnm; /* Private control structure number for
- microtasking. */
- long ssusr1; /* Reserved for user. */
- long ssusr2; /* Reserved for user. */
- long sstpid; /* Process ID for pid based multi-tasking. */
- long ssgvup; /* Pointer to multitasking thread giveup. */
- long sscray[7]; /* Reserved for Cray Research. */
- long ssa0;
- long ssa1;
- long ssa2;
- long ssa3;
- long ssa4;
- long ssa5;
- long ssa6;
- long ssa7;
- long sss0;
- long sss1;
- long sss2;
- long sss3;
- long sss4;
- long sss5;
- long sss6;
- long sss7;
- };
-
-#else /* CRAY2 */
-/* The following structure defines the vector of words
- returned by the STKSTAT library routine. */
-struct stk_stat
- {
- long now; /* Current total stack size. */
- long maxc; /* Amount of contiguous space which would
- be required to satisfy the maximum
- stack demand to date. */
- long high_water; /* Stack high-water mark. */
- long overflows; /* Number of stack overflow ($STKOFEN) calls. */
- long hits; /* Number of internal buffer hits. */
- long extends; /* Number of block extensions. */
- long stko_mallocs; /* Block allocations by $STKOFEN. */
- long underflows; /* Number of stack underflow calls ($STKRETN). */
- long stko_free; /* Number of deallocations by $STKRETN. */
- long stkm_free; /* Number of deallocations by $STKMRET. */
- long segments; /* Current number of stack segments. */
- long maxs; /* Maximum number of stack segments so far. */
- long pad_size; /* Stack pad size. */
- long current_address; /* Current stack segment address. */
- long current_size; /* Current stack segment size. This
- number is actually corrupted by STKSTAT to
- include the fifteen word trailer area. */
- long initial_address; /* Address of initial segment. */
- long initial_size; /* Size of initial segment. */
- };
-
-/* The following structure describes the data structure which trails
- any stack segment. I think that the description in 'asdef' is
- out of date. I only describe the parts that I am sure about. */
-
-struct stk_trailer
- {
- long this_address; /* Address of this block. */
- long this_size; /* Size of this block (does not include
- this trailer). */
- long unknown2;
- long unknown3;
- long link; /* Address of trailer block of previous
- segment. */
- long unknown5;
- long unknown6;
- long unknown7;
- long unknown8;
- long unknown9;
- long unknown10;
- long unknown11;
- long unknown12;
- long unknown13;
- long unknown14;
- };
-
-#endif /* CRAY2 */
-#endif /* not CRAY_STACK */
-
-#ifdef CRAY2
-/* Determine a "stack measure" for an arbitrary ADDRESS.
- I doubt that "lint" will like this much. */
-
-static long
-i00afunc (long *address)
-{
- struct stk_stat status;
- struct stk_trailer *trailer;
- long *block, size;
- long result = 0;
-
- /* We want to iterate through all of the segments. The first
- step is to get the stack status structure. We could do this
- more quickly and more directly, perhaps, by referencing the
- $LM00 common block, but I know that this works. */
-
- STKSTAT (&status);
-
- /* Set up the iteration. */
-
- trailer = (struct stk_trailer *) (status.current_address
- + status.current_size
- - 15);
-
- /* There must be at least one stack segment. Therefore it is
- a fatal error if "trailer" is null. */
-
- if (trailer == 0)
- abort ();
-
- /* Discard segments that do not contain our argument address. */
-
- while (trailer != 0)
- {
- block = (long *) trailer->this_address;
- size = trailer->this_size;
- if (block == 0 || size == 0)
- abort ();
- trailer = (struct stk_trailer *) trailer->link;
- if ((block <= address) && (address < (block + size)))
- break;
- }
-
- /* Set the result to the offset in this segment and add the sizes
- of all predecessor segments. */
-
- result = address - block;
-
- if (trailer == 0)
- {
- return result;
- }
-
- do
- {
- if (trailer->this_size <= 0)
- abort ();
- result += trailer->this_size;
- trailer = (struct stk_trailer *) trailer->link;
- }
- while (trailer != 0);
-
- /* We are done. Note that if you present a bogus address (one
- not in any segment), you will get a different number back, formed
- from subtracting the address of the first block. This is probably
- not what you want. */
-
- return (result);
-}
-
-#else /* not CRAY2 */
-/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
- Determine the number of the cell within the stack,
- given the address of the cell. The purpose of this
- routine is to linearize, in some sense, stack addresses
- for alloca. */
-
-static long
-i00afunc (long address)
-{
- long stkl = 0;
-
- long size, pseg, this_segment, stack;
- long result = 0;
-
- struct stack_segment_linkage *ssptr;
-
- /* Register B67 contains the address of the end of the
- current stack segment. If you (as a subprogram) store
- your registers on the stack and find that you are past
- the contents of B67, you have overflowed the segment.
-
- B67 also points to the stack segment linkage control
- area, which is what we are really interested in. */
-
- stkl = CRAY_STACKSEG_END ();
- ssptr = (struct stack_segment_linkage *) stkl;
-
- /* If one subtracts 'size' from the end of the segment,
- one has the address of the first word of the segment.
-
- If this is not the first segment, 'pseg' will be
- nonzero. */
-
- pseg = ssptr->sspseg;
- size = ssptr->sssize;
-
- this_segment = stkl - size;
-
- /* It is possible that calling this routine itself caused
- a stack overflow. Discard stack segments which do not
- contain the target address. */
-
- while (!(this_segment <= address && address <= stkl))
- {
-#ifdef DEBUG_I00AFUNC
- fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
-#endif
- if (pseg == 0)
- break;
- stkl = stkl - pseg;
- ssptr = (struct stack_segment_linkage *) stkl;
- size = ssptr->sssize;
- pseg = ssptr->sspseg;
- this_segment = stkl - size;
- }
-
- result = address - this_segment;
-
- /* If you subtract pseg from the current end of the stack,
- you get the address of the previous stack segment's end.
- This seems a little convoluted to me, but I'll bet you save
- a cycle somewhere. */
-
- while (pseg != 0)
- {
-#ifdef DEBUG_I00AFUNC
- fprintf (stderr, "%011o %011o\n", pseg, size);
-#endif
- stkl = stkl - pseg;
- ssptr = (struct stack_segment_linkage *) stkl;
- size = ssptr->sssize;
- pseg = ssptr->sspseg;
- result += size;
- }
- return (result);
-}
-
-#endif /* not CRAY2 */
-#endif /* CRAY */
-
-#endif /* no alloca */
#endif
static void read_pattern_file ();
-static void skip_padding ();
+static void tape_skip_padding ();
static void defer_copyin ();
static void create_defered_links ();
static void create_final_defers ();
while (archive_format == arf_unknown)
{
- peeked_bytes = peek_in_buf (tmpbuf, in_des, 512);
+ peeked_bytes = tape_buffered_peek (tmpbuf, in_des, 512);
if (peeked_bytes < 6)
error (1, 0, "premature end of archive");
}
else
{
- copy_in_buf ((char *) tmpbuf, in_des, 1L);
+ tape_buffered_read ((char *) tmpbuf, in_des, 1L);
++bytes_skipped;
}
}
file_hdr->c_tar_linkname = NULL;
- copy_in_buf ((char *) file_hdr, in_des, 6L);
+ tape_buffered_read ((char *) file_hdr, in_des, 6L);
while (1)
{
if (append_flag)
}
bytes_skipped++;
bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5);
- copy_in_buf ((char *) file_hdr + 5, in_des, 1L);
+ tape_buffered_read ((char *) file_hdr + 5, in_des, 1L);
}
}
unsigned long dev;
unsigned long rdev;
- copy_in_buf (ascii_header, in_des, 70L);
+ tape_buffered_read (ascii_header, in_des, 70L);
ascii_header[70] = '\0';
sscanf (ascii_header,
"%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo",
if (file_hdr->c_name != NULL)
free (file_hdr->c_name);
file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize + 1);
- copy_in_buf (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
+ tape_buffered_read (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
#ifndef __MSDOS__
/* HP/UX cpio creates archives that look just like ordinary archives,
but for devices it sets major = 0, minor = 1, and puts the
{
char ascii_header[112];
- copy_in_buf (ascii_header, in_des, 104L);
+ tape_buffered_read (ascii_header, in_des, 104L);
ascii_header[104] = '\0';
sscanf (ascii_header,
"%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
if (file_hdr->c_name != NULL)
free (file_hdr->c_name);
file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize);
- copy_in_buf (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
+ tape_buffered_read (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
/* In SVR4 ASCII format, the amount of space allocated for the header
is rounded up to the next long-word, so we might need to drop
1-3 bytes. */
- skip_padding (in_des, file_hdr->c_namesize + 110);
+ tape_skip_padding (in_des, file_hdr->c_namesize + 110);
}
/* Fill in FILE_HDR by reading a binary format cpio header from
it into the argument long header. */
short_hdr.c_dev = ((struct old_cpio_header *) file_hdr)->c_dev;
short_hdr.c_ino = ((struct old_cpio_header *) file_hdr)->c_ino;
- copy_in_buf (((char *) &short_hdr) + 6, in_des, 20L);
+ tape_buffered_read (((char *) &short_hdr) + 6, in_des, 20L);
/* If the magic number is byte swapped, fix the header. */
if (file_hdr->c_magic == swab_short ((unsigned short) 070707))
if (file_hdr->c_name != NULL)
free (file_hdr->c_name);
file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize);
- copy_in_buf (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
+ tape_buffered_read (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
/* In binary mode, the amount of space allocated in the header for
the filename is `c_namesize' rounded up to the next short-word,
so we might need to drop a byte. */
if (file_hdr->c_namesize % 2)
- toss_input (in_des, 1L);
+ tape_toss_input (in_des, 1L);
#ifndef __MSDOS__
/* HP/UX cpio creates archives that look just like ordinary archives,
dynamic_string new_name; /* New file name for rename option. */
FILE *tty_in; /* Interactive file for rename option. */
FILE *tty_out; /* Interactive file for rename option. */
+ FILE *rename_in; /* Batch file for rename option. */
char *str_res; /* Result for string function. */
struct utimbuf times; /* For setting file times. */
struct stat file_stat; /* Output file stat record. */
/* Initialize this in case it has members we don't know to set. */
bzero (×, sizeof (struct utimbuf));
- /* Open interactive file pair for rename operation. */
- if (rename_flag)
+ if (rename_batch_file)
{
+ rename_in = fopen (rename_batch_file, "r");
+ if (rename_in == NULL)
+ error (2, errno, CONSOLE);
+ }
+ else if (rename_flag)
+ {
+ /* Open interactive file pair for rename operation. */
tty_in = fopen (CONSOLE, "r");
if (tty_in == NULL)
error (2, errno, CONSOLE);
break;
}
+ /* Do we have to ignore absolute paths, and if so, does the filename
+ have an absolute path? */
+ if (no_abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0] == '/')
+ {
+ char *p;
+
+ p = file_hdr.c_name;
+ while (*p == '/')
+ ++p;
+ if (*p == '\0')
+ {
+ strcpy (file_hdr.c_name, ".");
+ }
+ else
+ {
+ char *non_abs_name;
+
+ non_abs_name = (char *) xmalloc (strlen (p) + 1);
+ strcpy (non_abs_name, p);
+ free (file_hdr.c_name);
+ file_hdr.c_name = non_abs_name;
+ }
+ }
+
/* Does the file name match one of the given patterns? */
if (num_patterns <= 0)
skip_file = FALSE;
if (skip_file)
{
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
}
else if (table_flag)
{
{
link_name = (char *) xmalloc ((unsigned int) file_hdr.c_filesize + 1);
link_name[file_hdr.c_filesize] = '\0';
- copy_in_buf (link_name, in_file_des, file_hdr.c_filesize);
+ tape_buffered_read (link_name, in_file_des, file_hdr.c_filesize);
long_format (&file_hdr, link_name);
free (link_name);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
continue;
}
else
else
printf ("%s\n", file_hdr.c_name);
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ crc = 0;
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ if (only_verify_crc_flag)
+ {
+#ifdef CP_IFLNK
+ if ((file_hdr.c_mode & CP_IFMT) == CP_IFLNK)
+ continue; /* links don't have a checksum */
+#endif
+ if (crc != file_hdr.c_chksum)
+ error (0, 0, "%s: checksum error (0x%x, should be 0x%x)",
+ file_hdr.c_name, crc, file_hdr.c_chksum);
+ }
}
else if (append_flag)
{
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ }
+ else if (only_verify_crc_flag)
+ {
+#ifdef CP_IFLNK
+ if ((file_hdr.c_mode & CP_IFMT) == CP_IFLNK)
+ {
+ if (archive_format != arf_tar && archive_format != arf_ustar)
+ {
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ continue;
+ }
+ }
+#endif
+ crc = 0;
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ if (crc != file_hdr.c_chksum)
+ error (0, 0, "%s: checksum error (0x%x, should be 0x%x)",
+ file_hdr.c_name, crc, file_hdr.c_chksum);
}
else
{
/* Copy the input file into the directory structure. */
/* Do we need to rename the file? */
- if (rename_flag)
+ if (rename_flag || rename_batch_file)
{
- fprintf (tty_out, "rename %s -> ", file_hdr.c_name);
- fflush (tty_out);
- str_res = ds_fgets (tty_in, &new_name);
+ if (rename_flag)
+ {
+ fprintf (tty_out, "rename %s -> ", file_hdr.c_name);
+ fflush (tty_out);
+ str_res = ds_fgets (tty_in, &new_name);
+ }
+ else
+ {
+ str_res = ds_fgetstr (rename_in, &new_name, '\n');
+ }
if (str_res == NULL || str_res[0] == 0)
{
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
continue;
}
else
{
error (0, 0, "%s not created: newer or same age version exists",
file_hdr.c_name);
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
continue; /* Go to the next file. */
}
else if (S_ISDIR (file_stat.st_mode)
{
error (0, errno, "cannot remove current %s",
file_hdr.c_name);
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
continue; /* Go to the next file. */
}
}
running as root), but there's nothing we can do about
that. */
defer_copyin (&file_hdr);
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
break;
}
/* If the file has data (filesize != 0), then presumably
file_hdr.c_ino);
if (link_res == 0)
{
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
break;
}
}
file_hdr.c_ino);
if (link_res == 0)
{
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
break;
}
}
if (out_file_des < 0)
{
error (0, errno, "%s", file_hdr.c_name);
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
continue;
}
error (0, 0, "cannot swap bytes of %s: odd number of bytes",
file_hdr.c_name);
}
- copy_files (in_file_des, out_file_des, file_hdr.c_filesize);
- empty_output_buffer (out_file_des);
+ copy_files_tape_to_disk (in_file_des, out_file_des, file_hdr.c_filesize);
+ disk_empty_output_buffer (out_file_des);
if (close (out_file_des) < 0)
error (0, errno, "%s", file_hdr.c_name);
if (utime (file_hdr.c_name, ×) < 0)
error (0, errno, "%s", file_hdr.c_name);
}
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
if (file_hdr.c_nlink > 1 && (archive_format == arf_newascii
|| archive_format == arf_crcascii) )
{
}
if (res < 0)
{
- error (0, errno, "%s", file_hdr.c_name);
- continue;
+ /* In some odd cases where the file_hdr.c_name includes `.',
+ the directory may have actually been created by
+ create_all_directories(), so the mkdir will fail
+ because the directory exists. If that's the case,
+ don't complain about it. */
+ if ( (errno != EEXIST) ||
+ (lstat (file_hdr.c_name, &file_stat) != 0) ||
+ !(S_ISDIR (file_stat.st_mode) ) )
+ {
+ error (0, errno, "%s", file_hdr.c_name);
+ continue;
+ }
}
if (!no_chown_flag)
if ((chown (file_hdr.c_name,
{
link_name = (char *) xmalloc ((unsigned int) file_hdr.c_filesize + 1);
link_name[file_hdr.c_filesize] = '\0';
- copy_in_buf (link_name, in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_buffered_read (link_name, in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
}
else
{
default:
error (0, 0, "%s: unknown file type", file_hdr.c_name);
- toss_input (in_file_des, file_hdr.c_filesize);
- skip_padding (in_file_des, file_hdr.c_filesize);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
}
if (verbose_flag)
if (archive_format == arf_newascii || archive_format == arf_crcascii)
create_final_defers ();
- res = (input_bytes + io_block_size - 1) / io_block_size;
- if (res == 1)
- fprintf (stderr, "1 block\n");
- else
- fprintf (stderr, "%d blocks\n", res);
+ if (!quiet_flag)
+ {
+ res = (input_bytes + io_block_size - 1) / io_block_size;
+ if (res == 1)
+ fprintf (stderr, "1 block\n");
+ else
+ fprintf (stderr, "%d blocks\n", res);
+ }
}
\f
/* Print the file described by FILE_HDR in long format.
{
register unsigned char c;
- while (c = *p++)
+ while ( (c = *p++) )
{
switch (c)
{
header type. */
static void
-skip_padding (in_file_des, offset)
+tape_skip_padding (in_file_des, offset)
int in_file_des;
int offset;
{
pad = 0;
if (pad != 0)
- toss_input (in_file_des, pad);
+ tape_toss_input (in_file_des, pad);
}
create_final_defers ()
{
struct deferment *d;
- struct deferment *d_prev;
- struct new_cpio_header *h;
int link_res;
int out_file_des;
struct utimbuf times; /* For setting file times. */
#include "rmt.h"
static unsigned long read_for_checksum ();
-static void clear_rest_of_block ();
-static void pad_output ();
+static void tape_clear_rest_of_block ();
+static void tape_pad_output ();
static int last_link ();
static int count_defered_links_to_dev_ino ();
static void add_link_defer ();
file_hdr->c_filesize, file_hdr->c_dev_maj, file_hdr->c_dev_min,
file_hdr->c_rdev_maj, file_hdr->c_rdev_min, file_hdr->c_namesize,
file_hdr->c_chksum);
- copy_buf_out (ascii_header, out_des, 110L);
+ tape_buffered_write (ascii_header, out_des, 110L);
/* Write file name to output. */
- copy_buf_out (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
- pad_output (out_des, file_hdr->c_namesize + 110);
+ tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
+ tape_pad_output (out_des, file_hdr->c_namesize + 110);
}
else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
{
error (0, 0, "%s: truncating inode number", file_hdr->c_name);
sprintf (ascii_header,
- "%06lo%06lo%06lo%06lo%06lo%06lo%06lo%06lo%011lo%06lo%011lo",
+ "%06o%06o%06lo%06lo%06lo%06lo%06lo%06o%011lo%06lo%011lo",
file_hdr->c_magic & 0xFFFF, dev & 0xFFFF,
file_hdr->c_ino & 0xFFFF, file_hdr->c_mode & 0xFFFF,
file_hdr->c_uid & 0xFFFF, file_hdr->c_gid & 0xFFFF,
file_hdr->c_nlink & 0xFFFF, rdev & 0xFFFF,
file_hdr->c_mtime, file_hdr->c_namesize & 0xFFFF,
file_hdr->c_filesize);
- copy_buf_out (ascii_header, out_des, 76L);
+ tape_buffered_write (ascii_header, out_des, 76L);
/* Write file name to output. */
- copy_buf_out (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
+ tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
}
else if (archive_format == arf_tar || archive_format == arf_ustar)
{
short_hdr.c_filesizes[1] = file_hdr->c_filesize & 0xFFFF;
/* Output the file header. */
- copy_buf_out ((char *) &short_hdr, out_des, 26L);
+ tape_buffered_write ((char *) &short_hdr, out_des, 26L);
/* Write file name to output. */
- copy_buf_out (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
+ tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
- pad_output (out_des, file_hdr->c_namesize + 26);
+ tape_pad_output (out_des, file_hdr->c_namesize + 26);
}
}
input_name.ds_string);
write_out_header (&file_hdr, out_file_des);
- copy_files (in_file_des, out_file_des, file_hdr.c_filesize);
+ copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize, input_name.ds_string);
#ifndef __MSDOS__
if (archive_format == arf_tar || archive_format == arf_ustar)
file_hdr.c_dev_min);
#endif
- pad_output (out_file_des, file_hdr.c_filesize);
+ tape_pad_output (out_file_des, file_hdr.c_filesize);
if (close (in_file_des) < 0)
error (0, errno, "%s", input_name.ds_string);
case CP_IFLNK:
{
char *link_name = (char *) xmalloc (file_stat.st_size + 1);
+ int link_size;
- if (readlink (input_name.ds_string, link_name,
- file_stat.st_size) < 0)
+ link_size = readlink (input_name.ds_string, link_name,
+ file_stat.st_size);
+ if (link_size < 0)
{
error (0, errno, "%s", input_name.ds_string);
free (link_name);
continue;
}
+ file_hdr.c_filesize = link_size;
if (archive_format == arf_tar || archive_format == arf_ustar)
{
- if (file_stat.st_size + 1 > 100)
+ if (link_size + 1 > 100)
{
error (0, 0, "%s: symbolic link too long",
file_hdr.c_name);
}
else
{
- link_name[file_stat.st_size] = '\0';
+ link_name[link_size] = '\0';
file_hdr.c_tar_linkname = link_name;
write_out_header (&file_hdr, out_file_des);
}
else
{
write_out_header (&file_hdr, out_file_des);
- copy_buf_out (link_name, out_file_des, file_stat.st_size);
- pad_output (out_file_des, file_hdr.c_filesize);
+ tape_buffered_write (link_name, out_file_des, link_size);
+ tape_pad_output (out_file_des, link_size);
}
free (link_name);
}
write_out_header (&file_hdr, out_file_des);
else
{
- copy_buf_out (zeros_512, out_file_des, 512);
- copy_buf_out (zeros_512, out_file_des, 512);
+ tape_buffered_write (zeros_512, out_file_des, 512);
+ tape_buffered_write (zeros_512, out_file_des, 512);
}
/* Fill up the output block. */
- clear_rest_of_block (out_file_des);
- empty_output_buffer (out_file_des);
+ tape_clear_rest_of_block (out_file_des);
+ tape_empty_output_buffer (out_file_des);
if (dot_flag)
fputc ('\n', stderr);
- res = (output_bytes + io_block_size - 1) / io_block_size;
- if (res == 1)
- fprintf (stderr, "1 block\n");
- else
- fprintf (stderr, "%d blocks\n", res);
+ if (!quiet_flag)
+ {
+ res = (output_bytes + io_block_size - 1) / io_block_size;
+ if (res == 1)
+ fprintf (stderr, "1 block\n");
+ else
+ fprintf (stderr, "%d blocks\n", res);
+ }
}
/* Read FILE_SIZE bytes of FILE_NAME from IN_FILE_DES and
OUT_FILE_DES. */
static void
-clear_rest_of_block (out_file_des)
+tape_clear_rest_of_block (out_file_des)
int out_file_des;
{
while (output_size < io_block_size)
{
if ((io_block_size - output_size) > 512)
- copy_buf_out (zeros_512, out_file_des, 512);
+ tape_buffered_write (zeros_512, out_file_des, 512);
else
- copy_buf_out (zeros_512, out_file_des, io_block_size - output_size);
+ tape_buffered_write (zeros_512, out_file_des, io_block_size - output_size);
}
}
to the end of the header. */
static void
-pad_output (out_file_des, offset)
+tape_pad_output (out_file_des, offset)
int out_file_des;
int offset;
{
pad = 0;
if (pad != 0)
- copy_buf_out (zeros_512, out_file_des, pad);
+ tape_buffered_write (zeros_512, out_file_des, pad);
}
int ino;
int maj;
int min;
- int count;
ino = file_hdr->c_ino;
maj = file_hdr->c_dev_maj;
min = file_hdr->c_dev_min;
static void
writeout_defered_file (header, out_file_des)
struct new_cpio_header *header;
+ int out_file_des;
{
int in_file_des;
struct new_cpio_header file_hdr;
header->c_name);
write_out_header (&file_hdr, out_file_des);
- copy_files (in_file_des, out_file_des, file_hdr.c_filesize);
+ copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize, header->c_name);
#ifndef __MSDOS__
if (archive_format == arf_tar || archive_format == arf_ustar)
file_hdr.c_dev_min);
#endif
- pad_output (out_file_des, file_hdr.c_filesize);
+ tape_pad_output (out_file_des, file_hdr.c_filesize);
if (close (in_file_des) < 0)
error (0, errno, "%s", header->c_name);
continue;
}
- copy_files (in_file_des, out_file_des, in_file_stat.st_size);
- empty_output_buffer (out_file_des);
+ copy_files_disk_to_disk (in_file_des, out_file_des, in_file_stat.st_size, input_name.ds_string);
+ disk_empty_output_buffer (out_file_des);
if (close (in_file_des) < 0)
error (0, errno, "%s", input_name.ds_string);
if (close (out_file_des) < 0)
}
if (res < 0)
{
- error (0, errno, "%s", output_name.ds_string);
- continue;
+ /* In some odd cases where the output_name includes `.',
+ the directory may have actually been created by
+ create_all_directories(), so the mkdir will fail
+ because the directory exists. If that's the case,
+ don't complain about it. */
+ if ( (errno != EEXIST) ||
+ (lstat (output_name.ds_string, &out_file_stat) != 0) ||
+ !(S_ISDIR (out_file_stat.st_mode) ) )
+ {
+ error (0, errno, "%s", output_name.ds_string);
+ continue;
+ }
}
if (!no_chown_flag)
if ((chown (output_name.ds_string,
else if (S_ISLNK (in_file_stat.st_mode))
{
char *link_name;
+ int link_size;
link_name = (char *) xmalloc ((unsigned int) in_file_stat.st_size + 1);
- if (readlink (input_name.ds_string, link_name,
- in_file_stat.st_size) < 0)
+ link_size = readlink (input_name.ds_string, link_name,
+ in_file_stat.st_size);
+ if (link_size < 0)
{
error (0, errno, "%s", input_name.ds_string);
free (link_name);
continue;
}
- link_name[in_file_stat.st_size] = '\0';
+ link_name[link_size] = '\0';
res = UMASKED_SYMLINK (link_name, output_name.ds_string,
in_file_stat.st_mode);
if (dot_flag)
fputc ('\n', stderr);
- res = (output_bytes + io_block_size - 1) / io_block_size;
- if (res == 1)
- fprintf (stderr, "1 block\n");
- else
- fprintf (stderr, "%d blocks\n", res);
+ if (!quiet_flag)
+ {
+ res = (output_bytes + io_block_size - 1) / io_block_size;
+ if (res == 1)
+ fprintf (stderr, "1 block\n");
+ else
+ fprintf (stderr, "%d blocks\n", res);
+ }
}
\f
/* Try and create a hard link from FILE_NAME to another file
[\-O [[user@]host:]archive] [\-F [[user@]host:]archive]
[\-\-file=[[user@]host:]archive] [\-\-format=format] [\-\-message=message]
[\-\-null] [\-\-reset-access-time] [\-\-verbose] [\-\-dot] [\-\-append]
-[\-\-block-size=blocks] [\-\-dereference] [\-\-io-size=bytes]
-[\-\-help] [\-\-version] < name-list [> archive]
+[\-\-block-size=blocks] [\-\-dereference] [\-\-io-size=bytes] [\-\-quiet]
+[\-\-force\-local] [\-\-help] [\-\-version] < name-list [> archive]
.B cpio
{\-i|\-\-extract} [\-bcdfmnrtsuvBSV] [\-C bytes] [\-E file] [\-H format]
[\-\-unconditional] [\-\-verbose] [\-\-block-size=blocks] [\-\-swap-halfwords]
[\-\-io-size=bytes] [\-\-pattern-file=file] [\-\-format=format]
[\-\-owner=[user][:.][group]] [\-\-no-preserve-owner] [\-\-message=message]
-[\-\-help] [\-\-version] [pattern...] [< archive]
+[\-\-force\-local] [\-\-no\-absolute\-filenames] [\-\-sparse] [\-\-only\-verify\-crc]
+[\-\-quiet] [\-\-help] [\-\-version] [pattern...] [< archive]
.B cpio
{\-p|\-\-pass-through} [\-0adlmuvLV] [\-R [user][:.][group]]
-[\-\-null] [\-\-reset-access-time] [\-\-make-directories] [\-\-link]
+[\-\-null] [\-\-reset-access-time] [\-\-make-directories] [\-\-link] [\-\-quiet]
[\-\-preserve-modification-time] [\-\-unconditional] [\-\-verbose] [\-\-dot]
[\-\-dereference] [\-\-owner=[user][:.][group]] [\-\-no-preserve-owner]
-[\-\-help] [\-\-version] destination-directory < name-list
+[\-\-sparse] [\-\-help] [\-\-version] destination-directory < name-list
.SH DESCRIPTION
This manual page
documents the GNU version of
.B cpio
copies files into or out of a cpio or tar archive, which is a file that
contains other files plus information about them, such as their
-pathname, owner, timestamps, and access permissions. The archive can
+file name, owner, timestamps, and access permissions. The archive can
be another file on the disk, a magnetic tape, or a pipe.
.B cpio
has three operating modes.
In the verbose table of contents listing, show numeric UID and GID
instead of translating them into names.
.TP
+.I " \-\-no-absolute-filenames"
+In copy-in mode, create all files relative to the current directory,
+even if they have an absolute file name in the archive.
+.TP
.I " \-\-no-preserve-owner"
In copy-in mode and copy-pass mode, do not change the ownership of the
files; leave them owned by the user extracting them. This is the
Run in copy-out mode.
.TP
.I "\-O archive"
-Archive filename to use instead of standard output. To use a
-tape drive on another machine as the archive, use a filename that
-starts with `HOSTNAME:'. The hostname can be preceded by a
-username and an `@' to access the remote tape drive as that user, if
-you have permission to do so (typically an entry in that user's
-`~/.rhosts' file).
+Archive filename to use instead of standard output. To use a tape
+drive on another machine as the archive, use a filename that starts
+with `HOSTNAME:'. The hostname can be preceded by a username and an
+`@' to access the remote tape drive as that user, if you have
+permission to do so (typically an entry in that user's `~/.rhosts'
+file).
+.TP
+.I " \-\-only-verify-crc"
+When reading a CRC format archive in copy-in mode, only verify the
+CRC's of each file in the archive, don't actually extract the files.
.TP
.I "\-p, \-\-pass-through"
Run in copy-pass mode.
.TP
+.I "\-\-quiet"
+Do not print the number of blocks copied.
+.TP
.I "\-r, \-\-rename"
Interactively rename files.
.TP
.I "\-R [user][:.][group], \-\-owner [user][:.][group]"
-In copy-out and copy-pass modes, set the ownership of all files
-created to the specified user and/or group. Either the user or the
-group, or both, must be present. If the group is omitted but the ":"
-or "." separator is given, use the given user's login group. Only the
+In copy-out and copy-pass modes, set the ownership of all files created
+to the specified user and/or group. Either the user or the group, or
+both, must be present. If the group is omitted but the ":" or "."
+separator is given, use the given user's login group. Only the
super-user can change files' ownership.
.TP
+.I "\-\-sparse"
+In copy-out and copy-pass modes, write files with large blocks of zeros
+as sparse files.
+.TP
.I "\-s, \-\-swap-bytes"
-In copy-in mode, swap the bytes of each halfword (pair of bytes) in
-the files.
+In copy-in mode, swap the bytes of each halfword (pair of bytes) in the
+files.
.TP
.I "\-S, \-\-swap-halfwords"
In copy-in mode, swap the halfwords of each word (4 bytes) in the
--- /dev/null
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename cpio.info
+@settitle cpio
+@setchapternewpage off
+@set VERSION GNU cpio 2.4
+@set RELEASEDATE November 1995
+@c %**end of header
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* cpio: (cpio). Making tape (or disk) archives.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
+This file documents @value{VERSION}.
+
+Copyright (C) 1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+
+@titlepage
+@title GNU CPIO
+@subtitle @value{VERSION} @value{RELEASEDATE}
+@author by Robert Carleton
+@c copyright page
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1995 Free Software Foundation, Inc.
+@sp 2
+This is the first edition of the GNU cpio documentation,@*
+and is consistent with @value{VERSION}.@*
+@sp 2
+Published by the Free Software Foundation @*
+59 Temple Place - Suite 330, @*
+Boston, MA 02111-1307, USA @*
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by the Free Software Foundation.
+@end titlepage
+
+@ifinfo
+@node Top, Introduction, (dir), (dir)
+@comment node-name, next, previous, up
+@top
+
+GNU cpio is a tool for creating and extracting archives, or copying
+files from one place to another. It handles a number of cpio formats as
+well as reading and writing tar files. This is the first edition of the
+GNU cpio documentation and is consistant with @value{VERSION}.
+
+@menu
+* Introduction::
+* Tutorial:: Getting started.
+* Invoking `cpio':: How to invoke `cpio'.
+* Media:: Using tapes and other archive media.
+* Concept Index:: Concept index.
+
+ --- The Detailed Node Listing ---
+
+Invoking cpio
+
+* Copy-out mode::
+* Copy-in mode::
+* Copy-pass mode::
+* Options::
+@end menu
+
+@end ifinfo
+
+@node Introduction, Tutorial, Top, Top
+@comment node-name, next, previous, up
+@chapter Introduction
+
+GNU cpio copies files into or out of a cpio or tar archive, The archive
+can be another file on the disk, a magnetic tape, or a pipe.
+
+GNU cpio supports the following archive formats: binary, old ASCII, new
+ASCII, crc, HPUX binary, HPUX old ASCII, old tar, and POSIX.1 tar. The
+tar format is provided for compatability with the tar program. By
+default, cpio creates binary format archives, for compatibility with
+older cpio programs. When extracting from archives, cpio automatically
+recognizes which kind of archive it is reading and can read archives
+created on machines with a different byte-order.
+
+@node Tutorial, Invoking `cpio', Introduction, Top
+@comment node-name, next, previous, up
+@chapter Tutorial
+@cindex creating a cpio archive
+@cindex extracting a cpio archive
+@cindex copying directory structures
+@cindex passing directory structures
+
+
+GNU cpio performs three primary functions. Copying files to an
+archive, Extracting files from an archive, and passing files to another
+directory tree. An archive can be a file on disk, one or more floppy
+disks, or one or more tapes.
+
+When creating an archive, cpio takes the list of files to be processed
+from the standard input, and then sends the archive to the standard
+output, or to the device defined by the @samp{-F} option.
+@xref{Copy-out mode}. Usually find or ls is used to provide this list
+to the standard input. In the following example you can see the
+possibilities for archiving the contents of a single directory.
+
+
+@example
+@cartouche
+% ls | cpio -ov > directory.cpio
+@end cartouche
+@end example
+
+The @samp{-o} option creates the archive, and the @samp{-v} option
+prints the names of the files archived as they are added. Notice that
+the options can be put together after a single @samp{-} or can be placed
+separately on the command line. The @samp{>} redirects the cpio output
+to the file @samp{directory.cpio}.
+
+
+If you wanted to archive an entire directory tree, the find command can
+provide the file list to cpio:
+
+
+@example
+@cartouche
+% find . -print -depth | cpio -ov > tree.cpio
+@end cartouche
+@end example
+
+
+This will take all the files in the current directory, the directories
+below and place them in the archive tree.cpio. Again the @samp{-o}
+creates an archive, and the @samp{-v} option shows you the name of the
+files as they are archived. @xref{Copy-out mode}. Using the `.' in the
+find statement will give you more flexibility when doing restores, as it
+will save file names with a relative path vice a hard wired, absolute
+path. The @samp{-depth} option forces @samp{find} to print of the
+entries in a directory before printing the directory itself. This
+limits the effects of restrictive directory permissions by printing the
+directory entries in a directory before the directory name itself.
+
+
+
+
+Extracting an archive requires a bit more thought because cpio will not
+create directories by default. Another characteristic, is it will not
+overwrite existing files unless you tell it to.
+
+
+@example
+@cartouche
+% cpio -iv < directory.cpio
+@end cartouche
+@end example
+
+This will retrieve the files archived in the file directory.cpio and
+place them in the present directory. The @samp{-i} option extracts the
+archive and the @samp{-v} shows the file names as they are extracted.
+If you are dealing with an archived directory tree, you need to use the
+@samp{-d} option to create directories as necessary, something like:
+
+@example
+@cartouche
+% cpio -idv < tree.cpio
+@end cartouche
+@end example
+
+This will take the contents of the archive tree.cpio and extract it to
+the current directory. If you try to extract the files on top of files
+of the same name that already exist (and have the same or later
+modification time) cpio will not extract the file unless told to do so
+by the -u option. @xref{Copy-in mode}.
+
+
+In copy-pass mode, cpio copies files from one directory tree to another,
+combining the copy-out and copy-in steps without actually using an
+archive. It reads the list of files to copy from the standard input;
+the directory into which it will copy them is given as a non-option
+argument. @xref{Copy-pass mode}.
+
+@example
+@cartouche
+% find . -depth -print0 | cpio --null -pvd new-dir
+@end cartouche
+@end example
+
+
+The example shows copying the files of the present directory, and
+sub-directories to a new directory called new-dir. Some new options are
+the @samp{-print0} available with GNU find, combined with the
+@samp{--null} option of cpio. These two options act together to send
+file names between find and cpio, even if special characters are
+embedded in the file names. Another is @samp{-p}, which tells cpio to
+pass the files it finds to the directory @samp{new-dir}.
+
+@node Invoking `cpio', Media, Tutorial, Top
+@comment node-name, next, previous, up
+@chapter Invoking cpio
+@cindex invoking cpio
+@cindex command line options
+
+@menu
+* Copy-out mode::
+* Copy-in mode::
+* Copy-pass mode::
+* Options::
+@end menu
+
+@node Copy-out mode, Copy-in mode, Invoking `cpio', Invoking `cpio'
+@comment node-name, next, previous, up
+@section Copy-out mode
+
+In copy-out mode, cpio copies files into an archive. It reads a list
+of filenames, one per line, on the standard input, and writes the
+archive onto the standard output. A typical way to generate the list
+of filenames is with the find command; you should give find the -depth
+option to minimize problems with permissions on directories that are
+unreadable.
+@xref{Options}.
+
+@example
+cpio @{-o|--create@} [-0acvABLV] [-C bytes] [-H format]
+[-M message] [-O [[user@@]host:]archive] [-F [[user@@]host:]archive]
+[--file=[[user@@]host:]archive] [--format=format] [--sparse]
+[--message=message][--null] [--reset-access-time] [--verbose]
+[--dot] [--append] [--block-size=blocks] [--dereference]
+[--io-size=bytes] [--help] [--version] < name-list [> archive]
+@end example
+
+@node Copy-in mode, Copy-pass mode, Copy-out mode, Invoking `cpio'
+@comment node-name, next, previous, up
+@section Copy-in mode
+
+In copy-in mode, cpio copies files out of an archive or lists the
+archive contents. It reads the archive from the standard input. Any
+non-option command line arguments are shell globbing patterns; only
+files in the archive whose names match one or more of those patterns are
+copied from the archive. Unlike in the shell, an initial `.' in a
+filename does match a wildcard at the start of a pattern, and a `/' in a
+filename can match wildcards. If no patterns are given, all files are
+extracted. @xref{Options}.
+
+@example
+cpio @{-i|--extract@} [-bcdfmnrtsuvBSV] [-C bytes] [-E file]
+[-H format] [-M message] [-R [user][:.][group]]
+[-I [[user@@]host:]archive] [-F [[user@@]host:]archive]
+[--file=[[user@@]host:]archive] [--make-directories]
+[--nonmatching] [--preserve-modification-time]
+[--numeric-uid-gid] [--rename] [--list] [--swap-bytes] [--swap]
+[--dot] [--unconditional] [--verbose] [--block-size=blocks]
+[--swap-halfwords] [--io-size=bytes] [--pattern-file=file]
+[--format=format] [--owner=[user][:.][group]]
+[--no- preserve-owner] [--message=message] [--help] [--version]
+[-no-abosolute-filenames] [-only-verify-crc] [-quiet]
+[pattern...] [< archive]
+@end example
+
+@node Copy-pass mode, Options, Copy-in mode, Invoking `cpio'
+@comment node-name, next, previous, up
+@section Copy-pass mode
+
+In copy-pass mode, cpio copies files from one directory tree to
+another, combining the copy-out and copy-in steps without actually
+using an archive. It reads the list of files to copy from the
+standard input; the directory into which it will copy them is given as
+a non-option argument.
+@xref{Options}.
+
+@example
+cpio @{-p|--pass-through@} [-0adlmuvLV] [-R [user][:.][group]]
+[--null] [--reset-access-time] [--make-directories] [--link]
+[--preserve-modification-time] [--unconditional] [--verbose]
+[--dot] [--dereference] [--owner=[user][:.][group]] [--sparse]
+[--no-preserve-owner] [--help] [--version] destination-directory
+< name-list
+@end example
+
+
+
+@node Options, , Copy-pass mode, Invoking `cpio'
+@comment node-name, next, previous, up
+@section Options
+
+
+@table @code
+
+
+@item -0, --null
+Read a list of filenames terminated by a null character, instead of a
+newline, so that files whose names contain newlines can be archived.
+GNU find is one way to produce a list of null-terminated filenames.
+This option may be used in copy-out and copy-pass modes.
+
+@item -a, --reset-access-time
+Reset the access times of files after reading them, so
+that it does not look like they have just been read.
+
+@item -A, --append
+Append to an existing archive. Only works in copy-out
+mode. The archive must be a disk file specified with
+the -O or -F (--file) option.
+
+@item -b, --swap
+Swap both halfwords of words and bytes of halfwords in the data.
+Equivalent to -sS. This option may be used in copy-in mode. Use this
+option to convert 32-bit integers between big-endian and little-endian
+machines.
+
+@item -B
+Set the I/O block size to 5120 bytes. Initially the
+block size is 512 bytes.
+
+@item --block-size=BLOCK-SIZE
+Set the I/O block size to BLOCK-SIZE * 512 bytes.
+
+@item -c
+Use the old portable (ASCII) archive format.
+
+@item -C IO-SIZE, --io-size=IO-SIZE
+Set the I/O block size to IO-SIZE bytes.
+
+@item -d, --make-directories
+Create leading directories where needed.
+
+@item -E FILE, --pattern-file=FILE
+Read additional patterns specifying filenames to extract or list from
+FILE. The lines of FILE are treated as if they had been non-option
+arguments to cpio. This option is used in copy-in mode,
+
+@item -f, --nonmatching
+Only copy files that do not match any of the given
+patterns.
+
+@item -F, --file=archive
+Archive filename to use instead of standard input or output. To use a
+tape drive on another machine as the archive, use a filename that starts
+with `HOSTNAME:'. The hostname can be preceded by a username and an
+`@@' to access the remote tape drive as that user, if you have
+permission to do so (typically an entry in that user's `~/.rhosts'
+file).
+
+@item --force-local
+With -F, -I, or -O, take the archive file name to be a
+local file even if it contains a colon, which would
+ordinarily indicate a remote host name.
+
+@item -H FORMAT, --format=FORMAT
+Use archive format FORMAT. The valid formats are listed below; the same
+names are also recognized in all-caps. The default in copy-in mode is
+to automatically detect the archive format, and in copy-out mode is
+@samp{bin}.
+
+@table @samp
+@item bin
+The obsolete binary format.
+
+@item odc
+The old (POSIX.1) portable format.
+
+@item newc
+The new (SVR4) portable format, which supports file systems having more
+than 65536 i-nodes.
+
+@item crc
+The new (SVR4) portable format with a checksum added.
+
+@item tar
+The old tar format.
+
+@item ustar
+The POSIX.1 tar format. Also recognizes GNU tar archives, which are
+similar but not identical.
+
+@item hpbin
+The obsolete binary format used by HPUX's cpio (which stores device
+files differently).
+
+@item hpodc
+The portable format used by HPUX's cpio (which stores device files
+differently).
+@end table
+
+@item -i, --extract
+Run in copy-in mode.
+@xref{Copy-in mode}.
+
+@item -I archive
+Archive filename to use instead of standard input. To use a tape drive
+on another machine as the archive, use a filename that starts with
+`HOSTNAME:'. The hostname can be preceded by a username and an `@@' to
+access the remote tape drive as that user, if you have permission to do
+so (typically an entry in that user's `~/.rhosts' file).
+
+@item -k
+Ignored; for compatibility with other versions of cpio.
+
+@item -l, --link
+Link files instead of copying them, when possible.
+
+@item -L, --dereference
+Copy the file that a symbolic link points to, rather than the symbolic
+link itself.
+
+@item -m, --preserve-modification-time
+Retain previous file modification times when creating files.
+
+@item -M MESSAGE, --message=MESSAGE
+Print MESSAGE when the end of a volume of the backup media (such as a
+tape or a floppy disk) is reached, to prompt the user to insert a new
+volume. If MESSAGE contains the string "%d", it is replaced by the
+current volume number (starting at 1).
+
+@item -n, --numeric-uid-gid
+Show numeric UID and GID instead of translating them into names when using the
+@samp{--verbose option}.
+
+@item --no-absolute-filenames
+Create all files relative to the current directory in copy-in mode, even
+if they have an absolute file name in the archive.
+
+@item --no-preserve-owner
+Do not change the ownership of the files; leave them owned by the user
+extracting them. This is the default for non-root users, so that users
+on System V don't inadvertantly give away files. This option can be
+used in copy-in mode and copy-pass mode
+
+@item -o, --create
+Run in copy-out mode.
+@xref{Copy-out mode}.
+
+@item -O archive
+Archive filename to use instead of standard output. To use a tape drive
+on another machine as the archive, use a filename that starts with
+`HOSTNAME:'. The hostname can be preceded by a username and an `@@' to
+access the remote tape drive as that user, if you have permission to do
+so (typically an entry in that user's `~/.rhosts' file).
+
+@item --only-verify-crc
+Verify the CRC's of each file in the archive, when reading a CRC format
+archive. Don't actually extract the files.
+
+@item -p, --pass-through
+Run in copy-pass mode.
+@xref{Copy-pass mode}.
+
+@item --quiet
+Do not print the number of blocks copied.
+
+@item -r, --rename
+Interactively rename files.
+
+@item -R [user][:.][group], --owner [user][:.][group]
+Set the ownership of all files created to the specified user and/or
+group in copy-out and copy-pass modes. Either the user, the group, or
+both, must be present. If the group is omitted but the ":" or "."
+separator is given, use the given user's login group. Only the
+super-user can change files' ownership.
+
+@item -s, --swap-bytes
+Swap the bytes of each halfword (pair of bytes) in the files.This option
+can be used in copy-in mode.
+
+@item -S, --swap-halfwords
+Swap the halfwords of each word (4 bytes) in the files. This option may
+be used in copy-in mode.
+
+@item --sparse
+Write files with large blocks of zeros as sparse files. This option is
+used in copy-out and copy-pass modes.
+
+@item -t, --list
+Print a table of contents of the input.
+
+@item -u, --unconditional
+Replace all files, without asking whether to replace
+existing newer files with older files.
+
+@item -v, --verbose
+List the files processed, or with @samp{-t}, give an @samp{ls -l} style
+table of contents listing. In a verbose table of contents of a ustar
+archive, user and group names in the archive that do not exist on the
+local system are replaced by the names that correspond locally to the
+numeric UID and GID stored in the archive.
+
+@item -V --dot
+Print a @kbd{.} for each file processed.
+
+@item --version
+Print the cpio program version number and exit.
+@end table
+
+
+@node Media, Concept Index, Invoking `cpio', Top
+@comment node-name, next, previous, up
+@chapter Magnetic Media
+@cindex magnetic media
+
+Archives are usually written on removable media--tape cartridges, mag
+tapes, or floppy disks.
+
+The amount of data a tape or disk holds depends not only on its size,
+but also on how it is formatted. A 2400 foot long reel of mag tape
+holds 40 megabytes of data when formated at 1600 bits per inch. The
+physically smaller EXABYTE tape cartridge holds 2.3 gigabytes.
+
+Magnetic media are re-usable--once the archive on a tape is no longer
+needed, the archive can be erased and the tape or disk used over. Media
+quality does deteriorate with use, however. Most tapes or disks should
+be disgarded when they begin to produce data errors.
+
+Magnetic media are written and erased using magnetic fields, and should
+be protected from such fields to avoid damage to stored data. Sticking
+a floppy disk to a filing cabinet using a magnet is probably not a good
+idea.
+
+
+@node Concept Index, , Media, Top
+@comment node-name, next, previous, up
+@unnumbered Concept Index
+@printindex cp
+@contents
+@bye
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#ifdef STDC_HEADERS
#include <stdlib.h>
#else
#endif
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
-#ifndef rindex
-#define rindex strrchr
-#endif
#else
#include <strings.h>
+#ifndef strrchr
+#define strrchr rindex
+#endif
#endif
/* Return the leading directories part of PATH,
char *slash;
int length; /* Length of result, not including NUL. */
- slash = rindex (path, '/');
+ slash = strrchr (path, '/');
if (slash == 0)
{
/* File is in the current directory. */
length = slash - path + 1;
}
- newpath = malloc (length + 1);
+ newpath = (char *) malloc (length + 1);
if (newpath == 0)
return 0;
strncpy (newpath, path, length);
/* error.c -- error handler for noninteractive utilities
- Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1990, 91, 92, 93, 94, 95 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* Written by David MacKenzie. */
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
-#include <stdio.h>
-
-#ifdef HAVE_VPRINTF
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
-#if __STDC__
-#include <stdarg.h>
-#define VA_START(args, lastarg) va_start(args, lastarg)
-#else /* !__STDC__ */
-#include <varargs.h>
-#define VA_START(args, lastarg) va_start(args)
-#endif /* !__STDC__ */
+#include <stdio.h>
-#else /* !HAVE_VPRINTF */
+#if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC
+# if __STDC__
+# include <stdarg.h>
+# define VA_START(args, lastarg) va_start(args, lastarg)
+# else
+# include <varargs.h>
+# define VA_START(args, lastarg) va_start(args)
+# endif
+#else
+# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
+# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
+#endif
+
+#if STDC_HEADERS || _LIBC
+# include <stdlib.h>
+# include <string.h>
+#else
+void exit ();
+#endif
-#ifdef HAVE_DOPRNT
-#define va_alist args
-#define va_dcl int args;
-#else /* !HAVE_DOPRNT */
-#define va_alist a1, a2, a3, a4, a5, a6, a7, a8
-#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
-#endif /* !HAVE_DOPRNT */
+/* This variable is incremented each time `error' is called. */
+unsigned int error_message_count;
-#endif /* !HAVE_VPRINTF */
+/* If NULL, error will flush stdout, then print on stderr the program
+ name, a colon and a space. Otherwise, error will call this
+ function without parameters instead. */
+void (*error_print_progname) () = NULL;
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#include <string.h>
-#else /* !STDC_HEADERS */
-void exit ();
-#endif /* !STDC_HEADERS */
+#ifdef _LIBC
+#define program_name program_invocation_name
+#endif
+/* The calling program should define program_name and set it to the
+ name of the executing program. */
extern char *program_name;
-#ifndef HAVE_STRERROR
+#if HAVE_STRERROR || _LIBC
+# ifndef strerror /* On some systems, strerror is a macro */
+char *strerror ();
+# endif
+#else
static char *
private_strerror (errnum)
int errnum;
return "Unknown system error";
}
#define strerror private_strerror
-#endif /* !HAVE_STRERROR */
+#endif
/* Print the program name and error message MESSAGE, which is a printf-style
format string with optional args.
If ERRNUM is nonzero, print its corresponding system error message.
Exit with status STATUS if it is nonzero. */
/* VARARGS */
+
void
-#if defined (HAVE_VPRINTF) && __STDC__
-error (int status, int errnum, char *message, ...)
-#else /* !HAVE_VPRINTF or !__STDC__ */
+#if defined(VA_START) && __STDC__
+error (int status, int errnum, const char *message, ...)
+#else
error (status, errnum, message, va_alist)
int status;
int errnum;
char *message;
va_dcl
-#endif /* !HAVE_VPRINTF or !__STDC__ */
+#endif
{
-#ifdef HAVE_VPRINTF
+#ifdef VA_START
va_list args;
-#endif /* HAVE_VPRINTF */
+#endif
+
+ if (error_print_progname)
+ (*error_print_progname) ();
+ else
+ {
+ fflush (stdout);
+ fprintf (stderr, "%s: ", program_name);
+ }
- fprintf (stderr, "%s: ", program_name);
-#ifdef HAVE_VPRINTF
+#ifdef VA_START
VA_START (args, message);
+# if HAVE_VPRINTF || _LIBC
vfprintf (stderr, message, args);
+# else
+ _doprnt (message, args, stderr);
+# endif
va_end (args);
-#else /* !HAVE_VPRINTF */
-#ifdef HAVE_DOPRNT
- _doprnt (message, &args, stderr);
-#else /* !HAVE_DOPRNT */
+#else
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
-#endif /* !HAVE_DOPRNT */
-#endif /* !HAVE_VPRINTF */
+#endif
+
+ ++error_message_count;
+
if (errnum)
fprintf (stderr, ": %s", strerror (errnum));
putc ('\n', stderr);
extern int io_block_size;
extern int create_dir_flag;
extern int rename_flag;
+extern char *rename_batch_file;
extern int table_flag;
extern int unconditional_flag;
extern int verbose_flag;
extern int set_group_flag;
extern gid_t set_group;
extern int no_chown_flag;
+extern int sparse_flag;
+extern int quiet_flag;
+extern int only_verify_crc_flag;
+extern int no_abs_paths_flag;
+
extern int last_header_start;
extern int copy_matching_files;
extern int numeric_uid;
extern char *input_buffer, *output_buffer;
extern char *in_buff, *out_buff;
+extern long input_buffer_size;
extern long input_size, output_size;
+#ifdef __GNUC__
+extern long long input_bytes, output_bytes;
+#else
extern long input_bytes, output_bytes;
+#endif
extern char zeros_512[];
extern char *directory_name;
extern char **save_patterns;
/* copypass.c */
void process_copy_pass P_((void));
+int link_to_maj_min_ino P_((char *file_name, int st_dev_maj,
+ int st_dev_min, int st_ino));
+int link_to_name P_((char *link_name, char *link_target));
/* dirname.c */
char *dirname P_((char *path));
#endif
/* util.c */
-void empty_output_buffer P_((int out_des));
+void tape_empty_output_buffer P_((int out_des));
+void disk_empty_output_buffer P_((int out_des));
void swahw_array P_((char *ptr, int count));
-void fill_input_buffer P_((int in_des, int num_bytes));
-void copy_buf_out P_((char *in_buf, int out_des, long num_bytes));
-void copy_in_buf P_((char *in_buf, int in_des, long num_bytes));
-int peek_in_buf P_((char *peek_buf, int in_des, int num_bytes));
-void toss_input P_((int in_des, long num_bytes));
-void copy_files P_((int in_des, int out_des, long num_bytes));
+void tape_buffered_write P_((char *in_buf, int out_des, long num_bytes));
+void tape_buffered_read P_((char *in_buf, int in_des, long num_bytes));
+int tape_buffered_peek P_((char *peek_buf, int in_des, int num_bytes));
+void tape_toss_input P_((int in_des, long num_bytes));
+void copy_files_tape_to_disk P_((int in_des, int out_des, long num_bytes));
+void copy_files_disk_to_tape P_((int in_des, int out_des, long num_bytes, char *filename));
+void copy_files_disk_to_disk P_((int in_des, int out_des, long num_bytes, char *filename));
void create_all_directories P_((char *name));
void prepare_append P_((int out_file_des));
char *find_inode_file P_((unsigned long node_num,
void tape_offline P_((int tape_des));
void get_next_reel P_((int tape_des));
void set_new_media_message P_((char *message));
-#ifdef __MSDOS__
+#if defined(__MSDOS__) && !defined(__GNUC__)
int chown P_((char *path, int owner, int group));
#endif
#ifdef __TURBOC__
/* xstrdup.c */
char *xstrdup P_((char *string));
+
+#define DISK_IO_BLOCK_SIZE (512)
/* filemode.c -- make a string describing file modes
- Copyright (C) 1985, 1990 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1990, 1993 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
\f
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
-#ifndef S_IREAD
-#define S_IREAD S_IRUSR
-#define S_IWRITE S_IWUSR
-#define S_IEXEC S_IXUSR
-#endif
-
-#if !defined(S_ISREG) || defined(NO_MODE_T)
-/* Doesn't have POSIX.1 stat stuff or doesn't have mode_t. */
-#define mode_t unsigned short
-#endif
+#if !S_IRUSR
+# if S_IREAD
+# define S_IRUSR S_IREAD
+# else
+# define S_IRUSR 00400
+# endif
+#endif
+
+#if !S_IWUSR
+# if S_IWRITE
+# define S_IWUSR S_IWRITE
+# else
+# define S_IWUSR 00200
+# endif
+#endif
+
+#if !S_IXUSR
+# if S_IEXEC
+# define S_IXUSR S_IEXEC
+# else
+# define S_IXUSR 00100
+# endif
+#endif
+
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISBLK
+#undef S_ISCHR
+#undef S_ISDIR
+#undef S_ISFIFO
+#undef S_ISLNK
+#undef S_ISMPB
+#undef S_ISMPC
+#undef S_ISNWK
+#undef S_ISREG
+#undef S_ISSOCK
+#endif /* STAT_MACROS_BROKEN. */
#if !defined(S_ISBLK) && defined(S_IFBLK)
-#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#endif
#if !defined(S_ISCHR) && defined(S_IFCHR)
-#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#endif
#if !defined(S_ISDIR) && defined(S_IFDIR)
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#if !defined(S_ISREG) && defined(S_IFREG)
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
#if !defined(S_ISFIFO) && defined(S_IFIFO)
-#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#endif
#if !defined(S_ISLNK) && defined(S_IFLNK)
-#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
-#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#endif
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
unsigned short mode;
char *str;
{
- str[0] = ftypelet (mode);
+ str[0] = ftypelet ((long) mode);
rwx ((mode & 0700) << 0, &str[1]);
rwx ((mode & 0070) << 3, &str[4]);
rwx ((mode & 0007) << 6, &str[7]);
static char
ftypelet (bits)
- mode_t bits;
+ long bits;
{
#ifdef S_ISBLK
if (S_ISBLK (bits))
unsigned short bits;
char *chars;
{
- chars[0] = (bits & S_IREAD) ? 'r' : '-';
- chars[1] = (bits & S_IWRITE) ? 'w' : '-';
- chars[2] = (bits & S_IEXEC) ? 'x' : '-';
+ chars[0] = (bits & S_IRUSR) ? 'r' : '-';
+ chars[1] = (bits & S_IWUSR) ? 'w' : '-';
+ chars[2] = (bits & S_IXUSR) ? 'x' : '-';
}
/* Set the 's' and 't' flags in file attributes string CHARS,
Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include <errno.h>
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
-#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
+#ifndef errno
extern int errno;
#endif
#define _FNMATCH_H 1
+#if defined(HAVE_SYS_CDEFS_H)
+#include <sys/cdefs.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
+#if !defined(HAVE_SYS_CDEFS_H)
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
-#if !(defined(_NetBSD__) || defined(__OpenBSD__))
#undef __P
-#define __P(args) args
-#else
-#include <sys/cdefs.h>
-#endif
+#define __P(protos) protos
#else /* Not C++ or ANSI C. */
#undef __P
-#define __P(args) ()
+#define __P(protos) ()
/* We can get away without defining `const' here only because in this file
it is used only inside the prototype for `fnmatch', which is elided in
non-ANSI C where `const' is problematical. */
#endif /* C++ or ANSI C. */
+#endif
+
+
+/* We #undef these before defining them because some losing systems
+ (HP-UX A.08.07 for example) define these in <unistd.h>. */
+#undef FNM_PATHNAME
+#undef FNM_NOESCAPE
+#undef FNM_PERIOD
/* Bits set in the FLAGS argument to `fnmatch'. */
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
- Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
\f
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
-#if !__STDC__ && !defined(const) && IN_GCC
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
#define const
#endif
-
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
-#ifndef _NO_PROTO
-#define _NO_PROTO
#endif
#include <stdio.h>
#include <stdlib.h>
#endif /* GNU C library. */
-/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
- long-named option. Because this is not POSIX.2 compliant, it is
- being phased out. */
-/* #define GETOPT_COMPAT */
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.
+ When compiling libc, the _ macro is predefined. */
+#ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# define _(msgid) gettext (msgid)
+#else
+# define _(msgid) (msgid)
+#endif
+#endif
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
-char *optarg = 0;
+char *optarg = NULL;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
\f
#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
/* If using GCC, we can safely declare strlen this way.
If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
-#ifdef IN_GCC
-#include "gstddef.h"
-#else
-#include <stddef.h>
-#endif
-extern size_t strlen (const char *);
-#endif
-
-#endif /* GNU C library. */
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
\f
/* Handle permutation of arguments. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
+
+/* Initialize the internal data when the first call is made. */
+
+static const char *
+_getopt_initialize (optstring)
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+ return optstring;
+}
\f
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
int *longind;
int long_only;
{
- int option_index;
-
- optarg = 0;
-
- /* Initialize the internal data when the first call is made.
- Start processing options with ARGV-element 1 (since ARGV-element 0
- is the program name); the sequence of previously skipped
- non-option ARGV-elements is empty. */
+ optarg = NULL;
if (optind == 0)
{
- first_nonopt = last_nonopt = optind = 1;
-
- nextchar = NULL;
-
- /* Determine how to handle the ordering of options and nonoptions. */
-
- if (optstring[0] == '-')
- {
- ordering = RETURN_IN_ORDER;
- ++optstring;
- }
- else if (optstring[0] == '+')
- {
- ordering = REQUIRE_ORDER;
- ++optstring;
- }
- else if (getenv ("POSIXLY_CORRECT") != NULL)
- ordering = REQUIRE_ORDER;
- else
- ordering = PERMUTE;
+ optstring = _getopt_initialize (optstring);
+ optind = 1; /* Don't scan ARGV[0], the program name. */
}
if (nextchar == NULL || *nextchar == '\0')
{
+ /* Advance to the next ARGV-element. */
+
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
else if (last_nonopt != optind)
first_nonopt = optind;
- /* Now skip any additional non-options
+ /* Skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
- && (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
- && (longopts == NULL
- || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif /* GETOPT_COMPAT */
- )
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
optind++;
last_nonopt = optind;
}
- /* Special ARGV-element `--' means premature end of options.
+ /* The special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
- if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
- && (longopts == NULL
- || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif /* GETOPT_COMPAT */
- )
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
{
if (ordering == REQUIRE_ORDER)
return EOF;
}
/* We have found another option-ARGV-element.
- Start decoding its characters. */
+ Skip the initial punctuation. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
if (longopts != NULL
- && ((argv[optind][0] == '-'
- && (argv[optind][1] == '-' || long_only))
-#ifdef GETOPT_COMPAT
- || argv[optind][0] == '+'
-#endif /* GETOPT_COMPAT */
- ))
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
{
+ char *nameend;
const struct option *p;
- char *s = nextchar;
+ const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
- const struct option *pfound = NULL;
int indfound;
+ int option_index;
- while (*s && *s != '=')
- s++;
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
- /* Test all options for either exact match or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name;
- p++, option_index++)
- if (!strncmp (p->name, nextchar, s - nextchar))
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
{
- if (s - nextchar == strlen (p->name))
+ if (nameend - nextchar == strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
}
else
- /* Second nonexact match found. */
+ /* Second or later nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
- fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
{
option_index = indfound;
optind++;
- if (*s)
+ if (*nameend)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
- optarg = s + 1;
+ optarg = nameend + 1;
else
{
if (opterr)
- {
- if (argv[optind - 1][1] == '-')
- /* --option */
- fprintf (stderr,
- "%s: option `--%s' doesn't allow an argument\n",
- argv[0], pfound->name);
- else
- /* +option or -option */
- fprintf (stderr,
- "%s: option `%c%s' doesn't allow an argument\n",
- argv[0], argv[optind - 1][0], pfound->name);
- }
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ _("%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ _("%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+
nextchar += strlen (nextchar);
return '?';
}
else
{
if (opterr)
- fprintf (stderr, "%s: option `%s' requires an argument\n",
- argv[0], argv[optind - 1]);
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
return pfound->val;
}
+
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
-#ifdef GETOPT_COMPAT
- || argv[optind][0] == '+'
-#endif /* GETOPT_COMPAT */
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
- fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
argv[0], nextchar);
else
/* +option or -option */
- fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
}
}
- /* Look at and handle the next option-character. */
+ /* Look at and handle the next short option-character. */
{
char c = *nextchar++;
{
if (opterr)
{
-#if 0
- if (c < 040 || c >= 0177)
- fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: illegal option -- %c\n"),
argv[0], c);
else
- fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
-#else
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
-#endif
+ fprintf (stderr, _("%s: invalid option -- %c\n"),
+ argv[0], c);
}
optopt = c;
return '?';
optind++;
}
else
- optarg = 0;
+ optarg = NULL;
nextchar = NULL;
}
else
{
if (opterr)
{
-#if 0
- fprintf (stderr, "%s: option `-%c' requires an argument\n",
- argv[0], c);
-#else
/* 1003.2 specifies the format of this message. */
- fprintf (stderr, "%s: option requires an argument -- %c\n",
- argv[0], c);
-#endif
+ fprintf (stderr,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
}
optopt = c;
if (optstring[0] == ':')
/* Declarations for getopt.
- Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
struct option
{
-#if __STDC__
+#if defined (__STDC__) && __STDC__
const char *name;
#else
char *name;
#define required_argument 1
#define optional_argument 2
-#if __STDC__
-#if defined(__GNU_LIBRARY__)
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
-#endif /* not __GNU_LIBRARY__ */
+#endif /* __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
extern int getopt_long_only ();
extern int _getopt_internal ();
-#endif /* not __STDC__ */
+#endif /* __STDC__ */
#ifdef __cplusplus
}
/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
\f
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include "getopt.h"
-#if !__STDC__ && !defined(const) && IN_GCC
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
#define const
#endif
+#endif
#include <stdio.h>
/* If TRUE, interactively rename files. (-r) */
int rename_flag = FALSE;
+/* If non-NULL, the name of a file that will be read to
+ rename all of the files in the archive. --rename-batch-file. */
+char *rename_batch_file = NULL;
+
/* If TRUE, print a table of contents of input. (-t) */
int table_flag = FALSE;
/* If TRUE, do not chown the files. */
int no_chown_flag = FALSE;
+/* If TRUE, try to write sparse ("holey") files. */
+int sparse_flag = FALSE;
+
+/* If TRUE, don't report number of blocks copied. */
+int quiet_flag = FALSE;
+
+/* If TRUE, only read the archive and verify the files' CRC's, don't
+ actually extract the files. */
+int only_verify_crc_flag = FALSE;
+
+/* If TRUE, don't use any absolute paths, prefix them by `./'. */
+int no_abs_paths_flag = FALSE;
+
#ifdef DEBUG_CPIO
/* If TRUE, print debugging information. */
int debug_flag = FALSE;
/* Input and output buffers. */
char *input_buffer, *output_buffer;
+/* The size of the input buffer. */
+long input_buffer_size;
+
/* Current locations in `input_buffer' and `output_buffer'. */
char *in_buff, *out_buff;
/* Current number of bytes stored at `input_buff' and `output_buff'. */
long input_size, output_size;
-/* Total number of bytes read and written for all files. */
+/* Total number of bytes read and written for all files.
+ Now that many tape drives hold more than 4Gb we need more than 32
+ bits to hold input_bytes and output_bytes. But it's not worth
+ the trouble of adding special multi-precision arithmetic if the
+ compiler doesn't support 64 bit ints since input_bytes and
+ output_bytes are only used to print the number of blocks copied. */
+#ifdef __GNUC__
+long long input_bytes, output_bytes;
+#else
long input_bytes, output_bytes;
+#endif
/* 512 bytes of 0; used for various padding operations. */
char zeros_512[512];
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
group_alist = tail;
return &tail->id.g;
}
-
+
tail->next = nogroup_alist;
nogroup_alist = tail;
return 0;
{"list", 0, &table_flag, TRUE},
{"make-directories", 0, &create_dir_flag, TRUE},
{"message", 1, 0, 'M'},
+ {"no-absolute-filenames", 0, 0, 136},
{"no-preserve-owner", 0, 0, 134},
{"nonmatching", 0, ©_matching_files, FALSE},
{"numeric-uid-gid", 0, &numeric_uid, TRUE},
+ {"only-verify-crc", 0, 0, 139},
{"owner", 1, 0, 'R'},
{"pass-through", 0, 0, 'p'},
{"pattern-file", 1, 0, 'E'},
{"preserve-modification-time", 0, &retain_time_flag, TRUE},
{"rename", 0, &rename_flag, TRUE},
+ {"rename-batch-file", 1, 0, 137},
+ {"quiet", 0, 0, 138},
+ {"sparse", 0, 0, 135},
{"swap", 0, 0, 'b'},
{"swap-bytes", 0, 0, 's'},
{"swap-halfwords", 0, 0, 'S'},
[-O [[user@]host:]archive] [-F [[user@]host:]archive]\n\
[--file=[[user@]host:]archive] [--format=format] [--message=message]\n\
[--null] [--reset-access-time] [--verbose] [--dot] [--append]\n\
- [--block-size=blocks] [--dereference] [--io-size=bytes]\n\
+ [--block-size=blocks] [--dereference] [--io-size=bytes] [--quiet]\n\
[--force-local] [--help] [--version] < name-list [> archive]\n", program_name);
fprintf (fp, "\
%s {-i|--extract} [-bcdfmnrtsuvBSV] [-C bytes] [-E file] [-H format]\n\
[--unconditional] [--verbose] [--block-size=blocks] [--swap-halfwords]\n\
[--io-size=bytes] [--pattern-file=file] [--format=format]\n\
[--owner=[user][:.][group]] [--no-preserve-owner] [--message=message]\n\
- [--force-local] [--help] [--version] [pattern...] [< archive]\n",
+ [--force-local] [--no-absolute-filenames] [--sparse] [--only-verify-crc]\n\
+ [--quiet] [--help] [--version] [pattern...] [< archive]\n",
program_name);
fprintf (fp, "\
%s {-p|--pass-through} [-0adlmuvLV] [-R [user][:.][group]]\n\
- [--null] [--reset-access-time] [--make-directories] [--link]\n\
+ [--null] [--reset-access-time] [--make-directories] [--link] [--quiet]\n\
[--preserve-modification-time] [--unconditional] [--verbose] [--dot]\n\
[--dereference] [--owner=[user][:.][group]] [--no-preserve-owner]\n\
- [--help] [--version] destination-directory < name-list\n", program_name);
+ [--sparse] [--help] [--version] destination-directory < name-list\n", program_name);
exit (status);
}
numeric_uid = TRUE;
break;
+ case 136: /* --no-absolute-filenames */
+ no_abs_paths_flag = TRUE;
+ break;
+
case 134: /* --no-preserve-owner */
if (set_owner_flag || set_group_flag)
usage (stderr, 2);
output_archive_name = optarg;
break;
+ case 139:
+ only_verify_crc_flag = TRUE;
+ break;
+
case 'p': /* Copy-pass mode. */
if (copy_function != 0)
usage (stderr, 2);
rename_flag = TRUE;
break;
+ case 137:
+ rename_batch_file = optarg;
+ break;
+
+ case 138:
+ quiet_flag = TRUE;
+ break;
+
case 'R': /* Set the owner. */
if (no_chown_flag)
usage (stderr, 2);
exit (0);
break;
+ case 135:
+ sparse_flag = TRUE;
+ break;
+
case 132: /* --help */
usage (stdout, 0);
break;
{
archive_des = 0;
if (link_flag || reset_time_flag || xstat != lstat || append_flag
+ || sparse_flag
|| output_archive_name
|| (archive_name && input_archive_name))
usage (stderr, 2);
|| retain_time_flag || no_chown_flag || set_owner_flag
|| set_group_flag || swap_bytes_flag || swap_halfwords_flag
|| (append_flag && !(archive_name || output_archive_name))
+ || rename_batch_file || no_abs_paths_flag
|| input_archive_name || (archive_name && output_archive_name))
usage (stderr, 2);
if (archive_format == arf_unknown)
archive_des = -1;
if (argc - 1 != optind || archive_format != arf_unknown
|| swap_bytes_flag || swap_halfwords_flag
- || table_flag || rename_flag || append_flag)
+ || table_flag || rename_flag || append_flag
+ || rename_batch_file || no_abs_paths_flag)
usage (stderr, 2);
directory_name = argv[optind];
}
void
initialize_buffers ()
{
- int buf_size;
+ int in_buf_size, out_buf_size;
- /* Make sure buffers can always hold 2 blocks and that they
- are big enough to hold 1 tar record (512 bytes) even if it
- is not aligned on a block boundary. The extra buffer space
- is needed by process_copyin and peek_in_buf to automatically
- figure out what kind of archive it is reading. */
-
- if (io_block_size >= 512)
- buf_size = 2 * io_block_size;
+ if (copy_function == process_copy_in)
+ {
+ /* Make sure the input buffer can always hold 2 blocks and that it
+ is big enough to hold 1 tar record (512 bytes) even if it
+ is not aligned on a block boundary. The extra buffer space
+ is needed by process_copyin and peek_in_buf to automatically
+ figure out what kind of archive it is reading. */
+ if (io_block_size >= 512)
+ in_buf_size = 2 * io_block_size;
+ else
+ in_buf_size = 1024;
+ out_buf_size = DISK_IO_BLOCK_SIZE;
+ }
+ else if (copy_function == process_copy_out)
+ {
+ in_buf_size = DISK_IO_BLOCK_SIZE;
+ out_buf_size = io_block_size;
+ }
else
- buf_size = 1024;
- input_buffer = (char *) xmalloc (buf_size);
+ {
+ in_buf_size = DISK_IO_BLOCK_SIZE;
+ out_buf_size = DISK_IO_BLOCK_SIZE;
+ }
+
+ input_buffer = (char *) xmalloc (in_buf_size);
in_buff = input_buffer;
+ input_buffer_size = in_buf_size;
input_size = 0;
input_bytes = 0;
- /* Leave space for an `int' sentinel for `empty_output_buffer',
- in case we ever put back sparseness checking. */
- output_buffer = (char *) xmalloc (buf_size + sizeof (int) * 2);
+ output_buffer = (char *) xmalloc (out_buf_size);
out_buff = output_buffer;
output_size = 0;
output_bytes = 0;
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
-#ifdef STDC_HEADERS
#include <errno.h>
+#ifdef STDC_HEADERS
#include <stdlib.h>
#else
extern int errno;
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
+#ifndef index
#define index strchr
+#endif
#else
#include <strings.h>
#endif
-#ifdef __MSDOS__
+#if defined(__MSDOS__) && !defined(__GNUC__)
typedef int uid_t;
typedef int gid_t;
#endif
}
/* We're done making leading directories.
- Make the final component of the path. */
+ Make the final component of the path. */
if (mkdir (dirpath, mode))
{
- error (0, errno, "cannot make directory `%s'", dirpath);
- umask (oldmask);
- return 1;
+ /* In some cases, if the final component in dirpath was `.' then we
+ just got an EEXIST error from that last mkdir(). If that's
+ the case, ignore it. */
+ if ( (errno != EEXIST) ||
+ (stat (dirpath, &stats) != 0) ||
+ (!S_ISDIR (stats.st_mode) ) )
+ {
+ error (0, errno, "cannot make directory `%s'", dirpath);
+ umask (oldmask);
+ return 1;
+ }
}
if (verbose_fmt_string != NULL)
error (0, 0, verbose_fmt_string, dirpath);
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#else
#endif
#ifndef _POSIX_VERSION
+#if defined(__MSDOS__) && !defined(__GNUC__)
+typedef long off_t;
+#endif
off_t lseek ();
#endif
#define CONSOLE "con"
#endif
-#ifdef __MSDOS__
+#if defined(__MSDOS__) && !defined(__GNUC__)
typedef int uid_t;
typedef int gid_t;
#endif
to_oct (tar_checksum (tar_hdr), 8, tar_hdr->chksum);
- copy_buf_out ((char *) &tar_rec, out_des, TARRECORDSIZE);
+ tape_buffered_write ((char *) &tar_rec, out_des, TARRECORDSIZE);
}
/* Return nonzero iff all the bytes in BLOCK are NUL.
gid_t *gidp;
#endif
- copy_in_buf ((char *) &tar_rec, in_des, TARRECORDSIZE);
+ tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
/* Check for a block of 0's. */
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
/* Commented out because GNU tar sometimes creates archives with
only one block of 0's at the end. This happened for the
cpio 2.0 distribution! */
- copy_in_buf ((char *) &tar_rec, in_des, TARRECORDSIZE);
+ tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
#endif
{
}
bcopy (((char *) &tar_rec) + 1, (char *) &tar_rec,
TARRECORDSIZE - 1);
- copy_in_buf (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
+ tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
++bytes_skipped;
continue;
}
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
\f
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#else
+#ifdef _AIX
+ #pragma alloca
+#else
+char *alloca ();
+#endif
+#endif
+#endif
+
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
-#else
-char *malloc ();
#endif
#ifdef HAVE_UNISTD_H
#define endgrent()
#endif
+/* Perform the equivalent of the statement `dest = strdup (src);',
+ but obtaining storage via alloca instead of from the heap. */
+
+#define V_STRDUP(dest, src) \
+ do \
+ { \
+ int _len = strlen ((src)); \
+ (dest) = (char *) alloca (_len + 1); \
+ strcpy (dest, src); \
+ } \
+ while (0)
+
#define isdigit(c) ((c) >= '0' && (c) <= '9')
char *strdup ();
-static int isnumber ();
+
+/* Return nonzero if STR represents an unsigned decimal integer,
+ otherwise return 0. */
+
+static int
+isnumber (str)
+ const char *str;
+{
+ for (; *str; str++)
+ if (!isdigit (*str))
+ return 0;
+ return 1;
+}
/* Extract from NAME, which has the form "[user][:.][group]",
a USERNAME, UID U, GROUPNAME, and GID G.
USERNAME and GROUPNAME will be in newly malloc'd memory.
Either one might be NULL instead, indicating that it was not
given and the corresponding numeric ID was left unchanged.
- Might write NULs into NAME.
Return NULL if successful, a static error message string if not. */
-char *
-parse_user_spec (name, uid, gid, username, groupname)
- char *name;
+const char *
+parse_user_spec (spec_arg, uid, gid, username_arg, groupname_arg)
+ const char *spec_arg;
uid_t *uid;
gid_t *gid;
- char **username, **groupname;
+ char **username_arg, **groupname_arg;
{
- static char *tired = "virtual memory exhausted";
+ static const char *tired = "virtual memory exhausted";
+ const char *error_msg;
+ char *spec; /* A copy we can write on. */
struct passwd *pwd;
struct group *grp;
- char *cp;
- int use_login_group = 0;
+ char *g, *u, *separator;
+ char *groupname;
+
+ error_msg = NULL;
+ *username_arg = *groupname_arg = NULL;
+ groupname = NULL;
- *username = *groupname = NULL;
+ V_STRDUP (spec, spec_arg);
- /* Check whether a group is given. */
- cp = index (name, ':');
- if (cp == NULL)
- cp = index (name, '.');
- if (cp != NULL)
+ /* Find the separator if there is one. */
+ separator = index (spec, ':');
+ if (separator == NULL)
+ separator = index (spec, '.');
+
+ /* Replace separator with a NUL. */
+ if (separator != NULL)
+ *separator = '\0';
+
+ /* Set U and G to non-zero length strings corresponding to user and
+ group specifiers or to NULL. */
+ u = (*spec == '\0' ? NULL : spec);
+
+ g = (separator == NULL || *(separator + 1) == '\0'
+ ? NULL
+ : separator + 1);
+
+ if (u == NULL && g == NULL)
+ return "can not omit both user and group";
+
+ if (u != NULL)
{
- *cp++ = '\0';
- if (*cp == '\0')
+ pwd = getpwnam (u);
+ if (pwd == NULL)
{
- if (cp == name + 1)
- /* Neither user nor group given, just "." or ":". */
- return "can not omit both user and group";
+
+ if (!isnumber (u))
+ error_msg = "invalid user";
else
- /* "user.". */
- use_login_group = 1;
+ {
+ int use_login_group;
+ use_login_group = (separator != NULL && g == NULL);
+ if (use_login_group)
+ error_msg = "cannot get the login group of a numeric UID";
+ else
+ *uid = atoi (u);
+ }
}
else
{
- /* Explicit group. */
- *groupname = strdup (cp);
- if (*groupname == NULL)
- return tired;
- grp = getgrnam (cp);
- if (grp == NULL)
+ *uid = pwd->pw_uid;
+ if (g == NULL && separator != NULL)
{
- if (!isnumber (cp))
- return "invalid group";
- *gid = atoi (cp);
+ /* A separator was given, but a group was not specified,
+ so get the login group. */
+ *gid = pwd->pw_gid;
+ grp = getgrgid (pwd->pw_gid);
+ if (grp == NULL)
+ {
+ /* This is enough room to hold the unsigned decimal
+ representation of any 32-bit quantity and the trailing
+ zero byte. */
+ char uint_buf[21];
+ sprintf (uint_buf, "%u", (unsigned) (pwd->pw_gid));
+ V_STRDUP (groupname, uint_buf);
+ }
+ else
+ {
+ V_STRDUP (groupname, grp->gr_name);
+ }
+ endgrent ();
}
- else
- *gid = grp->gr_gid;
- endgrent (); /* Save a file descriptor. */
}
+ endpwent ();
}
- /* Parse the user name, now that any group has been removed. */
-
- if (name[0] == '\0')
- /* No user name was given, just a group. */
- return NULL;
-
- *username = strdup (name);
- if (*username == NULL)
- return tired;
-
- pwd = getpwnam (name);
- if (pwd == NULL)
+ if (g != NULL && error_msg == NULL)
{
- if (!isnumber (name))
- return "invalid user";
- if (use_login_group)
- return "cannot get the login group of a numeric UID";
- *uid = atoi (name);
+ /* Explicit group. */
+ grp = getgrnam (g);
+ if (grp == NULL)
+ {
+ if (!isnumber (g))
+ error_msg = "invalid group";
+ else
+ *gid = atoi (g);
+ }
+ else
+ *gid = grp->gr_gid;
+ endgrent (); /* Save a file descriptor. */
+
+ if (error_msg == NULL)
+ V_STRDUP (groupname, g);
}
- else
+
+ if (error_msg == NULL)
{
- *uid = pwd->pw_uid;
- if (use_login_group)
+ if (u != NULL)
{
- *gid = pwd->pw_gid;
- grp = getgrgid (pwd->pw_gid);
- if (grp == NULL)
- {
- *groupname = malloc (15);
- if (*groupname == NULL)
- return tired;
- sprintf (*groupname, "%u", pwd->pw_gid);
- }
- else
+ *username_arg = strdup (u);
+ if (*username_arg == NULL)
+ error_msg = tired;
+ }
+
+ if (groupname != NULL && error_msg == NULL)
+ {
+ *groupname_arg = strdup (groupname);
+ if (*groupname_arg == NULL)
{
- *groupname = strdup (grp->gr_name);
- if (*groupname == NULL)
- return tired;
+ if (*username_arg != NULL)
+ {
+ free (*username_arg);
+ *username_arg = NULL;
+ }
+ error_msg = tired;
}
- endgrent ();
}
}
- endpwent ();
- return NULL;
+
+ return error_msg;
}
-/* Return nonzero if STR represents an unsigned decimal integer,
- otherwise return 0. */
+#ifdef TEST
-static int
-isnumber (str)
- char *str;
+#define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s))
+
+int
+main (int argc, char **argv)
{
- for (; *str; str++)
- if (!isdigit (*str))
- return 0;
- return 1;
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ const char *e;
+ char *username, *groupname;
+ uid_t uid;
+ gid_t gid;
+ char *tmp;
+
+ tmp = strdup (argv[i]);
+ e = parse_user_spec (tmp, &uid, &gid, &username, &groupname);
+ free (tmp);
+ printf ("%s: %u %u %s %s %s\n",
+ argv[i],
+ (unsigned int) uid,
+ (unsigned int) gid,
+ NULL_CHECK (username),
+ NULL_CHECK (groupname),
+ NULL_CHECK (e));
+ }
+
+ exit (0);
}
+
+#endif
#include <sys/mtio.h>
#endif
-static void empty_output_buffer_swap ();
+static void tape_fill_input_buffer P_((int in_des, int num_bytes));
+static int disk_fill_input_buffer P_((int in_des, int num_bytes));
static void hash_insert ();
+static void write_nuls_to_file P_((long num_bytes, int out_des));
/* Write `output_size' bytes of `output_buffer' to file
descriptor OUT_DES and reset `output_size' and `out_buff'. */
void
-empty_output_buffer (out_des)
+tape_empty_output_buffer (out_des)
int out_des;
{
int bytes_written;
#ifdef BROKEN_LONG_TAPE_DRIVER
static long output_bytes_before_lseek = 0;
-#endif
- if (swapping_halfwords || swapping_bytes)
- {
- empty_output_buffer_swap (out_des);
- return;
- }
-
-#ifdef BROKEN_LONG_TAPE_DRIVER
/* Some tape drivers seem to have a signed internal seek pointer and
they lose if it overflows and becomes negative (e.g. when writing
tapes > 2Gb). Doing an lseek (des, 0, SEEK_SET) seems to reset the
seek pointer and prevent it from overflowing. */
if (output_is_special
- && (output_bytes_before_lseek += output_size) < 0L)
+ && ( (output_bytes_before_lseek += output_size) >= 1073741824L) )
{
lseek(out_des, 0L, SEEK_SET);
output_bytes_before_lseek = 0;
}
/* Write `output_size' bytes of `output_buffer' to file
- descriptor OUT_DES with byte and/or halfword swapping and reset
- `output_size' and `out_buff'. This routine should not be called
- with `swapping_bytes' set unless the caller knows that the
- file being written has an even number of bytes, and it should not be
- called with `swapping_halfwords' set unless the caller knows
- that the file being written has a length divisible by 4. If either
- of those restrictions are not met, bytes may be lost in the output
- file. OUT_DES must refer to a file that we are creating during
- a process_copy_in, so we don't have to check for end of media
- errors or be careful about only writing in blocks of `output_size'
- bytes. */
+ descriptor OUT_DES and reset `output_size' and `out_buff'.
+ If `swapping_halfwords' or `swapping_bytes' is set,
+ do the appropriate swapping first. Our callers have
+ to make sure to only set these flags if `output_size'
+ is appropriate (a multiple of 4 for `swapping_halfwords',
+ 2 for `swapping_bytes'). The fact that DISK_IO_BLOCK_SIZE
+ must always be a multiple of 4 helps us (and our callers)
+ insure this. */
-static void
-empty_output_buffer_swap (out_des)
+void
+disk_empty_output_buffer (out_des)
int out_des;
{
- /* Since `output_size' might not be divisible by 4 or 2, we might
- not be able to be able to swap all the bytes and halfwords in
- `output_buffer' (e.g., if `output_size' is odd), so we might not be
- able to write them all. We will swap and write as many bytes as
- we can, and save the rest in `left_overs' for the next time we are
- called. */
- static char left_overs[4];
- static int left_over_bytes = 0;
-
int bytes_written;
- int complete_halfwords;
- int complete_words;
- int extra_bytes;
- output_bytes += output_size;
-
- out_buff = output_buffer;
-
- if (swapping_halfwords)
+ if (swapping_halfwords || swapping_bytes)
{
- if (left_over_bytes != 0)
- {
- while (output_size > 0 && left_over_bytes < 4)
- {
- left_overs[left_over_bytes++] = *out_buff++;
- --output_size;
- }
- if (left_over_bytes < 4)
- {
- out_buff = output_buffer;
- output_size = 0;
- return;
- }
- swahw_array (left_overs, 1);
- if (swapping_bytes)
- swab_array (left_overs, 2);
- bytes_written = rmtwrite (out_des, left_overs, 4);
- if (bytes_written != 4)
- error (1, errno, "write error");
- left_over_bytes = 0;
- }
- complete_words = output_size / 4;
- if (complete_words > 0)
+ if (swapping_halfwords)
{
- swahw_array (out_buff, complete_words);
+ int complete_words;
+ complete_words = output_size / 4;
+ swahw_array (output_buffer, complete_words);
if (swapping_bytes)
- swab_array (out_buff, 2 * complete_words);
- bytes_written = rmtwrite (out_des, out_buff, 4 * complete_words);
- if (bytes_written != (4 * complete_words))
- error (1, errno, "write error");
+ swab_array (output_buffer, 2 * complete_words);
}
- out_buff += (4 * complete_words);
- extra_bytes = output_size % 4;
- while (extra_bytes > 0)
+ else
{
- left_overs[left_over_bytes++] = *out_buff++;
- --extra_bytes;
+ int complete_halfwords;
+ complete_halfwords = output_size /2;
+ swab_array (output_buffer, complete_halfwords);
}
-
}
+
+ if (sparse_flag)
+ bytes_written = sparse_write (out_des, output_buffer, output_size);
else
+ bytes_written = write (out_des, output_buffer, output_size);
+
+ if (bytes_written != output_size)
{
- if (left_over_bytes != 0)
- {
- while (output_size > 0 && left_over_bytes < 2)
- {
- left_overs[left_over_bytes++] = *out_buff++;
- --output_size;
- }
- if (left_over_bytes < 2)
- {
- out_buff = output_buffer;
- output_size = 0;
- return;
- }
- swab_array (left_overs, 1);
- bytes_written = rmtwrite (out_des, left_overs, 2);
- if (bytes_written != 2)
- error (1, errno, "write error");
- left_over_bytes = 0;
- }
- complete_halfwords = output_size / 2;
- if (complete_halfwords > 0)
- {
- swab_array (out_buff, complete_halfwords);
- bytes_written = rmtwrite (out_des, out_buff, 2 * complete_halfwords);
- if (bytes_written != (2 * complete_halfwords))
- error (1, errno, "write error");
- }
- out_buff += (2 * complete_halfwords);
- extra_bytes = output_size % 2;
- while (extra_bytes > 0)
- {
- left_overs[left_over_bytes++] = *out_buff++;
- --extra_bytes;
- }
+ error (1, errno, "write error");
}
-
+ output_bytes += output_size;
out_buff = output_buffer;
output_size = 0;
}
static long input_bytes_before_lseek = 0;
#endif
-void
-fill_input_buffer (in_des, num_bytes)
+static void
+tape_fill_input_buffer (in_des, num_bytes)
int in_des;
int num_bytes;
{
tapes > 4Gb). Doing an lseek (des, 0, SEEK_SET) seems to reset the
seek pointer and prevent it from overflowing. */
if (input_is_special
- && (input_bytes_before_lseek += num_bytes) < 0L)
+ && ( (input_bytes_before_lseek += num_bytes) >= 1073741824L) )
{
lseek(in_des, 0L, SEEK_SET);
input_bytes_before_lseek = 0;
}
input_bytes += input_size;
}
+
+/* Read at most NUM_BYTES or `DISK_IO_BLOCK_SIZE' bytes, whichever is smaller,
+ into the start of `input_buffer' from file descriptor IN_DES.
+ Set `input_size' to the number of bytes read and reset `in_buff'.
+ Exit with an error if end of file is reached. */
+
+static int
+disk_fill_input_buffer (in_des, num_bytes)
+ int in_des;
+ int num_bytes;
+{
+ in_buff = input_buffer;
+ num_bytes = (num_bytes < DISK_IO_BLOCK_SIZE) ? num_bytes : DISK_IO_BLOCK_SIZE;
+ input_size = read (in_des, input_buffer, num_bytes);
+ if (input_size < 0)
+ {
+ input_size = 0;
+ return (-1);
+ }
+ else if (input_size == 0)
+ return (1);
+ input_bytes += input_size;
+ return (0);
+}
\f
/* Copy NUM_BYTES of buffer IN_BUF to `out_buff', which may be partly full.
When `out_buff' fills up, flush it to file descriptor OUT_DES. */
void
-copy_buf_out (in_buf, out_des, num_bytes)
+tape_buffered_write (in_buf, out_des, num_bytes)
char *in_buf;
int out_des;
long num_bytes;
{
space_left = io_block_size - output_size;
if (space_left == 0)
- empty_output_buffer (out_des);
+ tape_empty_output_buffer (out_des);
+ else
+ {
+ if (bytes_left < space_left)
+ space_left = bytes_left;
+ bcopy (in_buf, out_buff, (unsigned) space_left);
+ out_buff += space_left;
+ output_size += space_left;
+ in_buf += space_left;
+ bytes_left -= space_left;
+ }
+ }
+}
+
+/* Copy NUM_BYTES of buffer IN_BUF to `out_buff', which may be partly full.
+ When `out_buff' fills up, flush it to file descriptor OUT_DES. */
+
+void
+disk_buffered_write (in_buf, out_des, num_bytes)
+ char *in_buf;
+ int out_des;
+ long num_bytes;
+{
+ register long bytes_left = num_bytes; /* Bytes needing to be copied. */
+ register long space_left; /* Room left in output buffer. */
+
+ while (bytes_left > 0)
+ {
+ space_left = DISK_IO_BLOCK_SIZE - output_size;
+ if (space_left == 0)
+ disk_empty_output_buffer (out_des);
else
{
if (bytes_left < space_left)
When `in_buff' is exhausted, refill it from file descriptor IN_DES. */
void
-copy_in_buf (in_buf, in_des, num_bytes)
+tape_buffered_read (in_buf, in_des, num_bytes)
char *in_buf;
int in_des;
long num_bytes;
while (bytes_left > 0)
{
if (input_size == 0)
- fill_input_buffer (in_des, io_block_size);
+ tape_fill_input_buffer (in_des, io_block_size);
if (bytes_left < input_size)
space_left = bytes_left;
else
then EOF has been reached. */
int
-peek_in_buf (peek_buf, in_des, num_bytes)
+tape_buffered_peek (peek_buf, in_des, num_bytes)
char *peek_buf;
int in_des;
int num_bytes;
tapes > 4Gb). Doing an lseek (des, 0, SEEK_SET) seems to reset the
seek pointer and prevent it from overflowing. */
if (input_is_special
- && (input_bytes_before_lseek += num_bytes) < 0L)
+ && ( (input_bytes_before_lseek += num_bytes) >= 1073741824L) )
{
lseek(in_des, 0L, SEEK_SET);
input_bytes_before_lseek = 0;
while (input_size < num_bytes)
{
append_buf = in_buff + input_size;
+ if ( (append_buf - input_buffer) >= input_buffer_size)
+ {
+ /* We can keep up to 2 "blocks" (either the physical block size
+ or 512 bytes(the size of a tar record), which ever is
+ larger) in the input buffer when we are peeking. We
+ assume that our caller will never be interested in peeking
+ ahead at more than 512 bytes, so we know that by the time
+ we need a 3rd "block" in the buffer we can throw away the
+ first block to make room. */
+ int half;
+ half = input_buffer_size / 2;
+ bcopy (input_buffer + half, input_buffer, half);
+ in_buff = in_buff - half;
+ append_buf = append_buf - half;
+ }
tmp_input_size = rmtread (in_des, append_buf, io_block_size);
if (tmp_input_size == 0)
{
/* Skip the next NUM_BYTES bytes of file descriptor IN_DES. */
void
-toss_input (in_des, num_bytes)
+tape_toss_input (in_des, num_bytes)
int in_des;
long num_bytes;
{
while (bytes_left > 0)
{
if (input_size == 0)
- fill_input_buffer (in_des, io_block_size);
+ tape_fill_input_buffer (in_des, io_block_size);
if (bytes_left < input_size)
space_left = bytes_left;
else
space_left = input_size;
+
+ if (crc_i_flag && only_verify_crc_flag)
+ {
+ int k;
+ for (k = 0; k < space_left; ++k)
+ crc += in_buff[k] & 0xff;
+ }
+
in_buff += space_left;
input_size -= space_left;
bytes_left -= space_left;
NUM_BYTES is the number of bytes to copy. */
void
-copy_files (in_des, out_des, num_bytes)
+copy_files_tape_to_disk (in_des, out_des, num_bytes)
+ int in_des;
+ int out_des;
+ long num_bytes;
+{
+ long size;
+ long k;
+
+ while (num_bytes > 0)
+ {
+ if (input_size == 0)
+ tape_fill_input_buffer (in_des, io_block_size);
+ size = (input_size < num_bytes) ? input_size : num_bytes;
+ if (crc_i_flag)
+ {
+ for (k = 0; k < size; ++k)
+ crc += in_buff[k] & 0xff;
+ }
+ disk_buffered_write (in_buff, out_des, size);
+ num_bytes -= size;
+ input_size -= size;
+ in_buff += size;
+ }
+}
+/* Copy a file using the input and output buffers, which may start out
+ partly full. After the copy, the files are not closed nor the last
+ block flushed to output, and the input buffer may still be partly
+ full. If `crc_i_flag' is set, add each byte to `crc'.
+ IN_DES is the file descriptor for input;
+ OUT_DES is the file descriptor for output;
+ NUM_BYTES is the number of bytes to copy. */
+
+void
+copy_files_disk_to_tape (in_des, out_des, num_bytes, filename)
int in_des;
int out_des;
long num_bytes;
+ char *filename;
{
long size;
long k;
+ int rc;
+ long original_num_bytes;
+
+ original_num_bytes = num_bytes;
while (num_bytes > 0)
{
if (input_size == 0)
- fill_input_buffer (in_des, io_block_size);
+ if (rc = disk_fill_input_buffer (in_des, DISK_IO_BLOCK_SIZE))
+ {
+ if (rc > 0)
+ error (0, 0, "File %s shrunk by %ld bytes, padding with zeros",
+ filename, num_bytes);
+ else
+ error (0, 0, "Read error at byte %ld in file %s, padding with zeros",
+ original_num_bytes - num_bytes, filename);
+ write_nuls_to_file (num_bytes, out_des);
+ break;
+ }
size = (input_size < num_bytes) ? input_size : num_bytes;
if (crc_i_flag)
{
for (k = 0; k < size; ++k)
crc += in_buff[k] & 0xff;
}
- copy_buf_out (in_buff, out_des, size);
+ tape_buffered_write (in_buff, out_des, size);
+ num_bytes -= size;
+ input_size -= size;
+ in_buff += size;
+ }
+}
+/* Copy a file using the input and output buffers, which may start out
+ partly full. After the copy, the files are not closed nor the last
+ block flushed to output, and the input buffer may still be partly
+ full. If `crc_i_flag' is set, add each byte to `crc'.
+ IN_DES is the file descriptor for input;
+ OUT_DES is the file descriptor for output;
+ NUM_BYTES is the number of bytes to copy. */
+
+void
+copy_files_disk_to_disk (in_des, out_des, num_bytes, filename)
+ int in_des;
+ int out_des;
+ long num_bytes;
+ char *filename;
+{
+ long size;
+ long k;
+ long original_num_bytes;
+ int rc;
+
+ original_num_bytes = num_bytes;
+ while (num_bytes > 0)
+ {
+ if (input_size == 0)
+ if (rc = disk_fill_input_buffer (in_des, DISK_IO_BLOCK_SIZE))
+ {
+ if (rc > 0)
+ error (0, 0, "File %s shrunk by %ld bytes, padding with zeros",
+ filename, num_bytes);
+ else
+ error (0, 0, "Read error at byte %ld in file %s, padding with zeros",
+ original_num_bytes - num_bytes, filename);
+ write_nuls_to_file (num_bytes, out_des);
+ break;
+ }
+ size = (input_size < num_bytes) ? input_size : num_bytes;
+ if (crc_i_flag)
+ {
+ for (k = 0; k < size; ++k)
+ crc += in_buff[k] & 0xff;
+ }
+ disk_buffered_write (in_buff, out_des, size);
num_bytes -= size;
input_size -= size;
in_buff += size;
read (out_file_des, tmp_buf, useful_bytes_in_block);
if (lseek (out_file_des, start_of_block, SEEK_SET) < 0)
error (1, errno, "cannot seek on output");
- copy_buf_out (tmp_buf, out_file_des, useful_bytes_in_block);
+ /* fix juo -- is this copy_tape_buf_out? or copy_disk? */
+ tape_buffered_write (tmp_buf, out_file_des, useful_bytes_in_block);
free (tmp_buf);
}
new_media_message_with_number[length] = '\0';
length = strlen (p + 1);
new_media_message_after_number = xmalloc (length + 1);
- strcpy (new_media_message_after_number, message);
+ strcpy (new_media_message_after_number, p + 1);
}
}
}
#endif /* SYMLINK_USES_UMASK */
-#ifdef __MSDOS__
+#if defined(__MSDOS__) && !defined(__GNUC__)
int
chown (path, owner, group)
char *path;
return 0;
}
#endif
+
+#define DISKBLOCKSIZE (512)
+
+enum sparse_write_states { begin, in_zeros, not_in_zeros };
+
+
+static int
+buf_all_zeros (buf, bufsize)
+ char *buf;
+ int bufsize;
+{
+ int i;
+ for (i = 0; i < bufsize; ++i)
+ {
+ if (*buf++ != '\0')
+ return 0;
+ }
+ return 1;
+}
+
+int delayed_seek_count = 0;
+
+/* Write NBYTE bytes from BUF to remote tape connection FILDES.
+ Return the number of bytes written on success, -1 on error. */
+
+int
+sparse_write (fildes, buf, nbyte)
+ int fildes;
+ char *buf;
+ unsigned int nbyte;
+{
+ int complete_block_count;
+ int leftover_bytes_count;
+ int seek_count;
+ int write_count;
+ char *cur_write_start;
+ int lseek_rc;
+ int write_rc;
+ int i;
+ enum sparse_write_states state;
+
+ complete_block_count = nbyte / DISKBLOCKSIZE;
+ leftover_bytes_count = nbyte % DISKBLOCKSIZE;
+
+ if (delayed_seek_count != 0)
+ state = in_zeros;
+ else
+ state = begin;
+
+ seek_count = delayed_seek_count;
+
+ for (i = 0; i < complete_block_count; ++i)
+ {
+ switch (state)
+ {
+ case begin :
+ if (buf_all_zeros (buf, DISKBLOCKSIZE))
+ {
+ seek_count = DISKBLOCKSIZE;
+ state = in_zeros;
+ }
+ else
+ {
+ cur_write_start = buf;
+ write_count = DISKBLOCKSIZE;
+ state = not_in_zeros;
+ }
+ buf += DISKBLOCKSIZE;
+ break;
+ case in_zeros :
+ if (buf_all_zeros (buf, DISKBLOCKSIZE))
+ {
+ seek_count += DISKBLOCKSIZE;
+ }
+ else
+ {
+ lseek (fildes, seek_count, SEEK_CUR);
+ cur_write_start = buf;
+ write_count = DISKBLOCKSIZE;
+ state = not_in_zeros;
+ }
+ buf += DISKBLOCKSIZE;
+ break;
+ case not_in_zeros :
+ if (buf_all_zeros (buf, DISKBLOCKSIZE))
+ {
+ write_rc = write (fildes, cur_write_start, write_count);
+ seek_count = DISKBLOCKSIZE;
+ state = in_zeros;
+ }
+ else
+ {
+ write_count += DISKBLOCKSIZE;
+ }
+ buf += DISKBLOCKSIZE;
+ break;
+ }
+ }
+
+ switch (state)
+ {
+ case begin :
+ case in_zeros :
+ delayed_seek_count = seek_count;
+ break;
+ case not_in_zeros :
+ write_rc = write (fildes, cur_write_start, write_count);
+ delayed_seek_count = 0;
+ break;
+ }
+
+ if (leftover_bytes_count != 0)
+ {
+ if (delayed_seek_count != 0)
+ {
+ lseek_rc = lseek (fildes, delayed_seek_count, SEEK_CUR);
+ delayed_seek_count = 0;
+ }
+ write_rc = write (fildes, buf, leftover_bytes_count);
+ }
+ return nbyte;
+}
+\f
+static void
+write_nuls_to_file (num_bytes, out_des)
+ long num_bytes;
+ int out_des;
+{
+ long blocks;
+ long extra_bytes;
+ long i;
+
+ blocks = num_bytes / 512;
+ extra_bytes = num_bytes % 512;
+ for (i = 0; i < extra_bytes; ++i)
+ {
+ if (write (out_des, zeros_512, 512) != 512)
+ error (1, errno, "error writing NUL's");
+ }
+ if (extra_bytes != 0)
+ {
+ if (write (out_des, zeros_512, extra_bytes) != extra_bytes)
+ error (1, errno, "error writing NUL's");
+ }
+}
/* The version number of cpio and mt. */
-char *version_string = "version 2.3\n";
+char *version_string = "version 2.4.2\n";
/* xmalloc.c -- malloc with out of memory checking
- Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-#ifdef STDC_HEADERS
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if __STDC__
+#define VOID void
+#else
+#define VOID char
+#endif
+
+#include <sys/types.h>
+
+#if STDC_HEADERS
#include <stdlib.h>
#else
-char *malloc ();
-char *realloc ();
+VOID *malloc ();
+VOID *realloc ();
void free ();
#endif
+/* This is for other GNU distributions with internationalized messages.
+ The GNU C Library itself does not yet support such messages. */
+#if HAVE_LIBINTL_H
+# include <libintl.h>
+#else
+# define gettext(msgid) (msgid)
+#endif
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+
+/* Exit value when the requested amount of memory is not available.
+ The caller may set it to some other value. */
+int xmalloc_exit_failure = EXIT_FAILURE;
+
+#if __STDC__ && (HAVE_VPRINTF || HAVE_DOPRNT)
+void error (int, int, const char *, ...);
+#else
void error ();
+#endif
+
+static VOID *
+fixup_null_alloc (n)
+ size_t n;
+{
+ VOID *p;
+
+ p = 0;
+ if (n == 0)
+ p = malloc ((size_t) 1);
+ if (p == 0)
+ error (xmalloc_exit_failure, 0, gettext ("Memory exhausted"));
+ return p;
+}
/* Allocate N bytes of memory dynamically, with error checking. */
-char *
+VOID *
xmalloc (n)
- unsigned n;
+ size_t n;
{
- char *p;
+ VOID *p;
p = malloc (n);
if (p == 0)
- /* Must exit with 2 for `cmp'. */
- error (2, 0, "virtual memory exhausted");
+ p = fixup_null_alloc (n);
return p;
}
/* Change the size of an allocated block of memory P to N bytes,
with error checking.
- If P is NULL, run xmalloc.
- If N is 0, run free and return NULL. */
+ If P is NULL, run xmalloc. */
-char *
+VOID *
xrealloc (p, n)
- char *p;
- unsigned n;
+ VOID *p;
+ size_t n;
{
if (p == 0)
return xmalloc (n);
- if (n == 0)
- {
- free (p);
- return 0;
- }
p = realloc (p, n);
if (p == 0)
- /* Must exit with 2 for `cmp'. */
- error (2, 0, "virtual memory exhausted");
+ p = fixup_null_alloc (n);
return p;
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#else