cvs2svn managed to overlay two different path trees. fix.

This commit is contained in:
peter 2008-07-09 23:07:03 +00:00
parent c36d8046bb
commit bcfb49bc17
39 changed files with 0 additions and 11461 deletions

View File

@ -1,481 +0,0 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
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
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -1,495 +0,0 @@
/* 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 */

File diff suppressed because it is too large Load Diff

View File

@ -1,807 +0,0 @@
/* copyout.c - create a cpio archive
Copyright (C) 1990, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#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"
static unsigned long read_for_checksum ();
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 ();
static void writeout_other_defers ();
static void writeout_final_defers();
static void writeout_defered_file ();
/* Write out header FILE_HDR, including the file name, to file
descriptor OUT_DES. */
void
write_out_header (file_hdr, out_des)
struct new_cpio_header *file_hdr;
int out_des;
{
if (archive_format == arf_newascii || archive_format == arf_crcascii)
{
char ascii_header[112];
char *magic_string;
if (archive_format == arf_crcascii)
magic_string = "070702";
else
magic_string = "070701";
sprintf (ascii_header,
"%6s%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx",
magic_string,
file_hdr->c_ino, file_hdr->c_mode, file_hdr->c_uid,
file_hdr->c_gid, file_hdr->c_nlink, file_hdr->c_mtime,
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);
tape_buffered_write (ascii_header, out_des, 110L);
/* Write file name to output. */
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)
{
char ascii_header[78];
#ifndef __MSDOS__
dev_t dev;
dev_t rdev;
if (archive_format == arf_oldascii)
{
dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
}
else
{
/* HP/UX cpio creates archives that look just like ordinary archives,
but for devices it sets major = 0, minor = 1, and puts the
actual major/minor number in the filesize field. */
switch (file_hdr->c_mode & CP_IFMT)
{
case CP_IFCHR:
case CP_IFBLK:
#ifdef CP_IFSOCK
case CP_IFSOCK:
#endif
#ifdef CP_IFIFO
case CP_IFIFO:
#endif
file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
file_hdr->c_rdev_min);
rdev = 1;
break;
default:
dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
break;
}
}
#else
int dev = 0, rdev = 0;
#endif
if ((file_hdr->c_ino >> 16) != 0)
error (0, 0, "%s: truncating inode number", file_hdr->c_name);
sprintf (ascii_header,
"%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);
tape_buffered_write (ascii_header, out_des, 76L);
/* Write file name to output. */
tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
}
else if (archive_format == arf_tar || archive_format == arf_ustar)
{
write_out_tar_header (file_hdr, out_des);
}
else
{
struct old_cpio_header short_hdr;
short_hdr.c_magic = 070707;
short_hdr.c_dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
if ((file_hdr->c_ino >> 16) != 0)
error (0, 0, "%s: truncating inode number", file_hdr->c_name);
short_hdr.c_ino = file_hdr->c_ino & 0xFFFF;
short_hdr.c_mode = file_hdr->c_mode & 0xFFFF;
short_hdr.c_uid = file_hdr->c_uid & 0xFFFF;
short_hdr.c_gid = file_hdr->c_gid & 0xFFFF;
short_hdr.c_nlink = file_hdr->c_nlink & 0xFFFF;
if (archive_format != arf_hpbinary)
short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
else
{
switch (file_hdr->c_mode & CP_IFMT)
{
/* HP/UX cpio creates archives that look just like ordinary
archives, but for devices it sets major = 0, minor = 1, and
puts the actual major/minor number in the filesize field. */
case CP_IFCHR:
case CP_IFBLK:
#ifdef CP_IFSOCK
case CP_IFSOCK:
#endif
#ifdef CP_IFIFO
case CP_IFIFO:
#endif
file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
file_hdr->c_rdev_min);
short_hdr.c_rdev = makedev (0, 1);
break;
default:
short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj,
file_hdr->c_rdev_min);
break;
}
}
short_hdr.c_mtimes[0] = file_hdr->c_mtime >> 16;
short_hdr.c_mtimes[1] = file_hdr->c_mtime & 0xFFFF;
short_hdr.c_namesize = file_hdr->c_namesize & 0xFFFF;
short_hdr.c_filesizes[0] = file_hdr->c_filesize >> 16;
short_hdr.c_filesizes[1] = file_hdr->c_filesize & 0xFFFF;
/* Output the file header. */
tape_buffered_write ((char *) &short_hdr, out_des, 26L);
/* Write file name to output. */
tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
tape_pad_output (out_des, file_hdr->c_namesize + 26);
}
}
/* Read a list of file names from the standard input
and write a cpio collection on the standard output.
The format of the header depends on the compatibility (-c) flag. */
void
process_copy_out ()
{
int res; /* Result of functions. */
dynamic_string input_name; /* Name of file read from stdin. */
struct utimbuf times; /* For resetting file times after copy. */
struct stat file_stat; /* Stat record for file. */
struct new_cpio_header file_hdr; /* Output header information. */
int in_file_des; /* Source file descriptor. */
int out_file_des; /* Output file descriptor. */
char *p;
/* Initialize the copy out. */
ds_init (&input_name, 128);
/* Initialize this in case it has members we don't know to set. */
bzero (&times, sizeof (struct utimbuf));
file_hdr.c_magic = 070707;
#ifdef __MSDOS__
setmode (archive_des, O_BINARY);
#endif
/* Check whether the output file might be a tape. */
out_file_des = archive_des;
if (_isrmt (out_file_des))
{
output_is_special = 1;
output_is_seekable = 0;
}
else
{
if (fstat (out_file_des, &file_stat))
error (1, errno, "standard output is closed");
output_is_special =
#ifdef S_ISBLK
S_ISBLK (file_stat.st_mode) ||
#endif
S_ISCHR (file_stat.st_mode);
output_is_seekable = S_ISREG (file_stat.st_mode);
}
if (append_flag)
{
process_copy_in ();
prepare_append (out_file_des);
}
/* Copy files with names read from stdin. */
while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
{
/* Check for blank line. */
if (input_name.ds_string[0] == 0)
{
error (0, 0, "blank line ignored");
continue;
}
/* Process next file. */
if ((*xstat) (input_name.ds_string, &file_stat) < 0)
error (0, errno, "%s", input_name.ds_string);
else
{
/* Set values in output header. */
file_hdr.c_dev_maj = major (file_stat.st_dev);
file_hdr.c_dev_min = minor (file_stat.st_dev);
file_hdr.c_ino = file_stat.st_ino;
/* For POSIX systems that don't define the S_IF macros,
we can't assume that S_ISfoo means the standard Unix
S_IFfoo bit(s) are set. So do it manually, with a
different name. Bleah. */
file_hdr.c_mode = (file_stat.st_mode & 07777);
if (S_ISREG (file_stat.st_mode))
file_hdr.c_mode |= CP_IFREG;
else if (S_ISDIR (file_stat.st_mode))
file_hdr.c_mode |= CP_IFDIR;
#ifdef S_ISBLK
else if (S_ISBLK (file_stat.st_mode))
file_hdr.c_mode |= CP_IFBLK;
#endif
#ifdef S_ISCHR
else if (S_ISCHR (file_stat.st_mode))
file_hdr.c_mode |= CP_IFCHR;
#endif
#ifdef S_ISFIFO
else if (S_ISFIFO (file_stat.st_mode))
file_hdr.c_mode |= CP_IFIFO;
#endif
#ifdef S_ISLNK
else if (S_ISLNK (file_stat.st_mode))
file_hdr.c_mode |= CP_IFLNK;
#endif
#ifdef S_ISSOCK
else if (S_ISSOCK (file_stat.st_mode))
file_hdr.c_mode |= CP_IFSOCK;
#endif
#ifdef S_ISNWK
else if (S_ISNWK (file_stat.st_mode))
file_hdr.c_mode |= CP_IFNWK;
#endif
file_hdr.c_uid = file_stat.st_uid;
file_hdr.c_gid = file_stat.st_gid;
file_hdr.c_nlink = file_stat.st_nlink;
file_hdr.c_rdev_maj = major (file_stat.st_rdev);
file_hdr.c_rdev_min = minor (file_stat.st_rdev);
file_hdr.c_mtime = file_stat.st_mtime;
file_hdr.c_filesize = file_stat.st_size;
file_hdr.c_chksum = 0;
file_hdr.c_tar_linkname = NULL;
/* Strip leading `./' from the filename. */
p = input_name.ds_string;
while (*p == '.' && *(p + 1) == '/')
{
++p;
while (*p == '/')
++p;
}
#ifndef HPUX_CDF
file_hdr.c_name = p;
file_hdr.c_namesize = strlen (p) + 1;
#else
if ( (archive_format != arf_tar) && (archive_format != arf_ustar) )
{
/* We mark CDF's in cpio files by adding a 2nd `/' after the
"hidden" directory name. We need to do this so we can
properly recreate the directory as hidden (in case the
files of a directory go into the archive before the
directory itself (e.g from "find ... -depth ... | cpio")). */
file_hdr.c_name = add_cdf_double_slashes (p);
file_hdr.c_namesize = strlen (file_hdr.c_name) + 1;
}
else
{
/* We don't mark CDF's in tar files. We assume the "hidden"
directory will always go into the archive before any of
its files. */
file_hdr.c_name = p;
file_hdr.c_namesize = strlen (p) + 1;
}
#endif
if ((archive_format == arf_tar || archive_format == arf_ustar)
&& is_tar_filename_too_long (file_hdr.c_name))
{
error (0, 0, "%s: file name too long", file_hdr.c_name);
continue;
}
/* Copy the named file to the output. */
switch (file_hdr.c_mode & CP_IFMT)
{
case CP_IFREG:
#ifndef __MSDOS__
if (archive_format == arf_tar || archive_format == arf_ustar)
{
char *otherfile;
if ((otherfile = find_inode_file (file_hdr.c_ino,
file_hdr.c_dev_maj,
file_hdr.c_dev_min)))
{
file_hdr.c_tar_linkname = otherfile;
write_out_header (&file_hdr, out_file_des);
break;
}
}
if ( (archive_format == arf_newascii || archive_format == arf_crcascii)
&& (file_hdr.c_nlink > 1) )
{
if (last_link (&file_hdr) )
{
writeout_other_defers (&file_hdr, out_file_des);
}
else
{
add_link_defer (&file_hdr);
break;
}
}
#endif
in_file_des = open (input_name.ds_string,
O_RDONLY | O_BINARY, 0);
if (in_file_des < 0)
{
error (0, errno, "%s", input_name.ds_string);
continue;
}
if (archive_format == arf_crcascii)
file_hdr.c_chksum = read_for_checksum (in_file_des,
file_hdr.c_filesize,
input_name.ds_string);
write_out_header (&file_hdr, out_file_des);
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)
add_inode (file_hdr.c_ino, file_hdr.c_name, file_hdr.c_dev_maj,
file_hdr.c_dev_min);
#endif
tape_pad_output (out_file_des, file_hdr.c_filesize);
if (close (in_file_des) < 0)
error (0, errno, "%s", input_name.ds_string);
if (reset_time_flag)
{
times.actime = file_stat.st_atime;
times.modtime = file_stat.st_mtime;
if (utime (file_hdr.c_name, &times) < 0)
error (0, errno, "%s", file_hdr.c_name);
}
break;
case CP_IFDIR:
file_hdr.c_filesize = 0;
write_out_header (&file_hdr, out_file_des);
break;
#ifndef __MSDOS__
case CP_IFCHR:
case CP_IFBLK:
#ifdef CP_IFSOCK
case CP_IFSOCK:
#endif
#ifdef CP_IFIFO
case CP_IFIFO:
#endif
if (archive_format == arf_tar)
{
error (0, 0, "%s not dumped: not a regular file",
file_hdr.c_name);
continue;
}
else if (archive_format == arf_ustar)
{
char *otherfile;
if ((otherfile = find_inode_file (file_hdr.c_ino,
file_hdr.c_dev_maj,
file_hdr.c_dev_min)))
{
/* This file is linked to another file already in the
archive, so write it out as a hard link. */
file_hdr.c_mode = (file_stat.st_mode & 07777);
file_hdr.c_mode |= CP_IFREG;
file_hdr.c_tar_linkname = otherfile;
write_out_header (&file_hdr, out_file_des);
break;
}
add_inode (file_hdr.c_ino, file_hdr.c_name,
file_hdr.c_dev_maj, file_hdr.c_dev_min);
}
file_hdr.c_filesize = 0;
write_out_header (&file_hdr, out_file_des);
break;
#endif
#ifdef CP_IFLNK
case CP_IFLNK:
{
char *link_name = (char *) xmalloc (file_stat.st_size + 1);
int link_size;
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 (link_size + 1 > 100)
{
error (0, 0, "%s: symbolic link too long",
file_hdr.c_name);
}
else
{
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);
tape_buffered_write (link_name, out_file_des, link_size);
tape_pad_output (out_file_des, link_size);
}
free (link_name);
}
break;
#endif
default:
error (0, 0, "%s: unknown file type", input_name.ds_string);
}
if (verbose_flag)
fprintf (stderr, "%s\n", input_name.ds_string);
if (dot_flag)
fputc ('.', stderr);
}
}
writeout_final_defers(out_file_des);
/* The collection is complete; append the trailer. */
file_hdr.c_ino = 0;
file_hdr.c_mode = 0;
file_hdr.c_uid = 0;
file_hdr.c_gid = 0;
file_hdr.c_nlink = 1; /* Must be 1 for crc format. */
file_hdr.c_dev_maj = 0;
file_hdr.c_dev_min = 0;
file_hdr.c_rdev_maj = 0;
file_hdr.c_rdev_min = 0;
file_hdr.c_mtime = 0;
file_hdr.c_chksum = 0;
file_hdr.c_filesize = 0;
file_hdr.c_namesize = 11;
file_hdr.c_name = "TRAILER!!!";
if (archive_format != arf_tar && archive_format != arf_ustar)
write_out_header (&file_hdr, out_file_des);
else
{
tape_buffered_write (zeros_512, out_file_des, 512);
tape_buffered_write (zeros_512, out_file_des, 512);
}
/* Fill up the output block. */
tape_clear_rest_of_block (out_file_des);
tape_empty_output_buffer (out_file_des);
if (dot_flag)
fputc ('\n', stderr);
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
compute and return a checksum for them. */
static unsigned long
read_for_checksum (in_file_des, file_size, file_name)
int in_file_des;
int file_size;
char *file_name;
{
unsigned long crc;
char buf[BUFSIZ];
int bytes_left;
int bytes_read;
int i;
crc = 0;
for (bytes_left = file_size; bytes_left > 0; bytes_left -= bytes_read)
{
bytes_read = read (in_file_des, buf, BUFSIZ);
if (bytes_read < 0)
error (1, errno, "cannot read checksum for %s", file_name);
if (bytes_read == 0)
break;
for (i = 0; i < bytes_read; ++i)
crc += buf[i] & 0xff;
}
if (lseek (in_file_des, 0L, SEEK_SET))
error (1, errno, "cannot read checksum for %s", file_name);
return crc;
}
/* Write out NULs to fill out the rest of the current block on
OUT_FILE_DES. */
static void
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)
tape_buffered_write (zeros_512, out_file_des, 512);
else
tape_buffered_write (zeros_512, out_file_des, io_block_size - output_size);
}
}
/* Write NULs on OUT_FILE_DES to move from OFFSET (the current location)
to the end of the header. */
static void
tape_pad_output (out_file_des, offset)
int out_file_des;
int offset;
{
int pad;
if (archive_format == arf_newascii || archive_format == arf_crcascii)
pad = (4 - (offset % 4)) % 4;
else if (archive_format == arf_tar || archive_format == arf_ustar)
pad = (512 - (offset % 512)) % 512;
else if (archive_format != arf_oldascii && archive_format != arf_hpoldascii)
pad = (2 - (offset % 2)) % 2;
else
pad = 0;
if (pad != 0)
tape_buffered_write (zeros_512, out_file_des, pad);
}
/* When creating newc and crc archives if a file has multiple (hard)
links, we don't put any of them into the archive until we have seen
all of them (or until we get to the end of the list of files that
are going into the archive and know that we have seen all of the links
to the file that we will see). We keep these "defered" files on
this list. */
struct deferment *deferouts = NULL;
/* Is this file_hdr the last (hard) link to a file? I.e., have
we already seen and defered all of the other links? */
static int
last_link (file_hdr)
struct new_cpio_header *file_hdr;
{
int other_files_sofar;
other_files_sofar = count_defered_links_to_dev_ino (file_hdr);
if (file_hdr->c_nlink == (other_files_sofar + 1) )
{
return 1;
}
return 0;
}
/* Count the number of other (hard) links to this file that have
already been defered. */
static int
count_defered_links_to_dev_ino (file_hdr)
struct new_cpio_header *file_hdr;
{
struct deferment *d;
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;
count = 0;
for (d = deferouts; d != NULL; d = d->next)
{
if ( (d->header.c_ino == ino) && (d->header.c_dev_maj == maj)
&& (d->header.c_dev_min == min) )
++count;
}
return count;
}
/* Add the file header for a link that is being defered to the deferouts
list. */
static void
add_link_defer (file_hdr)
struct new_cpio_header *file_hdr;
{
struct deferment *d;
d = create_deferment (file_hdr);
d->next = deferouts;
deferouts = d;
}
/* We are about to put a file into a newc or crc archive that is
multiply linked. We have already seen and defered all of the
other links to the file but haven't written them into the archive.
Write the other links into the archive, and remove them from the
deferouts list. */
static void
writeout_other_defers (file_hdr, out_des)
struct new_cpio_header *file_hdr;
int out_des;
{
struct deferment *d;
struct deferment *d_prev;
int ino;
int maj;
int min;
ino = file_hdr->c_ino;
maj = file_hdr->c_dev_maj;
min = file_hdr->c_dev_min;
d_prev = NULL;
d = deferouts;
while (d != NULL)
{
if ( (d->header.c_ino == ino) && (d->header.c_dev_maj == maj)
&& (d->header.c_dev_min == min) )
{
struct deferment *d_free;
d->header.c_filesize = 0;
write_out_header (&d->header, out_des);
if (d_prev != NULL)
d_prev->next = d->next;
else
deferouts = d->next;
d_free = d;
d = d->next;
free_deferment (d_free);
}
else
{
d_prev = d;
d = d->next;
}
}
return;
}
/* When writing newc and crc format archives we defer multiply linked
files until we have seen all of the links to the file. If a file
has links to it that aren't going into the archive, then we will
never see the "last" link to the file, so at the end we just write
all of the leftover defered files into the archive. */
static void
writeout_final_defers(out_des)
int out_des;
{
struct deferment *d;
int other_count;
while (deferouts != NULL)
{
d = deferouts;
other_count = count_defered_links_to_dev_ino (&d->header);
if (other_count == 1)
{
writeout_defered_file (&d->header, out_des);
}
else
{
struct new_cpio_header file_hdr;
file_hdr = d->header;
file_hdr.c_filesize = 0;
write_out_header (&file_hdr, out_des);
}
deferouts = deferouts->next;
}
}
/* Write a file into the archive. This code is the same as
the code in process_copy_out(), but we need it here too
for writeout_final_defers() to call. */
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;
struct utimbuf times; /* For setting file times. */
/* Initialize this in case it has members we don't know to set. */
bzero (&times, sizeof (struct utimbuf));
file_hdr = *header;
in_file_des = open (header->c_name,
O_RDONLY | O_BINARY, 0);
if (in_file_des < 0)
{
error (0, errno, "%s", header->c_name);
return;
}
if (archive_format == arf_crcascii)
file_hdr.c_chksum = read_for_checksum (in_file_des,
file_hdr.c_filesize,
header->c_name);
write_out_header (&file_hdr, out_file_des);
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)
add_inode (file_hdr.c_ino, file_hdr.c_name, file_hdr.c_dev_maj,
file_hdr.c_dev_min);
#endif
tape_pad_output (out_file_des, file_hdr.c_filesize);
if (close (in_file_des) < 0)
error (0, errno, "%s", header->c_name);
if (reset_time_flag)
{
times.actime = file_hdr.c_mtime;
times.modtime = file_hdr.c_mtime;
if (utime (file_hdr.c_name, &times) < 0)
error (0, errno, "%s", file_hdr.c_name);
}
return;
}

