aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2004-02-27 13:28:40 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2004-02-27 13:28:40 +0000
commita783e2c18c6b566b2f4c2b06e6c388a9645c826c (patch)
treeae12abc157dee99bd4c67bab25316be06d3519a2 /src
parentcb721df9888a296af824a4acab4916694d6dc35d (diff)
downloadcpio-a783e2c18c6b566b2f4c2b06e6c388a9645c826c.tar.gz
cpio-a783e2c18c6b566b2f4c2b06e6c388a9645c826c.tar.bz2
Added to the repository
Diffstat (limited to 'src')
-rw-r--r--src/.cvsignore11
-rw-r--r--src/Makefile.am81
-rw-r--r--src/alloca.c495
-rw-r--r--src/argmatch.c87
-rw-r--r--src/bcopy.c19
-rw-r--r--src/copyin.c1605
-rw-r--r--src/copyout.c827
-rw-r--r--src/copypass.c482
-rw-r--r--src/cpio.h69
-rw-r--r--src/cpiohdr.h90
-rw-r--r--src/defer.c46
-rw-r--r--src/defer.h25
-rw-r--r--src/dirname.c70
-rw-r--r--src/dstring.c118
-rw-r--r--src/dstring.h49
-rw-r--r--src/error.c109
-rw-r--r--src/extern.h198
-rw-r--r--src/filemode.c255
-rw-r--r--src/filetypes.h84
-rw-r--r--src/fnmatch.c200
-rw-r--r--src/fnmatch.h67
-rw-r--r--src/getopt.c765
-rw-r--r--src/getopt.h129
-rw-r--r--src/getopt1.c180
-rw-r--r--src/gettext.h68
-rw-r--r--src/global.c204
-rw-r--r--src/idcache.c210
-rw-r--r--src/main.c550
-rw-r--r--src/makepath.c311
-rw-r--r--src/mkdir.c100
-rw-r--r--src/mt.c366
-rw-r--r--src/rmt.c473
-rw-r--r--src/rmt.h98
-rw-r--r--src/rtapelib.c601
-rw-r--r--src/safe-stat.h1
-rw-r--r--src/strdup.c43
-rw-r--r--src/strerror.c63
-rw-r--r--src/stripslash.c43
-rw-r--r--src/system.h146
-rw-r--r--src/tar.c528
-rw-r--r--src/tar.h112
-rw-r--r--src/tarhdr.h62
-rw-r--r--src/userspec.c265
-rw-r--r--src/util.c1376
-rw-r--r--src/xmalloc.c103
-rw-r--r--src/xstrdup.c36
46 files changed, 11820 insertions, 0 deletions
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644
index 0000000..729dc3f
--- /dev/null
+++ b/src/.cvsignore
@@ -0,0 +1,11 @@
+Makefile.in
+Makefile
+.deps
+.libs
+cpio
+mt
+rmt
+.gdbinit
+*.tar.gz
+*.tar.bz2
+localedir.h
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..1e5da40
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,81 @@
+# This file is part of GNU cpio
+# Copyright (C) 2003, 2004 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 Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+bin_PROGRAMS=cpio @CPIO_MT_PROG@
+libexec_PROGRAMS=@CPIO_RMT_PROG@
+EXTRA_PROGRAMS=mt rmt
+
+cpio_SOURCES = \
+ copyin.c\
+ copyout.c\
+ copypass.c\
+ defer.c\
+ dstring.c\
+ global.c\
+ main.c\
+ tar.c\
+ util.c\
+ error.c\
+ filemode.c\
+ dirname.c\
+ idcache.c\
+ makepath.c\
+ xmalloc.c\
+ stripslash.c\
+ userspec.c\
+ xstrdup.c
+
+noinst_HEADERS =\
+ cpio.h\
+ cpiohdr.h\
+ tar.h\
+ tarhdr.h\
+ defer.h\
+ dstring.h\
+ extern.h\
+ filetypes.h\
+ gettext.h\
+ system.h\
+ rmt.h\
+ safe-stat.h\
+ fnmatch.h\
+ getopt.h
+
+cpio_LDADD = @LIBOBJS@
+
+mt_SOURCES = \
+ mt.c argmatch.c
+mt_LDADD = @LIBOBJS@
+
+rmt_SOURCES = rmt.c
+rmt_LDADD = @LIBOBJS@
+
+EXTRA_DIST=\
+ getopt.c\
+ getopt1.c\
+ bcopy.c\
+ fnmatch.c\
+ mkdir.c\
+ strdup.c
+
+localedir = $(datadir)/locale
+
+DISTCLEANFILES = localedir.h
+localedir.h : Makefile
+ echo '#define LOCALEDIR "$(localedir)"' >$@
+
+mt.o main.o: localedir.h
diff --git a/src/alloca.c b/src/alloca.c
new file mode 100644
index 0000000..7061cec
--- /dev/null
+++ b/src/alloca.c
@@ -0,0 +1,495 @@
+/* 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
+
+#ifdef emacs
+#include "blockinput.h"
+#endif
+
+/* If compiling with GCC 2, this file's not needed. */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+ there must be some other way alloca is supposed to work. */
+#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. */
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+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
+#endif
+extern pointer malloc ();
+
+/* 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. */
+
+#ifdef emacs
+ BLOCK_INPUT;
+#endif
+
+ 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. */
+
+#ifdef emacs
+ UNBLOCK_INPUT;
+#endif
+ }
+
+ if (size == 0)
+ return NULL; /* No allocation required. */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ register pointer new = malloc (sizeof (header) + size);
+ /* Address of header. */
+
+ if (new == 0)
+ abort();
+
+ ((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));
+ }
+}
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#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 /* not GCC version 2 */
diff --git a/src/argmatch.c b/src/argmatch.c
new file mode 100644
index 0000000..d89699b
--- /dev/null
+++ b/src/argmatch.c
@@ -0,0 +1,87 @@
+/* argmatch.c -- find a match for a string in an array
+ Copyright (C) 1990 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 Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by David MacKenzie <djm@ai.mit.edu> */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <string.h>
+#endif
+
+extern char *program_name;
+
+/* If ARG is an unambiguous match for an element of the
+ null-terminated array OPTLIST, return the index in OPTLIST
+ of the matched element, else -1 if it does not match any element
+ or -2 if it is ambiguous (is a prefix of more than one element). */
+
+int
+argmatch (arg, optlist)
+ char *arg;
+ char **optlist;
+{
+ int i; /* Temporary index in OPTLIST. */
+ int arglen; /* Length of ARG. */
+ int matchind = -1; /* Index of first nonexact match. */
+ int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
+
+ arglen = strlen (arg);
+
+ /* Test all elements for either exact match or abbreviated matches. */
+ for (i = 0; optlist[i]; i++)
+ {
+ if (!strncmp (optlist[i], arg, arglen))
+ {
+ if (strlen (optlist[i]) == arglen)
+ /* Exact match found. */
+ return i;
+ else if (matchind == -1)
+ /* First nonexact match found. */
+ matchind = i;
+ else
+ /* Second nonexact match found. */
+ ambiguous = 1;
+ }
+ }
+ if (ambiguous)
+ return -2;
+ else
+ return matchind;
+}
+
+/* Error reporting for argmatch.
+ KIND is a description of the type of entity that was being matched.
+ VALUE is the invalid value that was given.
+ PROBLEM is the return value from argmatch. */
+
+void
+invalid_arg (kind, value, problem)
+ char *kind;
+ char *value;
+ int problem;
+{
+ fprintf (stderr, "%s: ", program_name);
+ if (problem == -1)
+ fprintf (stderr, "invalid");
+ else /* Assume -2. */
+ fprintf (stderr, "ambiguous");
+ fprintf (stderr, " %s `%s'\n", kind, value);
+}
diff --git a/src/bcopy.c b/src/bcopy.c
new file mode 100644
index 0000000..a8991c5
--- /dev/null
+++ b/src/bcopy.c
@@ -0,0 +1,19 @@
+/* bcopy.c -- copy memory.
+ Copy LENGTH bytes from SOURCE to DEST. Does not null-terminate.
+ In the public domain.
+ By David MacKenzie <djm@gnu.ai.mit.edu>. */
+
+void
+bcopy (source, dest, length)
+ char *source, *dest;
+ unsigned length;
+{
+ if (source < dest)
+ /* Moving from low mem to hi mem; start at end. */
+ for (source += length, dest += length; length; --length)
+ *--dest = *--source;
+ else if (source != dest)
+ /* Moving from hi mem to low mem; start at beginning. */
+ for (; length; --length)
+ *dest++ = *source++;
+}
diff --git a/src/copyin.c b/src/copyin.c
new file mode 100644
index 0000000..17e6744
--- /dev/null
+++ b/src/copyin.c
@@ -0,0 +1,1605 @@
+/* copyin.c - extract or list a cpio archive
+ Copyright (C) 1990,1991,1992,2001,2002,2003 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 Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "filetypes.h"
+#include "system.h"
+#include "cpiohdr.h"
+#include "dstring.h"
+#include "extern.h"
+#include "defer.h"
+#include "rmt.h"
+#ifndef FNM_PATHNAME
+#include <fnmatch.h>
+#endif
+
+#ifndef HAVE_LCHOWN
+#define lchown chown
+#endif
+
+static void read_pattern_file ();
+static void tape_skip_padding ();
+static void defer_copyin ();
+static void create_defered_links ();
+static void create_final_defers ();
+static int create_defered_links_to_skipped ();
+static int query_rename();
+static void list_file();
+static void copyin_file();
+static int try_existing_file();
+static void copyin_regular_file();
+static void copyin_directory();
+static void copyin_device();
+static void copyin_link();
+
+/* Return 16-bit integer I with the bytes swapped. */
+#define swab_short(i) ((((i) << 8) & 0xff00) | (((i) >> 8) & 0x00ff))
+
+/* Read the header, including the name of the file, from file
+ descriptor IN_DES into FILE_HDR. */
+
+void
+read_in_header (file_hdr, in_des)
+ struct new_cpio_header *file_hdr;
+ int in_des;
+{
+ long bytes_skipped = 0; /* Bytes of junk found before magic number. */
+
+ /* Search for a valid magic number. */
+
+ if (archive_format == arf_unknown)
+ {
+ char tmpbuf[512];
+ int check_tar;
+ int peeked_bytes;
+
+ while (archive_format == arf_unknown)
+ {
+ peeked_bytes = tape_buffered_peek (tmpbuf, in_des, 512);
+ if (peeked_bytes < 6)
+ error (1, 0, _("premature end of archive"));
+
+ if (!strncmp (tmpbuf, "070701", 6))
+ archive_format = arf_newascii;
+ else if (!strncmp (tmpbuf, "070707", 6))
+ archive_format = arf_oldascii;
+ else if (!strncmp (tmpbuf, "070702", 6))
+ {
+ archive_format = arf_crcascii;
+ crc_i_flag = TRUE;
+ }
+ else if ((*((unsigned short *) tmpbuf) == 070707) ||
+ (*((unsigned short *) tmpbuf) == swab_short ((unsigned short) 070707)))