View File

@ -1,464 +0,0 @@
/* copypass.c - cpio copy pass sub-function.
Copyright (C) 1990, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#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"
#ifndef HAVE_LCHOWN
#define lchown chown
#endif
/* Copy files listed on the standard input into directory `directory_name'.
If `link_flag', link instead of copying. */
void
process_copy_pass ()
{
dynamic_string input_name; /* Name of file from stdin. */
dynamic_string output_name; /* Name of new file. */
int dirname_len; /* Length of `directory_name'. */
int res; /* Result of functions. */
char *slash; /* For moving past slashes in input name. */
struct utimbuf times; /* For resetting file times after copy. */
struct stat in_file_stat; /* Stat record for input file. */
struct stat out_file_stat; /* Stat record for output file. */
int in_file_des; /* Input file descriptor. */
int out_file_des; /* Output file descriptor. */
int existing_dir; /* True if file is a dir & already exists. */
#ifdef HPUX_CDF
int cdf_flag;
int cdf_char;
#endif
/* Initialize the copy pass. */
dirname_len = strlen (directory_name);
ds_init (&input_name, 128);
ds_init (&output_name, dirname_len + 2);
strcpy (output_name.ds_string, directory_name);
output_name.ds_string[dirname_len] = '/';
output_is_seekable = TRUE;
/* Initialize this in case it has members we don't know to set. */
bzero (&times, sizeof (struct utimbuf));
/* Copy files with names read from stdin. */
while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
{
int link_res = -1;
/* Check for blank line and ignore it if found. */
if (input_name.ds_string[0] == '\0')
{
error (0, 0, "blank line ignored");
continue;
}
/* Check for current directory and ignore it if found. */
if (input_name.ds_string[0] == '.'
&& (input_name.ds_string[1] == '\0'
|| (input_name.ds_string[1] == '/'
&& input_name.ds_string[2] == '\0')))
continue;
if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
{
error (0, errno, "%s", input_name.ds_string);
continue;
}
/* Make the name of the new file. */
for (slash = input_name.ds_string; *slash == '/'; ++slash)
;
#ifdef HPUX_CDF
/* For CDF's we add a 2nd `/' after all "hidden" directories.
This kind of a kludge, but it's what we do when creating
archives, and it's easier to do this than to separately
keep track of which directories in a path are "hidden". */
slash = add_cdf_double_slashes (slash);
#endif
ds_resize (&output_name, dirname_len + strlen (slash) + 2);
strcpy (output_name.ds_string + dirname_len + 1, slash);
existing_dir = FALSE;
if (lstat (output_name.ds_string, &out_file_stat) == 0)
{
if (S_ISDIR (out_file_stat.st_mode)
&& S_ISDIR (in_file_stat.st_mode))
{
/* If there is already a directory there that
we are trying to create, don't complain about it. */
existing_dir = TRUE;
}
else if (!unconditional_flag
&& in_file_stat.st_mtime <= out_file_stat.st_mtime)
{
error (0, 0, "%s not created: newer or same age version exists",
output_name.ds_string);
continue; /* Go to the next file. */
}
else if (S_ISDIR (out_file_stat.st_mode)
? rmdir (output_name.ds_string)
: unlink (output_name.ds_string))
{
error (0, errno, "cannot remove current %s",
output_name.ds_string);
continue; /* Go to the next file. */
}
}
/* Do the real copy or link. */
if (S_ISREG (in_file_stat.st_mode))
{
#ifndef __MSDOS__
/* Can the current file be linked to a another file?
Set link_name to the original file name. */
if (link_flag)
/* User said to link it if possible. Try and link to
the original copy. If that fails we'll still try
and link to a copy we've already made. */
link_res = link_to_name (output_name.ds_string,
input_name.ds_string);
if ( (link_res < 0) && (in_file_stat.st_nlink > 1) )
link_res = link_to_maj_min_ino (output_name.ds_string,
major (in_file_stat.st_dev),
minor (in_file_stat.st_dev),
in_file_stat.st_ino);
#endif
/* If the file was not linked, copy contents of file. */
if (link_res < 0)
{
in_file_des = open (input_name.ds_string,
O_RDONLY | O_BINARY, 0);
if (in_file_des < 0)
{
error (0, errno, "%s", input_name.ds_string);
continue;
}
out_file_des = open (output_name.ds_string,
O_CREAT | O_WRONLY | O_BINARY, 0600);
if (out_file_des < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
out_file_des = open (output_name.ds_string,
O_CREAT | O_WRONLY | O_BINARY, 0600);
}
if (out_file_des < 0)
{
error (0, errno, "%s", output_name.ds_string);
close (in_file_des);
continue;
}
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)
error (0, errno, "%s", output_name.ds_string);
/* Set the attributes of the new file. */
if (!no_chown_flag)
if ((chown (output_name.ds_string,
set_owner_flag ? set_owner : in_file_stat.st_uid,
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
/* chown may have turned off some permissions we wanted. */
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
error (0, errno, "%s", output_name.ds_string);
if (reset_time_flag)
{
times.actime = in_file_stat.st_atime;
times.modtime = in_file_stat.st_mtime;
if (utime (input_name.ds_string, &times) < 0)
error (0, errno, "%s", input_name.ds_string);
if (utime (output_name.ds_string, &times) < 0)
error (0, errno, "%s", output_name.ds_string);
}
if (retain_time_flag)
{
times.actime = times.modtime = in_file_stat.st_mtime;
if (utime (output_name.ds_string, &times) < 0)
error (0, errno, "%s", output_name.ds_string);
}
}
}
else if (S_ISDIR (in_file_stat.st_mode))
{
#ifdef HPUX_CDF
cdf_flag = 0;
#endif
if (!existing_dir)
{
#ifdef HPUX_CDF
/* If the directory name ends in a + and is SUID,
then it is a CDF. Strip the trailing + from the name
before creating it. */
cdf_char = strlen (output_name.ds_string) - 1;
if ( (cdf_char > 0) &&
(in_file_stat.st_mode & 04000) &&
(output_name.ds_string [cdf_char] == '+') )
{
output_name.ds_string [cdf_char] = '\0';
cdf_flag = 1;
}
#endif
res = mkdir (output_name.ds_string, in_file_stat.st_mode);
}
else
res = 0;
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
res = mkdir (output_name.ds_string, in_file_stat.st_mode);
}
if (res < 0)
{
/* 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,
set_owner_flag ? set_owner : in_file_stat.st_uid,
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
/* chown may have turned off some permissions we wanted. */
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
error (0, errno, "%s", output_name.ds_string);
#ifdef HPUX_CDF
if (cdf_flag)
/* Once we "hide" the directory with the chmod(),
we have to refer to it using name+ isntead of name. */
output_name.ds_string [cdf_char] = '+';
#endif
if (retain_time_flag)
{
times.actime = times.modtime = in_file_stat.st_mtime;
if (utime (output_name.ds_string, &times) < 0)
error (0, errno, "%s", output_name.ds_string);
}
}
#ifndef __MSDOS__
else if (S_ISCHR (in_file_stat.st_mode) ||
S_ISBLK (in_file_stat.st_mode) ||
#ifdef S_ISFIFO
S_ISFIFO (in_file_stat.st_mode) ||
#endif
#ifdef S_ISSOCK
S_ISSOCK (in_file_stat.st_mode) ||
#endif
0)
{
/* Can the current file be linked to a another file?
Set link_name to the original file name. */
if (link_flag)
/* User said to link it if possible. */
link_res = link_to_name (output_name.ds_string,
input_name.ds_string);
if ( (link_res < 0) && (in_file_stat.st_nlink > 1) )
link_res = link_to_maj_min_ino (output_name.ds_string,
major (in_file_stat.st_dev),
minor (in_file_stat.st_dev),
in_file_stat.st_ino);
if (link_res < 0)
{
res = mknod (output_name.ds_string, in_file_stat.st_mode,
in_file_stat.st_rdev);
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
res = mknod (output_name.ds_string, in_file_stat.st_mode,
in_file_stat.st_rdev);
}
if (res < 0)
{
error (0, errno, "%s", output_name.ds_string);
continue;
}
if (!no_chown_flag)
if ((chown (output_name.ds_string,
set_owner_flag ? set_owner : in_file_stat.st_uid,
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
/* chown may have turned off some permissions we wanted. */
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
error (0, errno, "%s", output_name.ds_string);
if (retain_time_flag)
{
times.actime = times.modtime = in_file_stat.st_mtime;
if (utime (output_name.ds_string, &times) < 0)
error (0, errno, "%s", output_name.ds_string);
}
}
}
#endif
#ifdef S_ISLNK
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);
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[link_size] = '\0';
res = UMASKED_SYMLINK (link_name, output_name.ds_string,
in_file_stat.st_mode);
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
res = UMASKED_SYMLINK (link_name, output_name.ds_string,
in_file_stat.st_mode);
}
if (res < 0)
{
error (0, errno, "%s", output_name.ds_string);
free (link_name);
continue;
}
/* Set the attributes of the new link. */
if (!no_chown_flag)
if ((lchown (output_name.ds_string,
set_owner_flag ? set_owner : in_file_stat.st_uid,
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
free (link_name);
}
#endif
else
{
error (0, 0, "%s: unknown file type", input_name.ds_string);
}
if (verbose_flag)
fprintf (stderr, "%s\n", output_name.ds_string);
if (dot_flag)
fputc ('.', stderr);
}
if (dot_flag)
fputc ('\n', stderr);
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);
}
}
/* Try and create a hard link from FILE_NAME to another file
with the given major/minor device number and inode. If no other
file with the same major/minor/inode numbers is known, add this file
to the list of known files and associated major/minor/inode numbers
and return -1. If another file with the same major/minor/inode
numbers is found, try and create another link to it using
link_to_name, and return 0 for success and -1 for failure. */
int
link_to_maj_min_ino (file_name, st_dev_maj, st_dev_min, st_ino)
char *file_name;
int st_dev_maj;
int st_dev_min;
int st_ino;
{
int link_res;
char *link_name;
link_res = -1;
#ifndef __MSDOS__
/* Is the file a link to a previously copied file? */
link_name = find_inode_file (st_ino,
st_dev_maj,
st_dev_min);
if (link_name == NULL)
add_inode (st_ino, file_name,
st_dev_maj,
st_dev_min);
else
link_res = link_to_name (file_name, link_name);
#endif
return link_res;
}
/* Try and create a hard link from LINK_NAME to LINK_TARGET. If
`create_dir_flag' is set, any non-existent (parent) directories
needed by LINK_NAME will be created. If the link is successfully
created and `verbose_flag' is set, print "LINK_TARGET linked to LINK_NAME\n".
If the link can not be created and `link_flag' is set, print
"cannot link LINK_TARGET to LINK_NAME\n". Return 0 if the link
is created, -1 otherwise. */
int
link_to_name (link_name, link_target)
char *link_name;
char *link_target;
{
int res;
#ifdef __MSDOS__
res = -1;
#else /* not __MSDOS__ */
res = link (link_target, link_name);
if (res < 0 && create_dir_flag)
{
create_all_directories (link_name);
res = link (link_target, link_name);
}
if (res == 0)
{
if (verbose_flag)
error (0, 0, "%s linked to %s",
link_target, link_name);
}
else if (link_flag)
{
error (0, errno, "cannot link %s to %s",
link_target, link_name);
}
#endif /* not __MSDOS__ */
return res;
}

View File

@ -1,326 +0,0 @@
.TH CPIO 1L \" -*- nroff -*-
.SH NAME
cpio \- copy files to and from archives
.SH SYNOPSIS
.B cpio
{\-o|\-\-create} [\-0acvABLV] [\-C bytes] [\-H format] [\-M message]
[\-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] [\-\-quiet]
[\-\-force\-local] [\-\-help] [\-\-version] < name-list [> archive]
.B 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]
[\-\-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] [\-\-quiet]
[\-\-preserve-modification-time] [\-\-unconditional] [\-\-verbose] [\-\-dot]
[\-\-dereference] [\-\-owner=[user][:.][group]] [\-\-no-preserve-owner]
[\-\-sparse] [\-\-help] [\-\-version] destination-directory < name-list
.SH DESCRIPTION
This manual page
documents the GNU version of
.BR cpio .
.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
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.
.PP
In copy-out mode,
.B 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
.B find
command; you should give
.B find
the \-depth option to minimize problems with permissions on
directories that are unwritable or not searchable.
.PP
In copy-in mode,
.B 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.
.PP
In copy-pass mode,
.B 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.
.PP
.B cpio
supports the following archive formats: binary, old ASCII, new
ASCII, crc, HPUX binary, HPUX old ASCII, old tar, and POSIX.1 tar.
The binary format
is obsolete because it encodes information about the files in a way
that is not portable between different machine architectures.
The old ASCII format is portable between different machine architectures,
but should not be used on file systems with more than 65536 i-nodes.
The new ASCII format is portable between different machine architectures
and can be used on any size file system, but is not supported by all
versions of
.BR cpio ;
currently, it is only supported by GNU and Unix System V R4.
The crc format is
like the new ASCII format, but also contains a checksum for each file
which
.B cpio
calculates when creating an archive
and verifies when the file is extracted from the archive.
The HPUX formats are provided for compatibility with HPUX's cpio which
stores device files differently.
.PP
The tar format is provided for compatability with
the
.B tar
program. It can not be used to archive files with names
longer than 100 characters, and can not be used to archive "special"
(block or character devices) files.
The POSIX.1 tar format can not be used to archive files with names longer
than 255 characters (less unless they have a "/" in just the right place).
.PP
By default,
.B cpio
creates binary format archives, for compatibility with
older
.B cpio
programs.
When extracting from archives,
.B cpio
automatically recognizes which kind of archive it is reading and can
read archives created on machines with a different byte-order.
.PP
Some of the options to
.B cpio
apply only to certain operating modes; see the SYNOPSIS section for a
list of which options are allowed in which modes.
.SS OPTIONS
.TP
.I "\-0, \-\-null"
In copy-out and copy-pass modes, 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
.B find
is one way to produce a list of null-terminated filenames.
.TP
.I "\-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.
.TP
.I "\-A, \-\-append"
Append to an existing archive. Only works in copy-out mode. The
archive must be a disk file specified with the
.I \-O
or
.I "\-F (\-\-file)"
option.
.TP
.I "\-b, \-\-swap"
In copy-in mode, swap both halfwords of words and bytes of halfwords
in the data. Equivalent to
.IR "\-sS" .
Use this option to convert 32-bit integers between big-endian and
little-endian machines.
.TP
.I "\-B"
Set the I/O block size to 5120 bytes. Initially the block size is 512
bytes.
.TP
.I "\-\-block-size=BLOCK-SIZE"
Set the I/O block size to BLOCK-SIZE * 512 bytes.
.TP
.I "\-c"
Use the old portable (ASCII) archive format.
.TP
.I "\-C IO-SIZE, \-\-io-size=IO-SIZE"
Set the I/O block size to IO-SIZE bytes.
.TP
.I "\-d, \-\-make-directories"
Create leading directories where needed.
.TP
.I "\-E FILE, \-\-pattern-file=FILE"
In copy-in mode, 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
.BR cpio .
.TP
.I "\-f, \-\-nonmatching"
Only copy files that do not match any of the given patterns.
.TP
.I "\-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).
.TP
.I "\-\-force-local"
With
.IR \-F ,
.IR \-I ,
or
.IR \-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.
.TP
.I "\-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 "bin".
.RS
.IP bin
The obsolete binary format.
.IP odc
The old (POSIX.1) portable format.
.IP newc
The new (SVR4) portable format, which supports file systems having
more than 65536 i-nodes.
.IP crc
The new (SVR4) portable format with a checksum added.
.IP tar
The old tar format.
.IP ustar
The POSIX.1 tar format. Also recognizes GNU
.B tar
archives, which are similar but not identical.
.IP hpbin
The obsolete binary format used by HPUX's cpio (which stores device files
differently).
.IP hpodc
The portable format used by HPUX's cpio (which stores device files differently).
.RE
.TP
.I "\-i, \-\-extract"
Run in copy-in mode.
.TP
.I "\-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).
.TP
.I \-k
Ignored; for compatibility with other versions of
.BR cpio .
.TP
.I "\-l, \-\-link"
Link files instead of copying them, when possible.
.TP
.I "\-L, \-\-dereference"
Dereference symbolic links (copy the files that they point to instead
of copying the links).
.TP
.I "\-m, \-\-preserve-modification-time"
Retain previous file modification times when creating files.
.TP
.I "\-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).
.TP
.I "\-n, \-\-numeric-uid-gid"
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
default for non-root users, so that users on System V don't
inadvertantly give away files.
.TP
.I "\-o, \-\-create"
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).
.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
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.
.TP
.I "\-S, \-\-swap-halfwords"
In copy-in mode, swap the halfwords of each word (4 bytes) in the
files.
.TP
.I "\-t, \-\-list"
Print a table of contents of the input.
.TP
.I "\-u, \-\-unconditional"
Replace all files, without asking whether to replace existing newer
files with older files.
.TP
.I "\-v, \-\-verbose"
List the files processed, or with
.IR \-t ,
give an `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.
.TP
.I "\-V \-\-dot"
Print a "." for each file processed.
.TP
.I "\-\-version"
Print the
.B cpio
program version number and exit.

View File

@ -1,69 +0,0 @@
/* Extended cpio format from POSIX.1.
Copyright (C) 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _CPIO_H
#define _CPIO_H 1
/* A cpio archive consists of a sequence of files.
Each file has a 76 byte header,
a variable length, NUL terminated filename,
and variable length file data.
A header for a filename "TRAILER!!!" indicates the end of the archive. */
/* All the fields in the header are ISO 646 (approximately ASCII) strings
of octal numbers, left padded, not NUL terminated.
Field Name Length in Bytes Notes
c_magic 6 must be "070707"
c_dev 6
c_ino 6
c_mode 6 see below for value
c_uid 6
c_gid 6
c_nlink 6
c_rdev 6 only valid for chr and blk special files
c_mtime 11
c_namesize 6 count includes terminating NUL in pathname
c_filesize 11 must be 0 for FIFOs and directories */
/* Values for c_mode, OR'd together: */
#define C_IRUSR 000400
#define C_IWUSR 000200
#define C_IXUSR 000100
#define C_IRGRP 000040
#define C_IWGRP 000020
#define C_IXGRP 000010
#define C_IROTH 000004
#define C_IWOTH 000002
#define C_IXOTH 000001
#define C_ISUID 004000
#define C_ISGID 002000
#define C_ISVTX 001000
#define C_ISBLK 060000
#define C_ISCHR 020000
#define C_ISDIR 040000
#define C_ISFIFO 010000
#define C_ISSOCK 0140000
#define C_ISLNK 0120000
#define C_ISCTG 0110000
#define C_ISREG 0100000
#endif /* cpio.h */

View File

@ -1,558 +0,0 @@
\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

View File

@ -1,90 +0,0 @@
/* Extended cpio header from POSIX.1.
Copyright (C) 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _CPIOHDR_H
#define _CPIOHDR_H 1
#include <cpio.h>
struct old_cpio_header
{
unsigned short c_magic;
short c_dev;
unsigned short c_ino;
unsigned short c_mode;
unsigned short c_uid;
unsigned short c_gid;
unsigned short c_nlink;
short c_rdev;
unsigned short c_mtimes[2];
unsigned short c_namesize;
unsigned short c_filesizes[2];
unsigned long c_mtime; /* Long-aligned copy of `c_mtimes'. */
unsigned long c_filesize; /* Long-aligned copy of `c_filesizes'. */
char *c_name;
};
/* "New" portable format and CRC format:
Each file has a 110 byte header,
a variable length, NUL terminated filename,
and variable length file data.
A header for a filename "TRAILER!!!" indicates the end of the archive. */
/* All the fields in the header are ISO 646 (approximately ASCII) strings
of hexadecimal numbers, left padded, not NUL terminated.
Field Name Length in Bytes Notes
c_magic 6 "070701" for "new" portable format
"070702" for CRC format
c_ino 8
c_mode 8
c_uid 8
c_gid 8
c_nlink 8
c_mtime 8
c_filesize 8 must be 0 for FIFOs and directories
c_maj 8
c_min 8
c_rmaj 8 only valid for chr and blk special files
c_rmin 8 only valid for chr and blk special files
c_namesize 8 count includes terminating NUL in pathname
c_chksum 8 0 for "new" portable format; for CRC format
the sum of all the bytes in the file */
struct new_cpio_header
{
unsigned short c_magic;
unsigned long c_ino;
unsigned long c_mode;
unsigned long c_uid;
unsigned long c_gid;
unsigned long c_nlink;
unsigned long c_mtime;
unsigned long c_filesize;
long c_dev_maj;
long c_dev_min;
long c_rdev_maj;
long c_rdev_min;
unsigned long c_namesize;
unsigned long c_chksum;
char *c_name;
char *c_tar_linkname;
};
#endif /* cpiohdr.h */

View File

@ -1,43 +0,0 @@
/* defer.c - handle "defered" links in newc and crc archives
Copyright (C) 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
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <sys/types.h>
#include "system.h"
#include "cpiohdr.h"
#include "extern.h"
#include "defer.h"
struct deferment *
create_deferment (file_hdr)
struct new_cpio_header *file_hdr;
{
struct deferment *d;
d = (struct deferment *) xmalloc (sizeof (struct deferment) );
d->header = *file_hdr;
d->header.c_name = (char *) xmalloc (strlen (file_hdr->c_name) + 1);
strcpy (d->header.c_name, file_hdr->c_name);
return d;
}
void
free_deferment (d)
struct deferment *d;
{
free (d->header.c_name);
free (d);
}

View File

@ -1,8 +0,0 @@
struct deferment
{
struct deferment *next;
struct new_cpio_header header;
};
struct deferment *create_deferment P_((struct new_cpio_header *file_hdr));
void free_deferment P_((struct deferment *d));

View File

@ -1,70 +0,0 @@
/* dirname.c -- return all but the last element in a path
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef STDC_HEADERS
#include <stdlib.h>
#else
char *malloc ();
#endif
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#else
#include <strings.h>
#ifndef strrchr
#define strrchr rindex
#endif
#endif
/* Return the leading directories part of PATH,
allocated with malloc. If out of memory, return 0.
Assumes that trailing slashes have already been
removed. */
char *
dirname (path)
char *path;
{
char *newpath;
char *slash;
int length; /* Length of result, not including NUL. */
slash = strrchr (path, '/');
if (slash == 0)
{
/* File is in the current directory. */
path = ".";
length = 1;
}
else
{
/* Remove any trailing slashes from the result. */
while (slash > path && *slash == '/')
--slash;
length = slash - path + 1;
}
newpath = (char *) malloc (length + 1);
if (newpath == 0)
return 0;
strncpy (newpath, path, length);
newpath[length] = 0;
return newpath;
}

View File

@ -1,114 +0,0 @@
/* dstring.c - The dynamic string handling routines used by cpio.
Copyright (C) 1990, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
#include <string.h>
#else
#include <strings.h>
#endif
#include "dstring.h"
#if __STDC__
# define P_(s) s
#else
# define P_(s) ()
#endif
char *xmalloc P_((unsigned n));
char *xrealloc P_((char *p, unsigned n));
/* Initialiaze dynamic string STRING with space for SIZE characters. */
void
ds_init (string, size)
dynamic_string *string;
int size;
{
string->ds_length = size;
string->ds_string = (char *) xmalloc (size);
}
/* Expand dynamic string STRING, if necessary, to hold SIZE characters. */
void
ds_resize (string, size)
dynamic_string *string;
int size;
{
if (size > string->ds_length)
{
string->ds_length = size;
string->ds_string = (char *) xrealloc ((char *) string->ds_string, size);
}
}
/* Dynamic string S gets a string terminated by the EOS character
(which is removed) from file F. S will increase
in size during the function if the string from F is longer than
the current size of S.
Return NULL if end of file is detected. Otherwise,
Return a pointer to the null-terminated string in S. */
char *
ds_fgetstr (f, s, eos)
FILE *f;
dynamic_string *s;
char eos;
{
int insize; /* Amount needed for line. */
int strsize; /* Amount allocated for S. */
int next_ch;
/* Initialize. */
insize = 0;
strsize = s->ds_length;
/* Read the input string. */
next_ch = getc (f);
while (next_ch != eos && next_ch != EOF)
{
if (insize >= strsize - 1)
{
ds_resize (s, strsize * 2 + 2);
strsize = s->ds_length;
}
s->ds_string[insize++] = next_ch;
next_ch = getc (f);
}
s->ds_string[insize++] = '\0';
if (insize == 1 && next_ch == EOF)
return NULL;
else
return s->ds_string;
}
char *
ds_fgets (f, s)
FILE *f;
dynamic_string *s;
{
return ds_fgetstr (f, s, '\n');
}
char *
ds_fgetname (f, s)
FILE *f;
dynamic_string *s;
{
return ds_fgetstr (f, s, '\0');
}

View File

@ -1,49 +0,0 @@
/* dstring.h - Dynamic string handling include file. Requires strings.h.
Copyright (C) 1990, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef NULL
#define NULL 0
#endif
/* A dynamic string consists of record that records the size of an
allocated string and the pointer to that string. The actual string
is a normal zero byte terminated string that can be used with the
usual string functions. The major difference is that the
dynamic_string routines know how to get more space if it is needed
by allocating new space and copying the current string. */
typedef struct
{
int ds_length; /* Actual amount of storage allocated. */
char *ds_string; /* String. */
} dynamic_string;
/* Macros that look similar to the original string functions.
WARNING: These macros work only on pointers to dynamic string records.
If used with a real record, an "&" must be used to get the pointer. */
#define ds_strlen(s) strlen ((s)->ds_string)
#define ds_strcmp(s1, s2) strcmp ((s1)->ds_string, (s2)->ds_string)
#define ds_strncmp(s1, s2, n) strncmp ((s1)->ds_string, (s2)->ds_string, n)
#define ds_index(s, c) index ((s)->ds_string, c)
#define ds_rindex(s, c) rindex ((s)->ds_string, c)
void ds_init ();
void ds_resize ();
char *ds_fgetname ();
char *ds_fgets ();
char *ds_fgetstr ();

View File

@ -1,130 +0,0 @@
/* error.c -- error handler for noninteractive utilities
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
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#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
/* This variable is incremented each time `error' is called. */
unsigned int error_message_count;
/* 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 _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;
#if HAVE_STRERROR || _LIBC
# ifndef strerror /* On some systems, strerror is a macro */
char *strerror ();
# endif
#else
static char *
private_strerror (errnum)
int errnum;
{
extern char *sys_errlist[];
extern int sys_nerr;
if (errnum > 0 && errnum <= sys_nerr)
return sys_errlist[errnum];
return "Unknown system error";
}
#define strerror private_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(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
{
#ifdef VA_START
va_list args;
#endif
if (error_print_progname)
(*error_print_progname) ();
else
{
fflush (stdout);
fprintf (stderr, "%s: ", program_name);
}
#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
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
#endif
++error_message_count;
if (errnum)
fprintf (stderr, ": %s", strerror (errnum));
putc ('\n', stderr);
fflush (stderr);
if (status)
exit (status);
}

View File

@ -1,194 +0,0 @@
/* extern.h - External declarations for cpio. Requires system.h.
Copyright (C) 1990, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
enum archive_format
{
arf_unknown, arf_binary, arf_oldascii, arf_newascii, arf_crcascii,
arf_tar, arf_ustar, arf_hpoldascii, arf_hpbinary
};
extern enum archive_format archive_format;
extern int reset_time_flag;
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 dot_flag;
extern int link_flag;
extern int retain_time_flag;
extern int crc_i_flag;
extern int append_flag;
extern int swap_bytes_flag;
extern int swap_halfwords_flag;
extern int swapping_bytes;
extern int swapping_halfwords;
extern int set_owner_flag;
extern uid_t set_owner;
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 *pattern_file_name;
extern char *new_media_message;
extern char *new_media_message_with_number;
extern char *new_media_message_after_number;
extern int archive_des;
extern char *archive_name;
extern unsigned long crc;
#ifdef DEBUG_CPIO
extern int debug_flag;
#endif
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;
extern int num_patterns;
extern char name_end;
extern char input_is_special;
extern char output_is_special;
extern char input_is_seekable;
extern char output_is_seekable;
extern int f_force_local;
extern char *program_name;
extern int (*xstat) ();
extern void (*copy_function) ();
#if __STDC__ || defined(__MSDOS__)
# define P_(s) s
#else
# define P_(s) ()
#endif
/* copyin.c */
void read_in_header P_((struct new_cpio_header *file_hdr, int in_des));
void read_in_old_ascii P_((struct new_cpio_header *file_hdr, int in_des));
void read_in_new_ascii P_((struct new_cpio_header *file_hdr, int in_des));
void read_in_binary P_((struct new_cpio_header *file_hdr, int in_des));
void swab_array P_((char *arg, int count));
void process_copy_in P_((void));
void long_format P_((struct new_cpio_header *file_hdr, char *link_name));
void print_name_with_quoting P_((char *p));
/* copyout.c */
void write_out_header P_((struct new_cpio_header *file_hdr, int out_des));
void process_copy_out P_((void));
/* 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));
/* error.c */
void error P_((int status, int errnum, char *message, ...));
/* filemode.c */
void mode_string P_((unsigned int mode, char *str));
/* idcache.c */
#ifndef __MSDOS__
char *getgroup ();
char *getuser ();
uid_t *getuidbyname ();
gid_t *getgidbyname ();
#endif
/* main.c */
void process_args P_((int argc, char *argv[]));
void initialize_buffers P_((void));
/* makepath.c */
int make_path P_((char *argpath, int mode, int parent_mode,
uid_t owner, gid_t group, char *verbose_fmt_string));
/* stripslash.c */
void strip_trailing_slashes P_((char *path));
/* tar.c */
void write_out_tar_header P_((struct new_cpio_header *file_hdr, int out_des));
int null_block P_((long *block, int size));
void read_in_tar_header P_((struct new_cpio_header *file_hdr, int in_des));
int otoa P_((char *s, unsigned long *n));
int is_tar_header P_((char *buf));
int is_tar_filename_too_long P_((char *name));
/* userspec.c */
#ifndef __MSDOS__
char *parse_user_spec P_((char *name, uid_t *uid, gid_t *gid,
char **username, char **groupname));
#endif
/* util.c */
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 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,
unsigned long major_num, unsigned long minor_num));
void add_inode P_((unsigned long node_num, char *file_name,
unsigned long major_num, unsigned long minor_num));
int open_archive P_((char *file));
void tape_offline P_((int tape_des));
void get_next_reel P_((int tape_des));
void set_new_media_message P_((char *message));
#if defined(__MSDOS__) && !defined(__GNUC__)
int chown P_((char *path, int owner, int group));
#endif
#ifdef __TURBOC__
int utime P_((char *filename, struct utimbuf *utb));
#endif
#ifdef HPUX_CDF
char *add_cdf_double_slashes P_((char *filename));
#endif
/* xmalloc.c */
char *xmalloc P_((unsigned n));
char *xrealloc P_((char *p, unsigned n));
/* xstrdup.c */
char *xstrdup P_((char *string));
#define DISK_IO_BLOCK_SIZE (512)

View File

@ -1,255 +0,0 @@
/* filemode.c -- make a string describing file modes
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
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#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)
#endif
#if !defined(S_ISCHR) && defined(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)
#endif
#if !defined(S_ISREG) && defined(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)
#endif
#if !defined(S_ISLNK) && defined(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)
#endif
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
#endif
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
#endif
void mode_string ();
static char ftypelet ();
static void rwx ();
static void setst ();
/* filemodestring - fill in string STR with an ls-style ASCII
representation of the st_mode field of file stats block STATP.
10 characters are stored in STR; no terminating null is added.
The characters stored in STR are:
0 File type. 'd' for directory, 'c' for character
special, 'b' for block special, 'm' for multiplex,
'l' for symbolic link, 's' for socket, 'p' for fifo,
'-' for regular, '?' for any other file type
1 'r' if the owner may read, '-' otherwise.
2 'w' if the owner may write, '-' otherwise.
3 'x' if the owner may execute, 's' if the file is
set-user-id, '-' otherwise.
'S' if the file is set-user-id, but the execute
bit isn't set.
4 'r' if group members may read, '-' otherwise.
5 'w' if group members may write, '-' otherwise.
6 'x' if group members may execute, 's' if the file is
set-group-id, '-' otherwise.
'S' if it is set-group-id but not executable.
7 'r' if any user may read, '-' otherwise.
8 'w' if any user may write, '-' otherwise.
9 'x' if any user may execute, 't' if the file is "sticky"
(will be retained in swap space after execution), '-'
otherwise.
'T' if the file is sticky but not executable. */
void
filemodestring (statp, str)
struct stat *statp;
char *str;
{
mode_string (statp->st_mode, str);
}
/* Like filemodestring, but only the relevant part of the `struct stat'
is given as an argument. */
void
mode_string (mode, str)
unsigned short mode;
char *str;
{
str[0] = ftypelet ((long) mode);
rwx ((mode & 0700) << 0, &str[1]);
rwx ((mode & 0070) << 3, &str[4]);
rwx ((mode & 0007) << 6, &str[7]);
setst (mode, str);
}
/* Return a character indicating the type of file described by
file mode BITS:
'd' for directories
'b' for block special files
'c' for character special files
'm' for multiplexor files
'l' for symbolic links
's' for sockets
'p' for fifos
'-' for regular files
'?' for any other file type. */
static char
ftypelet (bits)
long bits;
{
#ifdef S_ISBLK
if (S_ISBLK (bits))
return 'b';
#endif
if (S_ISCHR (bits))
return 'c';
if (S_ISDIR (bits))
return 'd';
if (S_ISREG (bits))
return '-';
#ifdef S_ISFIFO
if (S_ISFIFO (bits))
return 'p';
#endif
#ifdef S_ISLNK
if (S_ISLNK (bits))
return 'l';
#endif
#ifdef S_ISSOCK
if (S_ISSOCK (bits))
return 's';
#endif
#ifdef S_ISMPC
if (S_ISMPC (bits))
return 'm';
#endif
#ifdef S_ISNWK
if (S_ISNWK (bits))
return 'n';
#endif
return '?';
}
/* Look at read, write, and execute bits in BITS and set
flags in CHARS accordingly. */
static void
rwx (bits, chars)
unsigned short bits;
char *chars;
{
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,
according to the file mode BITS. */
static void
setst (bits, chars)
unsigned short bits;
char *chars;
{
#ifdef S_ISUID
if (bits & S_ISUID)
{
if (chars[3] != 'x')
/* Set-uid, but not executable by owner. */
chars[3] = 'S';
else
chars[3] = 's';
}
#endif
#ifdef S_ISGID
if (bits & S_ISGID)
{
if (chars[6] != 'x')
/* Set-gid, but not executable by group. */
chars[6] = 'S';
else
chars[6] = 's';
}
#endif
#ifdef S_ISVTX
if (bits & S_ISVTX)
{
if (chars[9] != 'x')
/* Sticky, but not executable by others. */
chars[9] = 'T';
else
chars[9] = 't';
}
#endif
}

View File

@ -1,84 +0,0 @@
/* filetypes.h - deal with POSIX annoyances
Copyright (C) 1991 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Include sys/types.h and sys/stat.h before this file. */
#ifndef S_ISREG /* Doesn't have POSIX.1 stat stuff. */
#define mode_t unsigned short
#endif
/* Define the POSIX macros for systems that lack them. */
#if !defined(S_ISBLK) && defined(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)
#endif
#if !defined(S_ISDIR) && defined(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)
#endif
#if !defined(S_ISFIFO) && defined(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)
#endif
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#endif
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX network special */
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
#endif
/* Define the file type bits used in cpio archives.
They have the same values as the S_IF bits in traditional Unix. */
#define CP_IFMT 0170000 /* Mask for all file type bits. */
#if defined(S_ISBLK)
#define CP_IFBLK 0060000
#endif
#if defined(S_ISCHR)
#define CP_IFCHR 0020000
#endif
#if defined(S_ISDIR)
#define CP_IFDIR 0040000
#endif
#if defined(S_ISREG)
#define CP_IFREG 0100000
#endif
#if defined(S_ISFIFO)
#define CP_IFIFO 0010000
#endif
#if defined(S_ISLNK)
#define CP_IFLNK 0120000
#endif
#if defined(S_ISSOCK)
#define CP_IFSOCK 0140000
#endif
#if defined(S_ISNWK)
#define CP_IFNWK 0110000
#endif
#ifndef S_ISLNK
#define lstat stat
#endif
int lstat ();
int stat ();

View File

@ -1,765 +0,0 @@
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"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, 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 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* 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>
#endif
#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>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
#endif /* GNU C library. */
#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
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "getopt.h"
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = NULL;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* XXX 1003.2 says this must be 1 before any call. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Set to an option character which was unrecognized.
This must be initialized on some systems to avoid linking in the
system's own getopt implementation. */
int optopt = '?';
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
/* Value of POSIXLY_CORRECT environment variable. */
static char *posixly_correct;
#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
#define my_index strchr
#else
/* Avoid depending on library functions or files
whose names are inconsistent. */
char *getenv ();
static char *
my_index (str, chr)
const char *str;
int chr;
{
while (*str)
{
if (*str == chr)
return (char *) str;
str++;
}
return 0;
}
/* If using GCC, we can safely declare strlen this way.
If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
/* 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__ */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (argv)
char **argv;
{
int bottom = first_nonopt;
int middle = last_nonopt;
int top = optind;
char *tem;
/* Exchange the shorter segment with the far end of the longer segment.
That puts the shorter segment into the right place.
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
/* Bottom segment is the short one. */
int len = middle - bottom;
register int i;
/* Swap it with the top part of the top segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
/* Exclude the moved bottom segment from further swapping. */
top -= len;
}
else
{
/* Top segment is the short one. */
int len = top - middle;
register int i;
/* Swap it with the bottom part of the bottom segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
/* Exclude the moved top segment from further swapping. */
bottom += len;
}
}
/* Update records for the slots the non-options now occupy. */
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;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc;
char *const *argv;
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{
optarg = NULL;
if (optind == 0)
{
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,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0'))
optind++;
last_nonopt = optind;
}
/* 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 (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* 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'))
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
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][1] == '-'
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
{
char *nameend;
const struct option *p;
const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound;
int option_index;
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
/* Do nothing. */ ;
/* 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 (nameend - nextchar == strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second or later nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
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 = 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);
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
if (opterr)
fprintf (stderr,
_("%s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
nextchar += strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 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] == '-'
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
argv[0], nextchar);
else
/* +option or -option */
fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++;
return '?';
}
}
/* Look at and handle the next short option-character. */
{
char c = *nextchar++;
char *temp = my_index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
++optind;
if (temp == NULL || c == ':')
{
if (opterr)
{
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: invalid option -- %c\n"),
argv[0], c);
}
optopt = c;
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
{
optarg = nextchar;
optind++;
}
else
optarg = NULL;
nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != '\0')
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr)
{
/* 1003.2 specifies the format of this message. */
fprintf (stderr,
_("%s: option requires an argument -- %c\n"),
argv[0], c);
}
optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
}
}
return c;
}
}
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

View File

@ -1,129 +0,0 @@
/* Declarations for getopt.
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
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#if defined (__STDC__) && __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#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 /* __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,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

View File

@ -1,180 +0,0 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
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
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "getopt.h"
#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>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#else
char *getenv ();
#endif
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == EOF)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

View File

@ -1,197 +0,0 @@
/* global.c - global variables and initial values for cpio.
Copyright (C) 1990, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/types.h>
#include "cpiohdr.h"
#include "dstring.h"
#include "system.h"
#include "extern.h"
/* If TRUE, reset access times after reading files (-a). */
int reset_time_flag = FALSE;
/* Block size value, initially 512. -B sets to 5120. */
int io_block_size = 512;
/* The header format to recognize and produce. */
enum archive_format archive_format = arf_unknown;
/* If TRUE, create directories as needed. (-d with -i or -p) */
int create_dir_flag = FALSE;
/* 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, copy unconditionally (older replaces newer). (-u) */
int unconditional_flag = FALSE;
/* If TRUE, list the files processed, or ls -l style output with -t. (-v) */
int verbose_flag = FALSE;
/* If TRUE, print a . for each file processed. (-V) */
int dot_flag = FALSE;
/* If TRUE, link files whenever possible. Used with -p option. (-l) */
int link_flag = FALSE;
/* If TRUE, retain previous file modification time. (-m) */
int retain_time_flag = FALSE;
/* Set TRUE if crc_flag is TRUE and we are doing a cpio -i. Used
by copy_files so it knows whether to compute the crc. */
int crc_i_flag = FALSE;
/* If TRUE, append to end of archive. (-A) */
int append_flag = FALSE;
/* If TRUE, swap bytes of each file during cpio -i. */
int swap_bytes_flag = FALSE;
/* If TRUE, swap halfwords of each file during cpio -i. */
int swap_halfwords_flag = FALSE;
/* If TRUE, we are swapping halfwords on the current file. */
int swapping_halfwords = FALSE;
/* If TRUE, we are swapping bytes on the current file. */
int swapping_bytes = FALSE;
/* If TRUE, set ownership of all files to UID `set_owner'. */
int set_owner_flag = FALSE;
uid_t set_owner;
/* If TRUE, set group ownership of all files to GID `set_group'. */
int set_group_flag = FALSE;
gid_t set_group;
/* 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;
#endif
/* File position of last header read. Only used during -A to determine
where the old TRAILER!!! record started. */
int last_header_start = 0;
/* With -i; if TRUE, copy only files that match any of the given patterns;
if FALSE, copy only files that do not match any of the patterns. (-f) */
int copy_matching_files = TRUE;
/* With -itv; if TRUE, list numeric uid and gid instead of translating them
into names. */
int numeric_uid = FALSE;
/* Name of file containing additional patterns (-E). */
char *pattern_file_name = NULL;
/* Message to print when end of medium is reached (-M). */
char *new_media_message = NULL;
/* With -M with %d, message to print when end of medium is reached. */
char *new_media_message_with_number = NULL;
char *new_media_message_after_number = NULL;
/* File descriptor containing the archive. */
int archive_des;
/* Name of file containing the archive, if known; NULL if stdin/out. */
char *archive_name = NULL;
/* CRC checksum. */
unsigned long crc;
/* 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.
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];
/* Saving of argument values for later reference. */
char *directory_name = NULL;
char **save_patterns;
int num_patterns;
/* Character that terminates file names read from stdin. */
char name_end = '\n';
/* TRUE if input (cpio -i) or output (cpio -o) is a device node. */
char input_is_special = FALSE;
char output_is_special = FALSE;
/* TRUE if lseek works on the input. */
char input_is_seekable = FALSE;
/* TRUE if lseek works on the output. */
char output_is_seekable = FALSE;
/* If nonzero, don't consider file names that contain a `:' to be
on remote hosts; all files are local. */
int f_force_local = 0;
/* The name this program was run with. */
char *program_name;
/* A pointer to either lstat or stat, depending on whether
dereferencing of symlinks is done for input files. */
int (*xstat) ();
/* Which copy operation to perform. (-i, -o, -p) */
void (*copy_function) () = 0;

View File

@ -1,210 +0,0 @@
/* idcache.c -- map user and group IDs, cached for speed
Copyright (C) 1985, 1988, 1989, 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., 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>
#include <grp.h>
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#else
#include <strings.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef _POSIX_VERSION
struct passwd *getpwuid ();
struct passwd *getpwnam ();
struct group *getgrgid ();
struct group *getgrnam ();
#endif
char *xmalloc ();
char *xstrdup ();
struct userid
{
union
{
uid_t u;
gid_t g;
} id;
char *name;
struct userid *next;
};
static struct userid *user_alist;
/* The members of this list have names not in the local passwd file. */
static struct userid *nouser_alist;
/* Translate UID to a login name or a stringified number,
with cache. */
char *
getuser (uid)
uid_t uid;
{
register struct userid *tail;
struct passwd *pwent;
char usernum_string[20];
for (tail = user_alist; tail; tail = tail->next)
if (tail->id.u == uid)
return tail->name;
pwent = getpwuid (uid);
tail = (struct userid *) xmalloc (sizeof (struct userid));
tail->id.u = uid;
if (pwent == 0)
{
sprintf (usernum_string, "%u", (unsigned) uid);
tail->name = xstrdup (usernum_string);
}
else
tail->name = xstrdup (pwent->pw_name);
/* Add to the head of the list, so most recently used is first. */
tail->next = user_alist;
user_alist = tail;
return tail->name;
}
/* Translate USER to a UID, with cache.
Return NULL if there is no such user.
(We also cache which user names have no passwd entry,
so we don't keep looking them up.) */
uid_t *
getuidbyname (user)
char *user;
{
register struct userid *tail;
struct passwd *pwent;
for (tail = user_alist; tail; tail = tail->next)
/* Avoid a function call for the most common case. */
if (*tail->name == *user && !strcmp (tail->name, user))
return &tail->id.u;
for (tail = nouser_alist; tail; tail = tail->next)
/* Avoid a function call for the most common case. */
if (*tail->name == *user && !strcmp (tail->name, user))
return 0;
pwent = getpwnam (user);
tail = (struct userid *) xmalloc (sizeof (struct userid));
tail->name = xstrdup (user);
/* Add to the head of the list, so most recently used is first. */
if (pwent)
{
tail->id.u = pwent->pw_uid;
tail->next = user_alist;
user_alist = tail;
return &tail->id.u;
}
tail->next = nouser_alist;
nouser_alist = tail;
return 0;
}
/* Use the same struct as for userids. */
static struct userid *group_alist;
static struct userid *nogroup_alist;
/* Translate GID to a group name or a stringified number,
with cache. */
char *
getgroup (gid)
gid_t gid;
{
register struct userid *tail;
struct group *grent;
char groupnum_string[20];
for (tail = group_alist; tail; tail = tail->next)
if (tail->id.g == gid)
return tail->name;
grent = getgrgid (gid);
tail = (struct userid *) xmalloc (sizeof (struct userid));
tail->id.g = gid;
if (grent == 0)
{
sprintf (groupnum_string, "%u", (unsigned int) gid);
tail->name = xstrdup (groupnum_string);
}
else
tail->name = xstrdup (grent->gr_name);
/* Add to the head of the list, so most recently used is first. */
tail->next = group_alist;
group_alist = tail;
return tail->name;
}
/* Translate GROUP to a UID, with cache.
Return NULL if there is no such group.
(We also cache which group names have no group entry,
so we don't keep looking them up.) */
gid_t *
getgidbyname (group)
char *group;
{
register struct userid *tail;
struct group *grent;
for (tail = group_alist; tail; tail = tail->next)
/* Avoid a function call for the most common case. */
if (*tail->name == *group && !strcmp (tail->name, group))
return &tail->id.g;
for (tail = nogroup_alist; tail; tail = tail->next)
/* Avoid a function call for the most common case. */
if (*tail->name == *group && !strcmp (tail->name, group))
return 0;
grent = getgrnam (group);
tail = (struct userid *) xmalloc (sizeof (struct userid));
tail->name = xstrdup (group);
/* Add to the head of the list, so most recently used is first. */
if (grent)
{
tail->id.g = grent->gr_gid;
tail->next = group_alist;
group_alist = tail;
return &tail->id.g;
}
tail->next = nogroup_alist;
nogroup_alist = tail;
return 0;
}

View File

@ -1,521 +0,0 @@
/* main.c - main program and argument processing for cpio.
Copyright (C) 1990, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by Phil Nelson <phil@cs.wwu.edu>,
David MacKenzie <djm@gnu.ai.mit.edu>,
and John Oleynick <juo@klinzhai.rutgers.edu>. */
#include <stdio.h>
#include <getopt.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 "rmt.h"
struct option long_opts[] =
{
{"null", 0, 0, '0'},
{"append", 0, 0, 'A'},
{"block-size", 1, 0, 130},
{"create", 0, 0, 'o'},
{"dereference", 0, 0, 'L'},
{"dot", 0, 0, 'V'},
{"extract", 0, 0, 'i'},
{"file", 1, 0, 'F'},
{"force-local", 0, &f_force_local, 1},
{"format", 1, 0, 'H'},
{"help", 0, 0, 132},
{"io-size", 1, 0, 'C'},
{"link", 0, &link_flag, TRUE},
{"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, &copy_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'},
{"reset-access-time", 0, &reset_time_flag, TRUE},
{"unconditional", 0, &unconditional_flag, TRUE},
{"verbose", 0, &verbose_flag, TRUE},
{"version", 0, 0, 131},
#ifdef DEBUG_CPIO
{"debug", 0, &debug_flag, TRUE},
#endif
{0, 0, 0, 0}
};
/* Print usage message and exit with error. */
void
usage (fp, status)
FILE *fp;
int status;
{
fprintf (fp, "\
Usage: %s {-o|--create} [-0acvABLV] [-C bytes] [-H format] [-M message]\n\
[-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] [--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\
[-M message] [-R [user][:.][group]] [-I [[user@]host:]archive]\n\
[-F [[user@]host:]archive] [--file=[[user@]host:]archive]\n\
[--make-directories] [--nonmatching] [--preserve-modification-time]\n\
[--numeric-uid-gid] [--rename] [--list] [--swap-bytes] [--swap] [--dot]\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] [--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] [--quiet]\n\
[--preserve-modification-time] [--unconditional] [--verbose] [--dot]\n\
[--dereference] [--owner=[user][:.][group]] [--no-preserve-owner]\n\
[--sparse] [--help] [--version] destination-directory < name-list\n", program_name);
exit (status);
}
/* Process the arguments. Set all options and set up the copy pass
directory or the copy in patterns. */
void
process_args (argc, argv)
int argc;
char *argv[];
{
extern char *version_string;
void (*copy_in) (); /* Work around for pcc bug. */
void (*copy_out) ();
int c;
char *input_archive_name = 0;
char *output_archive_name = 0;
if (argc < 2)
usage (stderr, 2);
xstat = lstat;
while ((c = getopt_long (argc, argv,
"0aAbBcC:dfE:F:H:iI:lLmM:noO:prR:sStuvVz",
long_opts, (int *) 0)) != -1)
{
switch (c)
{
case 0: /* A long option that just sets a flag. */
break;
case '0': /* Read null-terminated filenames. */
name_end = '\0';
break;
case 'a': /* Reset access times. */
reset_time_flag = TRUE;
break;
case 'A': /* Append to the archive. */
append_flag = TRUE;
break;
case 'b': /* Swap bytes and halfwords. */
swap_bytes_flag = TRUE;
swap_halfwords_flag = TRUE;
break;
case 'B': /* Set block size to 5120. */
io_block_size = 5120;
break;
case 130: /* --block-size */
io_block_size = atoi (optarg);
if (io_block_size < 1)
error (2, 0, "invalid block size");
io_block_size *= 512;
break;
case 'c': /* Use the old portable ASCII format. */
if (archive_format != arf_unknown)
usage (stderr, 2);
#ifdef SVR4_COMPAT
archive_format = arf_newascii; /* -H newc. */
#else
archive_format = arf_oldascii; /* -H odc. */
#endif
break;
case 'C': /* Block size. */
io_block_size = atoi (optarg);
if (io_block_size < 1)
error (2, 0, "invalid block size");
break;
case 'd': /* Create directories where needed. */
create_dir_flag = TRUE;
break;
case 'f': /* Only copy files not matching patterns. */
copy_matching_files = FALSE;
break;
case 'E': /* Pattern file name. */
pattern_file_name = optarg;
break;
case 'F': /* Archive file name. */
archive_name = optarg;
break;
case 'H': /* Header format name. */
if (archive_format != arf_unknown)
usage (stderr, 2);
if (!strcmp (optarg, "crc") || !strcmp (optarg, "CRC"))
archive_format = arf_crcascii;
else if (!strcmp (optarg, "newc") || !strcmp (optarg, "NEWC"))
archive_format = arf_newascii;
else if (!strcmp (optarg, "odc") || !strcmp (optarg, "ODC"))
archive_format = arf_oldascii;
else if (!strcmp (optarg, "bin") || !strcmp (optarg, "BIN"))
archive_format = arf_binary;
else if (!strcmp (optarg, "ustar") || !strcmp (optarg, "USTAR"))
archive_format = arf_ustar;
else if (!strcmp (optarg, "tar") || !strcmp (optarg, "TAR"))
archive_format = arf_tar;
else if (!strcmp (optarg, "hpodc") || !strcmp (optarg, "HPODC"))
archive_format = arf_hpoldascii;
else if (!strcmp (optarg, "hpbin") || !strcmp (optarg, "HPBIN"))
archive_format = arf_hpbinary;
else
error (2, 0, "\
invalid archive format `%s'; valid formats are:\n\
crc newc odc bin ustar tar (all-caps also recognized)", optarg);
break;
case 'i': /* Copy-in mode. */
if (copy_function != 0)
usage (stderr, 2);
copy_function = process_copy_in;
break;
case 'I': /* Input archive file name. */
input_archive_name = optarg;
break;
case 'k': /* Handle corrupted archives. We always handle
corrupted archives, but recognize this
option for compatability. */
break;
case 'l': /* Link files when possible. */
link_flag = TRUE;
break;
case 'L': /* Dereference symbolic links. */
xstat = stat;
break;
case 'm': /* Retain previous file modify times. */
retain_time_flag = TRUE;
break;
case 'M': /* New media message. */
set_new_media_message (optarg);
break;
case 'n': /* Long list owner and group as numbers. */
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);
no_chown_flag = TRUE;
break;
case 'o': /* Copy-out mode. */
if (copy_function != 0)
usage (stderr, 2);
copy_function = process_copy_out;
break;
case 'O': /* Output archive file name. */
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);
copy_function = process_copy_pass;
break;
case 'r': /* Interactively rename. */
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);
#ifndef __MSDOS__
{
char *e, *u, *g;
e = parse_user_spec (optarg, &set_owner, &set_group, &u, &g);
if (e)
error (2, 0, "%s: %s", optarg, e);
if (u)
{
free (u);
set_owner_flag = TRUE;
}
if (g)
{
free (g);
set_group_flag = TRUE;
}
}
#endif
break;
case 's': /* Swap bytes. */
swap_bytes_flag = TRUE;
break;
case 'S': /* Swap halfwords. */
swap_halfwords_flag = TRUE;
break;
case 't': /* Only print a list. */
table_flag = TRUE;
break;
case 'u': /* Replace all! Unconditionally! */
unconditional_flag = TRUE;
break;
case 'v': /* Verbose! */
verbose_flag = TRUE;
break;
case 'V': /* Print `.' for each file. */
dot_flag = TRUE;
break;
case 131:
printf ("GNU cpio %s", version_string);
exit (0);
break;
case 135:
sparse_flag = TRUE;
break;
case 132: /* --help */
usage (stdout, 0);
break;
default:
usage (stderr, 2);
}
}
/* Do error checking and look at other args. */
if (copy_function == 0)
{
if (table_flag)
copy_function = process_copy_in;
else
usage (stderr, 2);
}
if ((!table_flag || !verbose_flag) && numeric_uid)
usage (stderr, 2);
/* Work around for pcc bug. */
copy_in = process_copy_in;
copy_out = process_copy_out;
if (copy_function == copy_in)
{
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);
if (archive_format == arf_crcascii)
crc_i_flag = TRUE;
num_patterns = argc - optind;
save_patterns = &argv[optind];
if (input_archive_name)
archive_name = input_archive_name;
}
else if (copy_function == copy_out)
{
archive_des = 1;
if (argc != optind || create_dir_flag || rename_flag
|| table_flag || unconditional_flag || link_flag
|| 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_format = arf_binary;
if (output_archive_name)
archive_name = output_archive_name;
}
else
{
/* Copy pass. */
archive_des = -1;
if (argc - 1 != optind || archive_format != arf_unknown
|| swap_bytes_flag || swap_halfwords_flag
|| table_flag || rename_flag || append_flag
|| rename_batch_file || no_abs_paths_flag)
usage (stderr, 2);
directory_name = argv[optind];
}
if (archive_name)
{
if (copy_function != copy_in && copy_function != copy_out)
usage (stderr, 2);
archive_des = open_archive (archive_name);
if (archive_des < 0)
error (1, errno, "%s", archive_name);
}
#ifndef __MSDOS__
/* Prevent SysV non-root users from giving away files inadvertantly.
This happens automatically on BSD, where only root can give
away files. */
if (set_owner_flag == FALSE && set_group_flag == FALSE && geteuid ())
no_chown_flag = TRUE;
#endif
}
/* Initialize the input and output buffers to their proper size and
initialize all variables associated with the input and output
buffers. */
void
initialize_buffers ()
{
int in_buf_size, out_buf_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
{
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;
output_buffer = (char *) xmalloc (out_buf_size);
out_buff = output_buffer;
output_size = 0;
output_bytes = 0;
/* Clear the block of zeros. */
bzero (zeros_512, 512);
}
void
main (argc, argv)
int argc;
char *argv[];
{
program_name = argv[0];
umask (0);
#ifdef __TURBOC__
_fmode = O_BINARY; /* Put stdin and stdout in binary mode. */
#endif
#ifdef __EMX__ /* gcc on OS/2. */
_response (&argc, &argv);
_wildcard (&argc, &argv);
#endif
process_args (argc, argv);
initialize_buffers ();
(*copy_function) ();
if (archive_des >= 0 && rmtclose (archive_des) == -1)
error (1, errno, "error closing archive");
exit (0);
}

View File

@ -1,307 +0,0 @@
/* makepath.c -- Ensure that a directory path exists.
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu> and
Jim Meyering <meyering@cs.utexas.edu>. */
/* This copy of makepath is almost like the fileutils one, but has
changes for HPUX CDF's. Maybe the 2 versions of makepath can
come together again in the future. */
#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 <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if !defined(S_ISDIR) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#include <errno.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#else
extern int errno;
#endif
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#ifndef index
#define index strchr
#endif
#else
#include <strings.h>
#endif
#if defined(__MSDOS__) && !defined(__GNUC__)
typedef int uid_t;
typedef int gid_t;
#endif
void error ();
/* Ensure that the directory ARGPATH exists.
Remove any trailing slashes from ARGPATH before calling this function.
Make any leading directories that don't already exist, with
permissions PARENT_MODE.
If the last element of ARGPATH does not exist, create it as
a new directory with permissions MODE.
If OWNER and GROUP are non-negative, make them the UID and GID of
created directories.
If VERBOSE_FMT_STRING is nonzero, use it as a printf format
string for printing a message after successfully making a directory,
with the name of the directory that was just made as an argument.
Return 0 if ARGPATH exists as a directory with the proper
ownership and permissions when done, otherwise 1. */
int
make_path (argpath, mode, parent_mode, owner, group, verbose_fmt_string)
char *argpath;
int mode;
int parent_mode;
uid_t owner;
gid_t group;
char *verbose_fmt_string;
{
char *dirpath; /* A copy we can scribble NULs on. */
struct stat stats;
int retval = 0;
int oldmask = umask (0);
dirpath = alloca (strlen (argpath) + 1);
strcpy (dirpath, argpath);
if (stat (dirpath, &stats))
{
char *slash;
int tmp_mode; /* Initial perms for leading dirs. */
int re_protect; /* Should leading dirs be unwritable? */
struct ptr_list
{
char *dirname_end;
struct ptr_list *next;
};
struct ptr_list *p, *leading_dirs = NULL;
/* If leading directories shouldn't be writable or executable,
or should have set[ug]id or sticky bits set and we are setting
their owners, we need to fix their permissions after making them. */
if (((parent_mode & 0300) != 0300)
|| (owner != (uid_t) -1 && group != (gid_t) -1
&& (parent_mode & 07000) != 0))
{
tmp_mode = 0700;
re_protect = 1;
}
else
{
tmp_mode = parent_mode;
re_protect = 0;
}
slash = dirpath;
while (*slash == '/')
slash++;
while ((slash = index (slash, '/')))
{
#ifdef HPUX_CDF
int iscdf;
iscdf = 0;
#endif
*slash = '\0';
if (stat (dirpath, &stats))
{
#ifdef HPUX_CDF
/* If this component of the pathname ends in `+' and is
followed by 2 `/'s, then this is a CDF. We remove the
`+' from the name and create the directory. Later
we will "hide" the directory. */
if ( (*(slash +1) == '/') && (*(slash -1) == '+') )
{
iscdf = 1;
*(slash -1) = '\0';
}
#endif
if (mkdir (dirpath, tmp_mode))
{
error (0, errno, "cannot make directory `%s'", dirpath);
umask (oldmask);
return 1;
}
else
{
if (verbose_fmt_string != NULL)
error (0, 0, verbose_fmt_string, dirpath);
if (owner != (uid_t) -1 && group != (gid_t) -1
&& chown (dirpath, owner, group)
#ifdef AFS
&& errno != EPERM
#endif
)
{
error (0, errno, "%s", dirpath);
retval = 1;
}
if (re_protect)
{
struct ptr_list *new = (struct ptr_list *)
alloca (sizeof (struct ptr_list));
new->dirname_end = slash;
new->next = leading_dirs;
leading_dirs = new;
}
#ifdef HPUX_CDF
if (iscdf)
{
/* If this is a CDF, "hide" the directory by setting
its hidden/setuid bit. Also add the `+' back to
its name (since once it's "hidden" we must refer
to as `name+' instead of `name'). */
chmod (dirpath, 04700);
*(slash - 1) = '+';
}
#endif
}
}
else if (!S_ISDIR (stats.st_mode))
{
error (0, 0, "`%s' exists but is not a directory", dirpath);
umask (oldmask);
return 1;
}
*slash++ = '/';
/* Avoid unnecessary calls to `stat' when given
pathnames containing multiple adjacent slashes. */
while (*slash == '/')
slash++;
}
/* We're done making leading directories.
Make the final component of the path. */
if (mkdir (dirpath, mode))
{
/* 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);
if (owner != (uid_t) -1 && group != (gid_t) -1)
{
if (chown (dirpath, owner, group)
#ifdef AFS
&& errno != EPERM
#endif
)
{
error (0, errno, "%s", dirpath);
retval = 1;
}
}
/* chown may have turned off some permission bits we wanted. */
if ((mode & 07000) != 0 && chmod (dirpath, mode))
{
error (0, errno, "%s", dirpath);
retval = 1;
}
/* If the mode for leading directories didn't include owner "wx"
privileges, we have to reset their protections to the correct
value. */
for (p = leading_dirs; p != NULL; p = p->next)
{
*(p->dirname_end) = '\0';
#if 0
/* cpio always calls make_path with parent mode 0700, so
we don't have to do this. If we ever do have to do this,
we have to stat the directory first to get the setuid
bit so we don't break HP CDF's. */
if (chmod (dirpath, parent_mode))
{
error (0, errno, "%s", dirpath);
retval = 1;
}
#endif
}
}
else
{
/* We get here if the entire path already exists. */
if (!S_ISDIR (stats.st_mode))
{
error (0, 0, "`%s' exists but is not a directory", dirpath);
umask (oldmask);
return 1;
}
/* chown must precede chmod because on some systems,
chown clears the set[ug]id bits for non-superusers,
resulting in incorrect permissions.
On System V, users can give away files with chown and then not
be able to chmod them. So don't give files away. */
if (owner != (uid_t) -1 && group != (gid_t) -1
&& chown (dirpath, owner, group)
#ifdef AFS
&& errno != EPERM
#endif
)
{
error (0, errno, "%s", dirpath);
retval = 1;
}
if (chmod (dirpath, mode))
{
error (0, errno, "%s", dirpath);
retval = 1;
}
}
umask (oldmask);
return retval;
}

View File

@ -1,98 +0,0 @@
/* Definitions for communicating with a remote tape drive.
Copyright (C) 1988, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if !defined(_POSIX_VERSION)
#ifdef __MSDOS__
#include <io.h>
#else /* !__MSDOS__ */
extern off_t lseek ();
#endif /* __MSDOS__ */
#endif /* _POSIX_VERSION */
#ifdef NO_REMOTE
#define _isrmt(f) 0
#define rmtopen open
#define rmtaccess access
#define rmtstat stat
#define rmtcreat creat
#define rmtlstat lstat
#define rmtread read
#define rmtwrite write
#define rmtlseek lseek
#define rmtclose close
#define rmtioctl ioctl
#define rmtdup dup
#define rmtfstat fstat
#define rmtfcntl fcntl
#define rmtisatty isatty
#else /* !NO_REMOTE */
#define __REM_BIAS 128
#define RMTIOCTL
#ifndef O_CREAT
#define O_CREAT 01000
#endif
extern char *__rmt_path;
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#ifndef index
#define index strchr
#endif
#else
extern char *index ();
#endif
#define _remdev(path) (!f_force_local && (__rmt_path=index(path, ':')))
#define _isrmt(fd) ((fd) >= __REM_BIAS)
#define rmtopen(path,oflag,mode) (_remdev(path) ? __rmt_open(path, oflag, mode, __REM_BIAS) : open(path, oflag, mode))
#define rmtaccess(path, amode) (_remdev(path) ? 0 : access(path, amode))
#define rmtstat(path, buf) (_remdev(path) ? (errno = EOPNOTSUPP), -1 : stat(path, buf))
#define rmtcreat(path, mode) (_remdev(path) ? __rmt_open (path, 1 | O_CREAT, mode, __REM_BIAS) : creat(path, mode))
#define rmtlstat(path,buf) (_remdev(path) ? (errno = EOPNOTSUPP), -1 : lstat(path,buf))
#define rmtread(fd, buf, n) (_isrmt(fd) ? __rmt_read(fd - __REM_BIAS, buf, n) : read(fd, buf, n))
#define rmtwrite(fd, buf, n) (_isrmt(fd) ? __rmt_write(fd - __REM_BIAS, buf, n) : write(fd, buf, n))
#define rmtlseek(fd, off, wh) (_isrmt(fd) ? __rmt_lseek(fd - __REM_BIAS, off, wh) : lseek(fd, off, wh))
#define rmtclose(fd) (_isrmt(fd) ? __rmt_close(fd - __REM_BIAS) : close(fd))
#ifdef RMTIOCTL
#define rmtioctl(fd,req,arg) (_isrmt(fd) ? __rmt_ioctl(fd - __REM_BIAS, req, arg) : ioctl(fd, req, arg))
#else
#define rmtioctl(fd,req,arg) (_isrmt(fd) ? (errno = EOPNOTSUPP), -1 : ioctl(fd, req, arg))
#endif
#define rmtdup(fd) (_isrmt(fd) ? (errno = EOPNOTSUPP), -1 : dup(fd))
#define rmtfstat(fd, buf) (_isrmt(fd) ? (errno = EOPNOTSUPP), -1 : fstat(fd, buf))
#define rmtfcntl(fd,cmd,arg) (_isrmt(fd) ? (errno = EOPNOTSUPP), -1 : fcntl (fd, cmd, arg))
#define rmtisatty(fd) (_isrmt(fd) ? 0 : isatty(fd))
#undef RMTIOCTL
int __rmt_open ();
int __rmt_close ();
int __rmt_read ();
int __rmt_write ();
long __rmt_lseek ();
int __rmt_ioctl ();
#endif /* !NO_REMOTE */

View File

@ -1,582 +0,0 @@
/* Functions for communicating with a remote tape drive.
Copyright (C) 1988, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* The man page rmt(8) for /etc/rmt documents the remote mag tape
protocol which rdump and rrestore use. Unfortunately, the man
page is *WRONG*. The author of the routines I'm including originally
wrote his code just based on the man page, and it didn't work, so he
went to the rdump source to figure out why. The only thing he had to
change was to check for the 'F' return code in addition to the 'E',
and to separate the various arguments with \n instead of a space. I
personally don't think that this is much of a problem, but I wanted to
point it out. -- Arnold Robbins
Originally written by Jeff Lee, modified some by Arnold Robbins.
Redone as a library that can replace open, read, write, etc., by
Fred Fish, with some additional work by Arnold Robbins.
Modified to make all rmtXXX calls into macros for speed by Jay Fenlason.
Use -DHAVE_NETDB_H for rexec code, courtesy of Dan Kegel, srs!dan. */
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#ifdef HAVE_SYS_MTIO_H
#include <sys/ioctl.h>
#include <sys/mtio.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include <errno.h>
#include <setjmp.h>
#include <sys/stat.h>
#ifndef errno
extern int errno;
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef STDC_HEADERS
#include <string.h>
#include <stdlib.h>
#endif
/* Maximum size of a fully qualified host name. */
#define MAXHOSTLEN 257
/* Size of buffers for reading and writing commands to rmt.
(An arbitrary limit.) */
#define CMDBUFSIZE 64
#ifndef RETSIGTYPE
#define RETSIGTYPE void
#endif
/* Maximum number of simultaneous remote tape connections.
(Another arbitrary limit.) */
#define MAXUNIT 4
/* Return the parent's read side of remote tape connection FILDES. */
#define READ(fildes) (from_rmt[fildes][0])
/* Return the parent's write side of remote tape connection FILDES. */
#define WRITE(fildes) (to_rmt[fildes][1])
/* The pipes for receiving data from remote tape drives. */
static int from_rmt[MAXUNIT][2] =
{-1, -1, -1, -1, -1, -1, -1, -1};
/* The pipes for sending data to remote tape drives. */
static int to_rmt[MAXUNIT][2] =
{-1, -1, -1, -1, -1, -1, -1, -1};
/* Temporary variable used by macros in rmt.h. */
char *__rmt_path;
/* Close remote tape connection FILDES. */
static void
_rmt_shutdown (fildes)
int fildes;
{
close (READ (fildes));
close (WRITE (fildes));
READ (fildes) = -1;
WRITE (fildes) = -1;
}
/* Attempt to perform the remote tape command specified in BUF
on remote tape connection FILDES.
Return 0 if successful, -1 on error. */
static int
command (fildes, buf)
int fildes;
char *buf;
{
register int buflen;
RETSIGTYPE (*pipe_handler) ();
/* Save the current pipe handler and try to make the request. */
pipe_handler = signal (SIGPIPE, SIG_IGN);
buflen = strlen (buf);
if (write (WRITE (fildes), buf, buflen) == buflen)
{
signal (SIGPIPE, pipe_handler);
return 0;
}
/* Something went wrong. Close down and go home. */
signal (SIGPIPE, pipe_handler);
_rmt_shutdown (fildes);
errno = EIO;
return -1;
}
/* Read and return the status from remote tape connection FILDES.
If an error occurred, return -1 and set errno. */
static int
status (fildes)
int fildes;
{
int i;
char c, *cp;
char buffer[CMDBUFSIZE];
/* Read the reply command line. */
for (i = 0, cp = buffer; i < CMDBUFSIZE; i++, cp++)
{
if (read (READ (fildes), cp, 1) != 1)
{
_rmt_shutdown (fildes);
errno = EIO;
return -1;
}
if (*cp == '\n')
{
*cp = '\0';
break;
}
}
if (i == CMDBUFSIZE)
{
_rmt_shutdown (fildes);
errno = EIO;
return -1;
}
/* Check the return status. */
for (cp = buffer; *cp; cp++)
if (*cp != ' ')
break;
if (*cp == 'E' || *cp == 'F')
{
errno = atoi (cp + 1);
/* Skip the error message line. */
while (read (READ (fildes), &c, 1) == 1)
if (c == '\n')
break;
if (*cp == 'F')
_rmt_shutdown (fildes);
return -1;
}
/* Check for mis-synced pipes. */
if (*cp != 'A')
{
_rmt_shutdown (fildes);
errno = EIO;
return -1;
}
/* Got an `A' (success) response. */
return atoi (cp + 1);
}
#ifdef HAVE_NETDB_H
/* Execute /etc/rmt as user USER on remote system HOST using rexec.
Return a file descriptor of a bidirectional socket for stdin and stdout.
If USER is NULL, or an empty string, use the current username.
By default, this code is not used, since it requires that
the user have a .netrc file in his/her home directory, or that the
application designer be willing to have rexec prompt for login and
password info. This may be unacceptable, and .rhosts files for use
with rsh are much more common on BSD systems. */
static int
_rmt_rexec (host, user)
char *host;
char *user;
{
struct servent *rexecserv;
int save_stdin = dup (fileno (stdin));
int save_stdout = dup (fileno (stdout));
int tape_fd; /* Return value. */
/* When using cpio -o < filename, stdin is no longer the tty.
But the rexec subroutine reads the login and the passwd on stdin,
to allow remote execution of the command.
So, reopen stdin and stdout on /dev/tty before the rexec and
give them back their original value after. */
if (freopen ("/dev/tty", "r", stdin) == NULL)
freopen ("/dev/null", "r", stdin);
if (freopen ("/dev/tty", "w", stdout) == NULL)
freopen ("/dev/null", "w", stdout);
rexecserv = getservbyname ("exec", "tcp");
if (NULL == rexecserv)
{
fprintf (stderr, "exec/tcp: service not available");
exit (1);
}
if (user != NULL && *user == '\0')
user = NULL;
tape_fd = rexec (&host, rexecserv->s_port, user, NULL,
"/etc/rmt", (int *) NULL);
fclose (stdin);
fdopen (save_stdin, "r");
fclose (stdout);
fdopen (save_stdout, "w");
return tape_fd;
}
#endif /* HAVE_NETDB_H */
/* Open a magtape device on the system specified in PATH, as the given user.
PATH has the form `[user@]system:/dev/????'.
If COMPAT is defined, it can also have the form `system[.user]:/dev/????'.
OFLAG is O_RDONLY, O_WRONLY, etc.
MODE is ignored; 0666 is always used.
If successful, return the remote tape pipe number plus BIAS.
On error, return -1. */
int
__rmt_open (path, oflag, mode, bias)
char *path;
int oflag;
int mode;
int bias;
{
int i, rc;
char buffer[CMDBUFSIZE]; /* Command buffer. */
char system[MAXHOSTLEN]; /* The remote host name. */
char device[CMDBUFSIZE]; /* The remote device name. */
char login[CMDBUFSIZE]; /* The remote user name. */
char *sys, *dev, *user; /* For copying into the above buffers. */
sys = system;
dev = device;
user = login;
/* Find an unused pair of file descriptors. */
for (i = 0; i < MAXUNIT; i++)
if (READ (i) == -1 && WRITE (i) == -1)
break;
if (i == MAXUNIT)
{
errno = EMFILE;
return -1;
}
/* Pull apart the system and device, and optional user.
Don't munge the original string. */
while (*path != '@'
#ifdef COMPAT
&& *path != '.'
#endif
&& *path != ':')
{
*sys++ = *path++;
}
*sys = '\0';
path++;
if (*(path - 1) == '@')
{
/* Saw user part of user@host. Start over. */
strcpy (user, system);
sys = system;
while (*path != ':')
{
*sys++ = *path++;
}
*sys = '\0';
path++;
}
#ifdef COMPAT
else if (*(path - 1) == '.')
{
while (*path != ':')
{
*user++ = *path++;
}
*user = '\0';
path++;
}
#endif
else
*user = '\0';
while (*path)
{
*dev++ = *path++;
}
*dev = '\0';
#ifdef HAVE_NETDB_H
/* Execute the remote command using rexec. */
READ (i) = WRITE (i) = _rmt_rexec (system, login);
if (READ (i) < 0)
return -1;
#else /* !HAVE_NETDB_H */
/* Set up the pipes for the `rsh' command, and fork. */
if (pipe (to_rmt[i]) == -1 || pipe (from_rmt[i]) == -1)
return -1;
rc = fork ();
if (rc == -1)
return -1;
if (rc == 0)
{
/* Child. */
close (0);
dup (to_rmt[i][0]);
close (to_rmt[i][0]);
close (to_rmt[i][1]);
close (1);
dup (from_rmt[i][1]);
close (from_rmt[i][0]);
close (from_rmt[i][1]);
setuid (getuid ());
setgid (getgid ());
if (*login)
{
execl ("/usr/ucb/rsh", "rsh", system, "-l", login,
"/etc/rmt", (char *) 0);
execl ("/usr/bin/remsh", "remsh", system, "-l", login,
"/etc/rmt", (char *) 0);
execl ("/usr/bin/rsh", "rsh", system, "-l", login,
"/etc/rmt", (char *) 0);
execl ("/usr/bsd/rsh", "rsh", system, "-l", login,
"/etc/rmt", (char *) 0);
execl ("/usr/bin/nsh", "nsh", system, "-l", login,
"/etc/rmt", (char *) 0);
}
else
{
execl ("/usr/ucb/rsh", "rsh", system,
"/etc/rmt", (char *) 0);
execl ("/usr/bin/remsh", "remsh", system,
"/etc/rmt", (char *) 0);
execl ("/usr/bin/rsh", "rsh", system,
"/etc/rmt", (char *) 0);
execl ("/usr/bsd/rsh", "rsh", system,
"/etc/rmt", (char *) 0);
execl ("/usr/bin/nsh", "nsh", system,
"/etc/rmt", (char *) 0);
}
/* Bad problems if we get here. */
perror ("cannot execute remote shell");
_exit (1);
}
/* Parent. */
close (to_rmt[i][0]);
close (from_rmt[i][1]);
#endif /* !HAVE_NETDB_H */
/* Attempt to open the tape device. */
sprintf (buffer, "O%s\n%d\n", device, oflag);
if (command (i, buffer) == -1 || status (i) == -1)
return -1;
return i + bias;
}
/* Close remote tape connection FILDES and shut down.
Return 0 if successful, -1 on error. */
int
__rmt_close (fildes)
int fildes;
{
int rc;
if (command (fildes, "C\n") == -1)
return -1;
rc = status (fildes);
_rmt_shutdown (fildes);
return rc;
}
/* Read up to NBYTE bytes into BUF from remote tape connection FILDES.
Return the number of bytes read on success, -1 on error. */
int
__rmt_read (fildes, buf, nbyte)
int fildes;
char *buf;
unsigned int nbyte;
{
int rc, i;
char buffer[CMDBUFSIZE];
sprintf (buffer, "R%d\n", nbyte);
if (command (fildes, buffer) == -1 || (rc = status (fildes)) == -1)
return -1;
for (i = 0; i < rc; i += nbyte, buf += nbyte)
{
nbyte = read (READ (fildes), buf, rc - i);
if (nbyte <= 0)
{
_rmt_shutdown (fildes);
errno = EIO;
return -1;
}
}
return rc;
}
/* Write NBYTE bytes from BUF to remote tape connection FILDES.
Return the number of bytes written on success, -1 on error. */
int
__rmt_write (fildes, buf, nbyte)
int fildes;
char *buf;
unsigned int nbyte;
{
char buffer[CMDBUFSIZE];
RETSIGTYPE (*pipe_handler) ();
sprintf (buffer, "W%d\n", nbyte);
if (command (fildes, buffer) == -1)
return -1;
pipe_handler = signal (SIGPIPE, SIG_IGN);
if (write (WRITE (fildes), buf, nbyte) == nbyte)
{
signal (SIGPIPE, pipe_handler);
return status (fildes);
}
/* Write error. */
signal (SIGPIPE, pipe_handler);
_rmt_shutdown (fildes);
errno = EIO;
return -1;
}
/* Perform an imitation lseek operation on remote tape connection FILDES.
Return the new file offset if successful, -1 if on error. */
long
__rmt_lseek (fildes, offset, whence)
int fildes;
long offset;
int whence;
{
char buffer[CMDBUFSIZE];
sprintf (buffer, "L%ld\n%d\n", offset, whence);
if (command (fildes, buffer) == -1)
return -1;
return status (fildes);
}
/* Perform a raw tape operation on remote tape connection FILDES.
Return the results of the ioctl, or -1 on error. */
#ifdef MTIOCTOP
int
__rmt_ioctl (fildes, op, arg)
int fildes, op;
char *arg;
{
char c;
int rc, cnt;
char buffer[CMDBUFSIZE];
switch (op)
{
default:
errno = EINVAL;
return -1;
case MTIOCTOP:
/* MTIOCTOP is the easy one. Nothing is transfered in binary. */
sprintf (buffer, "I%d\n%d\n", ((struct mtop *) arg)->mt_op,
((struct mtop *) arg)->mt_count);
if (command (fildes, buffer) == -1)
return -1;
return status (fildes); /* Return the count. */
case MTIOCGET:
/* Grab the status and read it directly into the structure.
This assumes that the status buffer is not padded
and that 2 shorts fit in a long without any word
alignment problems; i.e., the whole struct is contiguous.
NOTE - this is probably NOT a good assumption. */
if (command (fildes, "S") == -1 || (rc = status (fildes)) == -1)
return -1;
for (; rc > 0; rc -= cnt, arg += cnt)
{
cnt = read (READ (fildes), arg, rc);
if (cnt <= 0)
{
_rmt_shutdown (fildes);
errno = EIO;
return -1;
}
}
/* Check for byte position. mt_type is a small integer field
(normally) so we will check its magnitude. If it is larger than
256, we will assume that the bytes are swapped and go through
and reverse all the bytes. */
if (((struct mtget *) arg)->mt_type < 256)
return 0;
for (cnt = 0; cnt < rc; cnt += 2)
{
c = arg[cnt];
arg[cnt] = arg[cnt + 1];
arg[cnt + 1] = c;
}
return 0;
}
}
#endif

View File

@ -1 +0,0 @@
#define SAFE_STAT(path,pbuf) stat(path,pbuf)

View File

@ -1,43 +0,0 @@
/* stripslash.c -- remove trailing slashes from a string
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., 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
#include <strings.h>
#endif
/* Remove trailing slashes from PATH.
This is useful when using filename completion from a shell that
adds a "/" after directory names (such as tcsh and bash), because
the Unix rename and rmdir system calls return an "Invalid argument" error
when given a path that ends in "/" (except for the root directory). */
void
strip_trailing_slashes (path)
char *path;
{
int last;
last = strlen (path) - 1;
while (last > 0 && path[last] == '/')
path[last--] = '\0';
}

View File

@ -1,142 +0,0 @@
/* System dependent declarations. Requires sys/types.h.
Copyright (C) 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#ifndef index
#define index strchr
#endif
#ifndef rindex
#define rindex strrchr
#endif
#ifndef bcmp
#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
#endif
#ifndef bzero
#define bzero(s, n) memset ((s), 0, (n))
#endif
#else
#include <strings.h>
#endif
#include <time.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
#ifndef _POSIX_VERSION
#if defined(__MSDOS__) && !defined(__GNUC__)
typedef long off_t;
#endif
off_t lseek ();
#endif
/* Since major is a function on SVR4, we can't use `ifndef major'. */
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
#define HAVE_MAJOR
#endif
#ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#define HAVE_MAJOR
#endif
#ifdef major /* Might be defined in sys/types.h. */
#define HAVE_MAJOR
#endif
#ifndef HAVE_MAJOR
#define major(dev) (((dev) >> 8) & 0xff)
#define minor(dev) ((dev) & 0xff)
#define makedev(ma, mi) (((ma) << 8) | (mi))
#endif
#undef HAVE_MAJOR
#if defined(__MSDOS__) || defined(_POSIX_VERSION) || defined(HAVE_FCNTL_H)
#include <fcntl.h>
#else
#include <sys/file.h>
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#include <errno.h>
#ifndef errno
extern int errno;
#endif
#ifdef __EMX__ /* gcc on OS/2. */
#define EPERM EACCES
#define ENXIO EIO
#endif
#ifdef HAVE_UTIME_H
#include <utime.h>
#else
struct utimbuf
{
time_t actime;
time_t modtime;
};
#endif
#ifdef TRUE
#undef TRUE
#endif
#define TRUE 1
#ifdef FALSE
#undef FALSE
#endif
#define FALSE 0
#ifndef __MSDOS__
#define CONSOLE "/dev/tty"
#else
#define CONSOLE "con"
#endif
#if defined(__MSDOS__) && !defined(__GNUC__)
typedef int uid_t;
typedef int gid_t;
#endif
/* On most systems symlink() always creates links with rwxrwxrwx
protection modes, but on some (HP/UX 8.07; I think maybe DEC's OSF
on MIPS too) symlink() uses the value of umask, so links' protection modes
aren't always rwxrwxrwx. There doesn't seem to be any way to change
the modes of a link (no system call like, say, lchmod() ), it seems
the only way to set the modes right is to set umask before calling
symlink(). */
#ifndef SYMLINK_USES_UMASK
#define UMASKED_SYMLINK(name1,name2,mode) symlink(name1,name2)
#else
#define UMASKED_SYMLINK(name1,name2,mode) umasked_symlink(name1,name2,mode)
#endif /* SYMLINK_USES_UMASK */

View File

@ -1,522 +0,0 @@
/* tar.c - read in write tar headers for cpio
Copyright (C) 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#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 "rmt.h"
#include "tarhdr.h"
static void to_oct ();
static char *stash_tar_linkname ();
static char *stash_tar_filename ();
/* Compute and return a checksum for TAR_HDR,
counting the checksum bytes as if they were spaces. */
unsigned long
tar_checksum (tar_hdr)
struct tar_header *tar_hdr;
{
unsigned long sum = 0;
char *p = (char *) tar_hdr;
char *q = p + TARRECORDSIZE;
int i;
while (p < tar_hdr->chksum)
sum += *p++ & 0xff;
for (i = 0; i < 8; ++i)
{
sum += ' ';
++p;
}
while (p < q)
sum += *p++ & 0xff;
return sum;
}
/* Write out header FILE_HDR, including the file name, to file
descriptor OUT_DES. */
void
write_out_tar_header (file_hdr, out_des)
struct new_cpio_header *file_hdr;
int out_des;
{
int name_len;
union tar_record tar_rec;
struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
bzero ((char *) &tar_rec, TARRECORDSIZE);
/* process_copy_out must ensure that file_hdr->c_name is short enough,
or we will lose here. */
name_len = strlen (file_hdr->c_name);
if (name_len <= TARNAMESIZE)
{
strncpy (tar_hdr->name, file_hdr->c_name, name_len);
}
else
{
/* Fit as much as we can into `name', the rest into `prefix'. */
char *suffix = file_hdr->c_name + name_len - TARNAMESIZE;
/* We have to put the boundary at a slash. */
name_len = TARNAMESIZE;
while (*suffix != '/')
{
--name_len;
++suffix;
}
strncpy (tar_hdr->name, suffix + 1, name_len);
strncpy (tar_hdr->prefix, file_hdr->c_name, suffix - file_hdr->c_name);
}
/* SVR4 seems to want the whole mode, not just protection modes.
Nobody else seems to care, so we might as well put it all in. */
to_oct (file_hdr->c_mode, 8, tar_hdr->mode);
to_oct (file_hdr->c_uid, 8, tar_hdr->uid);
to_oct (file_hdr->c_gid, 8, tar_hdr->gid);
to_oct (file_hdr->c_filesize, 12, tar_hdr->size);
to_oct (file_hdr->c_mtime, 12, tar_hdr->mtime);
switch (file_hdr->c_mode & CP_IFMT)
{
case CP_IFREG:
if (file_hdr->c_tar_linkname)
{
/* process_copy_out makes sure that c_tar_linkname is shorter
than TARLINKNAMESIZE. */
strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname,
TARLINKNAMESIZE);
tar_hdr->typeflag = LNKTYPE;
to_oct (0, 12, tar_hdr->size);
}
else
tar_hdr->typeflag = REGTYPE;
break;
case CP_IFDIR:
tar_hdr->typeflag = DIRTYPE;
break;
#ifndef __MSDOS__
case CP_IFCHR:
tar_hdr->typeflag = CHRTYPE;
break;
case CP_IFBLK:
tar_hdr->typeflag = BLKTYPE;
break;
#ifdef CP_IFIFO
case CP_IFIFO:
tar_hdr->typeflag = FIFOTYPE;
break;
#endif /* CP_IFIFO */
#ifdef CP_IFLNK
case CP_IFLNK:
tar_hdr->typeflag = SYMTYPE;
/* process_copy_out makes sure that c_tar_linkname is shorter
than TARLINKNAMESIZE. */
strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname,
TARLINKNAMESIZE);
to_oct (0, 12, tar_hdr->size);
break;
#endif /* CP_IFLNK */
#endif /* !__MSDOS__ */
}
if (archive_format == arf_ustar)
{
char *name;
strncpy (tar_hdr->magic, TMAGIC, TMAGLEN);
strncpy (tar_hdr->magic + TMAGLEN, TVERSION, TVERSLEN);
#ifndef __MSDOS__
name = getuser (file_hdr->c_uid);
if (name)
strcpy (tar_hdr->uname, name);
name = getgroup (file_hdr->c_gid);
if (name)
strcpy (tar_hdr->gname, name);
#endif
to_oct (file_hdr->c_rdev_maj, 8, tar_hdr->devmajor);
to_oct (file_hdr->c_rdev_min, 8, tar_hdr->devminor);
}
to_oct (tar_checksum (tar_hdr), 8, tar_hdr->chksum);
tape_buffered_write ((char *) &tar_rec, out_des, TARRECORDSIZE);
}
/* Return nonzero iff all the bytes in BLOCK are NUL.
SIZE is the number of bytes to check in BLOCK; it must be a
multiple of sizeof (long). */
int
null_block (block, size)
long *block;
int size;
{
register long *p = block;
register int i = size / sizeof (long);
while (i--)
if (*p++)
return 0;
return 1;
}
/* Read a tar header, including the file name, from file descriptor IN_DES
into FILE_HDR. */
void
read_in_tar_header (file_hdr, in_des)
struct new_cpio_header *file_hdr;
int in_des;
{
long bytes_skipped = 0;
int warned = FALSE;
union tar_record tar_rec;
struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
#ifndef __MSDOS__
uid_t *uidp;
gid_t *gidp;
#endif
tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
/* Check for a block of 0's. */
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
{
#if 0
/* Found one block of 512 0's. If the next block is also all 0's
then this is the end of the archive. If not, assume the
previous block was all corruption and continue reading
the archive. */
/* 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! */
tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
#endif
{
file_hdr->c_name = "TRAILER!!!";
return;
}
#if 0
bytes_skipped = TARRECORDSIZE;
#endif
}
while (1)
{
otoa (tar_hdr->chksum, &file_hdr->c_chksum);
if (file_hdr->c_chksum != tar_checksum (tar_hdr))
{
/* If the checksum is bad, skip 1 byte and try again. When
we try again we do not look for an EOF record (all zeros),
because when we start skipping bytes in a corrupted archive
the chances are pretty good that we might stumble across
2 blocks of 512 zeros (that probably is not really the last
record) and it is better to miss the EOF and give the user
a "premature EOF" error than to give up too soon on a corrupted
archive. */
if (!warned)
{
error (0, 0, "invalid header: checksum error");
warned = TRUE;
}
bcopy (((char *) &tar_rec) + 1, (char *) &tar_rec,
TARRECORDSIZE - 1);
tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
++bytes_skipped;
continue;
}
if (archive_format != arf_ustar)
file_hdr->c_name = stash_tar_filename (NULL, tar_hdr->name);
else
file_hdr->c_name = stash_tar_filename (tar_hdr->prefix, tar_hdr->name);
file_hdr->c_nlink = 1;
otoa (tar_hdr->mode, &file_hdr->c_mode);
file_hdr->c_mode = file_hdr->c_mode & 07777;
#ifndef __MSDOS__
if (archive_format == arf_ustar
&& (uidp = getuidbyname (tar_hdr->uname)))
file_hdr->c_uid = *uidp;
else
#endif
otoa (tar_hdr->uid, &file_hdr->c_uid);
#ifndef __MSDOS__
if (archive_format == arf_ustar
&& (gidp = getgidbyname (tar_hdr->gname)))
file_hdr->c_gid = *gidp;
else
#endif
otoa (tar_hdr->gid, &file_hdr->c_gid);
otoa (tar_hdr->size, &file_hdr->c_filesize);
otoa (tar_hdr->mtime, &file_hdr->c_mtime);
otoa (tar_hdr->devmajor, (unsigned long *) &file_hdr->c_rdev_maj);
otoa (tar_hdr->devminor, (unsigned long *) &file_hdr->c_rdev_min);
file_hdr->c_tar_linkname = NULL;
switch (tar_hdr->typeflag)
{
case REGTYPE:
case CONTTYPE: /* For now, punt. */
default:
file_hdr->c_mode |= CP_IFREG;
break;
case DIRTYPE:
file_hdr->c_mode |= CP_IFDIR;
break;
#ifndef __MSDOS__
case CHRTYPE:
file_hdr->c_mode |= CP_IFCHR;
/* If a POSIX tar header has a valid linkname it's always supposed
to set typeflag to be LNKTYPE. System V.4 tar seems to
be broken, and for device files with multiple links it
puts the name of the link into linkname, but leaves typeflag
as CHRTYPE, BLKTYPE, FIFOTYPE, etc. */
file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
/* Does POSIX say that the filesize must be 0 for devices? We
assume so, but HPUX's POSIX tar sets it to be 1 which causes
us problems (when reading an archive we assume we can always
skip to the next file by skipping filesize bytes). For
now at least, it's easier to clear filesize for devices,
rather than check everywhere we skip in copyin.c. */
file_hdr->c_filesize = 0;
break;
case BLKTYPE:
file_hdr->c_mode |= CP_IFBLK;
file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
file_hdr->c_filesize = 0;
break;
#ifdef CP_IFIFO
case FIFOTYPE:
file_hdr->c_mode |= CP_IFIFO;
file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
file_hdr->c_filesize = 0;
break;
#endif
case SYMTYPE:
#ifdef CP_IFLNK
file_hdr->c_mode |= CP_IFLNK;
file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
file_hdr->c_filesize = 0;
break;
/* Else fall through. */
#endif
case LNKTYPE:
file_hdr->c_mode |= CP_IFREG;
file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
file_hdr->c_filesize = 0;
break;
#endif /* !__MSDOS__ */
case AREGTYPE:
/* Old tar format; if the last char in filename is '/' then it is
a directory, otherwise it's a regular file. */
if (file_hdr->c_name[strlen (file_hdr->c_name) - 1] == '/')
file_hdr->c_mode |= CP_IFDIR;
else
file_hdr->c_mode |= CP_IFREG;
break;
}
break;
}
if (bytes_skipped > 0)
error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
}
/* Stash the tar linkname in static storage. */
static char *
stash_tar_linkname (linkname)
char *linkname;
{
static char hold_tar_linkname[TARLINKNAMESIZE + 1];
strncpy (hold_tar_linkname, linkname, TARLINKNAMESIZE);
hold_tar_linkname[TARLINKNAMESIZE] = '\0';
return hold_tar_linkname;
}
/* Stash the tar filename and optional prefix in static storage. */
static char *
stash_tar_filename (prefix, filename)
char *prefix;
char *filename;
{
static char hold_tar_filename[TARNAMESIZE + TARPREFIXSIZE + 2];
if (prefix == NULL || *prefix == '\0')
{
strncpy (hold_tar_filename, filename, TARNAMESIZE);
hold_tar_filename[TARNAMESIZE] = '\0';
}
else
{
strncpy (hold_tar_filename, prefix, TARPREFIXSIZE);
hold_tar_filename[TARPREFIXSIZE] = '\0';
strcat (hold_tar_filename, "/");
strncat (hold_tar_filename, filename, TARNAMESIZE);
hold_tar_filename[TARPREFIXSIZE + TARNAMESIZE] = '\0';
}
return hold_tar_filename;
}
/* Convert the string of octal digits S into a number and store
it in *N. Return nonzero if the whole string was converted,
zero if there was something after the number.
Skip leading and trailing spaces. */
int
otoa (s, n)
char *s;
unsigned long *n;
{
unsigned long val = 0;
while (*s == ' ')
++s;
while (*s >= '0' && *s <= '7')
val = 8 * val + *s++ - '0';
while (*s == ' ')
++s;
*n = val;
return *s == '\0';
}
/* Convert a number into a string of octal digits.
Convert long VALUE into a DIGITS-digit field at WHERE,
including a trailing space and room for a NUL. DIGITS==3 means
1 digit, a space, and room for a NUL.
We assume the trailing NUL is already there and don't fill it in.
This fact is used by start_header and finish_header, so don't change it!
This is be equivalent to:
sprintf (where, "%*lo ", digits - 2, value);
except that sprintf fills in the trailing NUL and we don't. */
static void
to_oct (value, digits, where)
register long value;
register int digits;
register char *where;
{
--digits; /* Leave the trailing NUL slot alone. */
where[--digits] = ' '; /* Put in the space, though. */
/* Produce the digits -- at least one. */
do
{
where[--digits] = '0' + (char) (value & 7); /* One octal digit. */
value >>= 3;
}
while (digits > 0 && value != 0);
/* Add leading spaces, if necessary. */
while (digits > 0)
where[--digits] = ' ';
}
/* Return
2 if BUF is a valid POSIX tar header (the checksum is correct
and it has the "ustar" magic string),
1 if BUF is a valid old tar header (the checksum is correct),
0 otherwise. */
int
is_tar_header (buf)
char *buf;
{
struct tar_header *tar_hdr = (struct tar_header *) buf;
unsigned long chksum;
otoa (tar_hdr->chksum, &chksum);
if (chksum != tar_checksum (tar_hdr))
return 0;
/* GNU tar 1.10 and previous set the magic field to be "ustar " instead
of "ustar\0". Only look at the first 5 characters of the magic
field so we can recognize old GNU tar ustar archives. */
if (!strncmp (tar_hdr->magic, TMAGIC, TMAGLEN - 1))
return 2;
return 1;
}
/* Return TRUE if the filename is too long to fit in a tar header.
For old tar headers, if the filename's length is less than or equal
to 100 then it will fit, otherwise it will not. For POSIX tar headers,
if the filename's length is less than or equal to 100 then it
will definitely fit, and if it is greater than 256 then it
will definitely not fit. If the length is between 100 and 256,
then the filename will fit only if it is possible to break it
into a 155 character "prefix" and 100 character "name". There
must be a slash between the "prefix" and the "name", although
the slash is not stored or counted in either the "prefix" or
the "name", and there must be at least one character in both
the "prefix" and the "name". If it is not possible to break down
the filename like this then it will not fit. */
int
is_tar_filename_too_long (name)
char *name;
{
int whole_name_len;
int prefix_name_len;
char *p;
whole_name_len = strlen (name);
if (whole_name_len <= TARNAMESIZE)
return FALSE;
if (archive_format != arf_ustar)
return TRUE;
if (whole_name_len > TARNAMESIZE + TARPREFIXSIZE + 1)
return TRUE;
/* See whether we can split up the name into acceptably-sized
`prefix' and `name' (`p') pieces. Start out by making `name'
as big as possible, then shrink it by looking for the first '/'. */
p = name + whole_name_len - TARNAMESIZE;
while (*p != '/' && *p != '\0')
++p;
if (*p == '\0')
/* The last component of the path is longer than TARNAMESIZE. */
return TRUE;
prefix_name_len = p - name - 1;
/* Interestingly, a name consisting of a slash followed by
TARNAMESIZE characters can't be stored, because the prefix
would be empty, and thus ignored. */
if (prefix_name_len > TARPREFIXSIZE || prefix_name_len == 0)
return TRUE;
return FALSE;
}

View File

@ -1,112 +0,0 @@
/* Extended tar format from POSIX.1.
Copyright (C) 1992 Free Software Foundation, Inc.
Written by David J. MacKenzie.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#ifndef _TAR_H
#define _TAR_H 1
/* A tar archive consists of 512-byte blocks.
Each file in the archive has a header block followed by 0+ data blocks.
Two blocks of NUL bytes indicate the end of the archive. */
/* The fields of header blocks:
All strings are stored as ISO 646 (approximately ASCII) strings.
Fields are numeric unless otherwise noted below; numbers are ISO 646
representations of octal numbers, with leading zeros as needed.
linkname is only valid when typeflag==LNKTYPE. It doesn't use prefix;
files that are links to pathnames >100 chars long can not be stored
in a tar archive.
If typeflag=={LNKTYPE,SYMTYPE,DIRTYPE} then size must be 0.
devmajor and devminor are only valid for typeflag=={BLKTYPE,CHRTYPE}.
chksum contains the sum of all 512 bytes in the header block,
treating each byte as an 8-bit unsigned value and treating the
8 bytes of chksum as blank characters.
uname and gname are used in preference to uid and gid, if those
names exist locally.
Field Name Byte Offset Length in Bytes Field Type
name 0 100 NUL-terminated if NUL fits
mode 100 8
uid 108 8
gid 116 8
size 124 12
mtime 136 12
chksum 148 8
typeflag 156 1 see below
linkname 157 100 NUL-terminated if NUL fits
magic 257 6 must be TMAGIC (NUL term.)
version 263 2 must be TVERSION
uname 265 32 NUL-terminated
gname 297 32 NUL-terminated
devmajor 329 8
devminor 337 8
prefix 345 155 NUL-terminated if NUL fits
If the first character of prefix is '\0', the file name is name;
otherwise, it is prefix/name. Files whose pathnames don't fit in that
length can not be stored in a tar archive. */
/* The bits in mode: */
#define TSUID 04000
#define TSGID 02000
#define TSVTX 01000
#define TUREAD 00400
#define TUWRITE 00200
#define TUEXEC 00100
#define TGREAD 00040
#define TGWRITE 00020
#define TGEXEC 00010
#define TOREAD 00004
#define TOWRITE 00002
#define TOEXEC 00001
/* The values for typeflag:
Values 'A'-'Z' are reserved for custom implementations.
All other values are reserved for future POSIX.1 revisions. */
#define REGTYPE '0' /* Regular file (preferred code). */
#define AREGTYPE '\0' /* Regular file (alternate code). */
#define LNKTYPE '1' /* Hard link. */
#define SYMTYPE '2' /* Symbolic link (hard if not supported). */
#define CHRTYPE '3' /* Character special. */
#define BLKTYPE '4' /* Block special. */
#define DIRTYPE '5' /* Directory. */
#define FIFOTYPE '6' /* Named pipe. */
#define CONTTYPE '7' /* Contiguous file */
/* (regular file if not supported). */
/* Contents of magic field and its length. */
#define TMAGIC "ustar"
#define TMAGLEN 6
/* Contents of the version field and its length. */
#define TVERSION "00"
#define TVERSLEN 2
#endif /* tar.h */

View File

@ -1,62 +0,0 @@
/* Extended tar header from POSIX.1.
Copyright (C) 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _TARHDR_H
#define _TARHDR_H 1
#include <tar.h>
/* Size of `name' field. */
#define TARNAMESIZE 100
/* Size of `linkname' field. */
#define TARLINKNAMESIZE 100
/* Size of `prefix' field. */
#define TARPREFIXSIZE 155
/* Size of entire tar header. */
#define TARRECORDSIZE 512
struct tar_header
{
char name[TARNAMESIZE];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag;
char linkname[TARLINKNAMESIZE];
char magic[6];
char version[2];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char prefix[TARPREFIXSIZE];
};
union tar_record
{
struct tar_header header;
char buffer[TARRECORDSIZE];
};
#endif /* tarhdr.h */

View File

@ -1,240 +0,0 @@
/* tcexparg.c - Unix-style command line wildcards for Turbo C 2.0
This file is in the public domain.
Compile your main program with -Dmain=_main and link with this file.
After that, it is just as if the operating system had expanded the
arguments, except that they are not sorted. The program name and all
arguments that are expanded from wildcards are lowercased.
Syntax for wildcards:
* Matches zero or more of any character (except a '.' at
the beginning of a name).
? Matches any single character.
[r3z] Matches 'r', '3', or 'z'.
[a-d] Matches a single character in the range 'a' through 'd'.
[!a-d] Matches any single character except a character in the
range 'a' through 'd'.
The period between the filename root and its extension need not be
given explicitly. Thus, the pattern `a*e' will match 'abacus.exe'
and 'axyz.e' as well as 'apple'. Comparisons are not case sensitive.
Authors:
The expargs code is a modification of wildcard expansion code
written for Turbo C 1.0 by
Richard Hargrove
Texas Instruments, Inc.
P.O. Box 869305, m/s 8473
Plano, Texas 75086
214/575-4128
and posted to USENET in September, 1987.
The wild_match code was written by Rich Salz, rsalz@bbn.com,
posted to net.sources in November, 1986.
The code connecting the two is by Mike Slomin, bellcore!lcuxa!mike2,
posted to comp.sys.ibm.pc in November, 1988.
Major performance enhancements and bug fixes, and source cleanup,
by David MacKenzie, djm@gnu.ai.mit.edu. */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>
#include <dir.h>
/* Number of new arguments to allocate space for at a time. */
#define ARGS_INCREMENT 10
/* The name this program was run with, for error messages. */
static char *program_name;
static char **grow_argv (char **new_argv, int new_argc);
static void fatal_error (const char *message);
int wild_match (char *string, char *pattern);
char *basename (char *path);
char **expargs (int *, char **);
#ifdef main
#undef main
#endif
int
main (int argc, char **argv, char **envp)
{
argv = expargs (&argc, argv);
return _main (argc, argv, envp);
}
char **
expargs (int *pargc, char **argv)
{
char path[MAXPATH + 1];
char **new_argv;
struct ffblk block;
char *path_base;
char *arg_base;
int argind;
int new_argc;
int path_length;
int matched;
program_name = argv[0];
if (program_name && *program_name)
strlwr (program_name);
new_argv = grow_argv (NULL, 0);
new_argv[0] = argv[0];
new_argc = 1;
for (argind = 1; argind < *pargc; ++argind)
{
matched = 0;
if (strpbrk (argv[argind], "?*[") != NULL)
{
strncpy (path, argv[argind], MAXPATH - 3);
path_base = basename (path);
strcpy (path_base, "*.*");
arg_base = argv[argind] + (path_base - path);
if (!findfirst (path, &block, FA_DIREC))
{
strlwr (path);
do
{
/* Only match "." and ".." explicitly. */
if (*block.ff_name == '.' && *arg_base != '.')
continue;
path_length = stpcpy (path_base, block.ff_name) - path + 1;
strlwr (path_base);
if (wild_match (path, argv[argind]))
{
matched = 1;
new_argv[new_argc] = (char *) malloc (path_length);
if (new_argv[new_argc] == NULL)
fatal_error ("memory exhausted");
strcpy (new_argv[new_argc++], path);
new_argv = grow_argv (new_argv, new_argc);
}
} while (!findnext (&block));
}
}
if (matched == 0)
new_argv[new_argc++] = argv[argind];
new_argv = grow_argv (new_argv, new_argc);
}
*pargc = new_argc;
new_argv[new_argc] = NULL;
return &new_argv[0];
}
/* Return a pointer to the last element of PATH. */
char *
basename (char *path)
{
char *tail;
for (tail = path; *path; ++path)
if (*path == ':' || *path == '\\')
tail = path + 1;
return tail;
}
static char **
grow_argv (char **new_argv, int new_argc)
{
if (new_argc % ARGS_INCREMENT == 0)
{
new_argv = (char **) realloc
(new_argv, sizeof (char *) * (new_argc + ARGS_INCREMENT));
if (new_argv == NULL)
fatal_error ("memory exhausted");
}
return new_argv;
}
static void
fatal_error (const char *message)
{
putc ('\n', stderr);
if (program_name && *program_name)
{
fputs (program_name, stderr);
fputs (": ", stderr);
}
fputs (message, stderr);
putc ('\n', stderr);
exit (1);
}
/* Shell-style pattern matching for ?, \, [], and * characters.
I'm putting this replacement in the public domain.
Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. */
/* The character that inverts a character class; '!' or '^'. */
#define INVERT '!'
static int star (char *string, char *pattern);
/* Return nonzero if `string' matches Unix-style wildcard pattern
`pattern'; zero if not. */
int
wild_match (char *string, char *pattern)
{
int prev; /* Previous character in character class. */
int matched; /* If 1, character class has been matched. */
int reverse; /* If 1, character class is inverted. */
for (; *pattern; string++, pattern++)
switch (*pattern)
{
case '\\':
/* Literal match with following character; fall through. */
pattern++;
default:
if (*string != *pattern)
return 0;
continue;
case '?':
/* Match anything. */
if (*string == '\0')
return 0;
continue;
case '*':
/* Trailing star matches everything. */
return *++pattern ? star (string, pattern) : 1;
case '[':
/* Check for inverse character class. */
reverse = pattern[1] == INVERT;
if (reverse)
pattern++;
for (prev = 256, matched = 0; *++pattern && *pattern != ']';
prev = *pattern)
if (*pattern == '-'
? *string <= *++pattern && *string >= prev
: *string == *pattern)
matched = 1;
if (matched == reverse)
return 0;
continue;
}
return *string == '\0';
}
static int
star (char *string, char *pattern)
{
while (wild_match (string, pattern) == 0)
if (*++string == '\0')
return 0;
return 1;
}

View File

@ -1,277 +0,0 @@
/* userspec.c -- Parse a user and group string.
Copyright (C) 1989, 1990, 1991, 1992 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#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>
#include <grp.h>
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#ifndef index
#define index strchr
#endif
#else
#include <strings.h>
#endif
#ifdef STDC_HEADERS
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef _POSIX_VERSION
struct passwd *getpwnam ();
struct group *getgrnam ();
struct group *getgrgid ();
#endif
#ifdef _POSIX_SOURCE
#define endpwent()
#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 ();
/* 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.
Either user or group, or both, must be present.
If the group is omitted but the ":" or "." separator is given,
use the given user's login group.
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.
Return NULL if successful, a static error message string if not. */
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_arg, **groupname_arg;
{
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 *g, *u, *separator;
char *groupname;
error_msg = NULL;
*username_arg = *groupname_arg = NULL;
groupname = NULL;
V_STRDUP (spec, spec_arg);
/* 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)
{
pwd = getpwnam (u);
if (pwd == NULL)
{
if (!isnumber (u))
error_msg = "invalid user";
else
{
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
{
*uid = pwd->pw_uid;
if (g == NULL && separator != NULL)
{
/* 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 ();
}
}
endpwent ();
}
if (g != NULL && error_msg == NULL)
{
/* 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);
}
if (error_msg == NULL)
{
if (u != NULL)
{
*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)
{
if (*username_arg != NULL)
{
free (*username_arg);
*username_arg = NULL;
}
error_msg = tired;
}
}
}
return error_msg;
}
#ifdef TEST
#define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s))
int
main (int argc, char **argv)
{
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

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +0,0 @@
/* The version number of cpio and mt. */
char *version_string = "version 2.4.2\n";

View File

@ -1,103 +0,0 @@
/* xmalloc.c -- malloc with out of memory checking
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
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
#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
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. */
VOID *
xmalloc (n)
size_t n;
{
VOID *p;
p = malloc (n);
if (p == 0)
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. */
VOID *
xrealloc (p, n)
VOID *p;
size_t n;
{
if (p == 0)
return xmalloc (n);
p = realloc (p, n);
if (p == 0)
p = fixup_null_alloc (n);
return p;
}

View File

@ -1,36 +0,0 @@
/* xstrdup.c -- copy a string with out of memory checking
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., 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
#include <strings.h>
#endif
char *xmalloc ();
/* Return a newly allocated copy of STRING. */
char *
xstrdup (string)
char *string;
{
return strcpy (xmalloc (strlen (string) + 1), string);
}