This is GNU cpio 2.3. It handles tar files and is fully compatible

with SYSV cpio.  It's also supposed to integrate rmt support, though
I haven't tried this.
This commit is contained in:
Jordan K. Hubbard 1993-08-07 22:33:48 +00:00
parent db8789d38e
commit 8843e04abc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=253
46 changed files with 12084 additions and 0 deletions

339
gnu/usr.bin/cpio/COPYING Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 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.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, 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 software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, 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 redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
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 give any other recipients of the Program a copy of this License
along with the Program.
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 Program or any portion
of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
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 Program, 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 Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) 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; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, 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 executable. 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.
If distribution of executable or 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 counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program 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.
5. 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 Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program 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.
7. 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 Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program 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 Program.
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.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program 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.
9. The Free Software Foundation may publish revised and/or new versions
of the 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 Program
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 Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, 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
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), 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 Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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 of the License, 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.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -0,0 +1,481 @@
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!

781
gnu/usr.bin/cpio/ChangeLog Normal file
View File

@ -0,0 +1,781 @@
Mon Jul 5 14:54:08 1993 John Oleynick (juo@spiff.gnu.ai.mit.edu)
* cpio.1: Updated man page for 2.3.
* Makefile.in: Create distribution with .gz extension, instead of .z.
Tue Jun 29 18:54:37 1993 John Oleynick (juo@goldman.gnu.ai.mit.edu)
* Makefile.in: Added installdirs target (using mkinstalldirs).
* Added mkinstalldirs script.
* main.c, mt.c: Added --help option. Changed usage() to
take a stream and exit value (so --help can print on stdout
and return a 0 exit status).
* extern.h: Removed usage()'s prototype (it was out of date,
and only used in main.c).
Thu May 6 00:22:22 1993 John Oleynick (juo@hal.gnu.ai.mit.edu)
* cpio.1: Added hpbin and hpodc.
Tue May 4 00:32:29 1993 John Oleynick (juo@hal.gnu.ai.mit.edu)
* copyin.c (process_copy_in), copypass.c (process_copy_pass): When
deleting an existing file, if the file is a directory, use rmdir()
instead of unlink().
Thu Apr 29 14:43:56 1993 John Oleynick (juo@goldman.gnu.ai.mit.edu)
* tar.c (read_in_tar_header): Clear non-protection bits from
mode, in case tar has left some device bits in there.
Wed Apr 28 10:36:53 1993 John Oleynick (juo@goldman.gnu.ai.mit.edu)
* util.c: Added code to try and work around broken tape drivers
that have problems with tapes > 2Gb.
* copyout.c (process_copy_out): Pass file_hdr to
writeout_other_defers() and add_link_defer() by reference,
not by value.
* copyin.c (process_copy_in): Pass file_hdr to defer_copyin()
and create_defered_links() by reference, not by value.
* defer.c: include <sys/types.h> (to build on BSD 4.3 on HP300)
Fri Apr 16 18:01:17 1993 John Oleynick (juo@goldman.gnu.ai.mit.edu)
* mt.c, util.c: Include <sys/mtio.h> if HAVE_SYS_MTIO_H is
defined, not HAVE_MTIO_H.
Wed Apr 14 17:37:46 1993 John Oleynick (juo@goldman.gnu.ai.mit.edu)
* util.c: Include <sys/io/trioctl.h> if HAVE_SYS_IO_TRIOCTL_H
is defined.
* mt.c: Only include <sys/mtio.h> if HAVE_SYS_MTIO_H is defined.
Fri Apr 2 13:09:11 1993 John Oleynick (juo@goldman.gnu.ai.mit.edu)
* configure.in: Added fnmatch to AC_REPLACE_FUNCS. Added
sys/io/trioctl.h to AC_HAVE_HEADERS.
* Makefile.in: Removed fnmatch.o from OBJS.
* copyin.c: Only include "fnmatch.h" if FNM_PATHNAME isn't
defined yet.
* mt.c: Include <sys/io/trioctl.h> if HAVE_SYS_IO_TRIOCTL_H is
defined.
Mon Mar 29 17:04:06 1993 John Oleynick (juo@hal.gnu.ai.mit.edu)
* Many changes for supporting HPUX Context Dependent Files;
also some bug fixes to fix problems with multiply (hard) linked
device files; minor changes to support HPUX format archives
(slightly broken?) System V.4 posix tar archives and HPUX
posix tar archives.
* Makefile.in: New files defer.o, defer,c and defer.h; added
-DSYMLINK_USES_UMASK and -DHPUX_CDF comments; changed dist rule
to use gzip with tar, instead of compress.
* copyin.c: changes for new arf_hpbinary and arf_hpascii formats;
HPUX CDF's; DEBUG_CPIO; fixes to properly handle multiple
links in newc and crc format archives (new routines defer_copyin(),
create_defered_links(), create_final_defers()); move most
multiple (hard) link code to new routines link_name() and
link_to_maj_min_ino(); use new macro UMASKED_SYMLINK instead of
symlink().
* copyout.c: fixes to properly handle multiple links in newc
and crc format archives (new routines last_link(),
count_defered_links_to_dev_ino(), add_link_defer(),
writeout_other_defers(), writeout_final_defers(),
writeout_defered_file()); support for new arf_hpbinary and
arf_hpascii formats; support for HPUX CDF's.
* copypass.c: move most multiple link code to new routines
link_name() and link_to_maj_min_ino(); use new macro UMASKED_SYMLINK
instead of symlink(); support for HPUX CDF's.
* extern.h: added arf_hpascii and arf_hpbinary archive enum types;
added debug_flag.
* global.c: added debug_flag.
* main.c: added debug_flag; support for hpodc and hpbin formats.
* makepath.c: split from standard makpath.c to add support
for HPUX CDF's.
* mt.c: added !defined(__osf__) (from Andrew Marquis
<amarquis@genome.wi.mit.edu>).
* system.h: new macro UMASKED_SYMLINK
* tar.c: minor changes to read (slightly broken?) System V.4 posix
tar archives and HPUX posix tar archives.
* util.c: HPUX CDF support (including new routines
add_cdf_double_slashes() and islasparentcdf()); new routine
umasked_symlink().
Sun Mar 14 23:00:14 1993 Jim Meyering (meyering@comco.com)
* copypass.c (process_copy_pass): Use <=, not just <, when comparing
mtimes. From Pieter Bowman <bowman@math.utah.edu>.
Fri Jan 15 14:35:37 1993 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu)
* copyin.c: Move include of fnmatch.h to get right FNM* macros.
Tue Nov 24 08:45:32 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu)
* Version 2.2.
* copyout.c (process_copy_out): Add parens for gcc -Wall.
From Jim Meyering.
* system.h: Use HAVE_FCNTL_H, not USG.
* dstring.c, mt.c, system.h: Use HAVE_STRING_H, not USG.
Fri Nov 20 22:47:18 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu)
* copyin.c (read_in_binary): Copy the dev and ino that are
already in `file_hdr' into `short_hdr'.
From dao@abars.att.com (David A Oshinsky).
* system.h [!_POSIX_VERSION]: Declare lseek as off_t, not long.
From Karl Berry.
Wed Oct 14 13:53:41 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu)
* Version 2.1.
Tue Oct 13 22:51:34 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu)
* main.c: Add --swap equivalent to -b.
* mt.c: Add f_force_local variable and -V --version option.
Fri Oct 2 18:42:27 1992 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu)
* main.c (long_opts, usage): Add --force-local option.
Thu Oct 1 23:23:43 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu)
* main.c (process_args) [__MSDOS__]: Don't call geteuid.
* copyin.c (read_in_{old,new}_ascii): Use `l' for sscanf into longs.
* copyout.c (write_out_header): Ditto for sprintf.
* global.c, extern.h: Make input_size and output_size long.
Thu Sep 10 23:39:30 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu)
* global.c, extern.h: Add new var f_force_local to work with
rmt.h change from tar.
Sun Aug 23 00:18:20 1992 David J. MacKenzie (djm@churchy.gnu.ai.mit.edu)
* Version 2.0.
* tar.c (otoa): Compute value in an unsigned long, not an int.
* copyout.c (write_out_header) [__MSDOS__]: Don't use dev_t.
* main.c (process_args): By default, don't chown for non-root users.
Sat Aug 22 14:17:54 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu)
* global.c, extern.h: Use uid_t and gid_t.
* main.c (main) [__EMX__]: Expand wildcards.
* system.h [__EMX__]: Alias some error names. From Kai Uwe Rommel.
* extern.h [__STDC__]: Use prototypes.
* copyin.c (process_copy_in), copyout.c (process_copy_out),
copypass.c (process_copy_pass): Open all files with O_BINARY.
Add cast to chmod call.
* util.c: Add cast to bcopy calls. Make hash_insert static.
From Kai Uwe Rommel.
Thu Aug 20 22:03:49 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu)
* util.c (peek_in_buf): Don't print "end of file" before
getting the next reel of medium.
* copyin.c (read_in_old_ascii): Allocate space for NUL terminator.
Print newline for dot line when done, even if appending.
Thu Jul 23 16:34:53 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu)
* tar.c (write_out_tar_header, read_in_tar_header)
[__MSDOS__]: Don't try to get user and group names.
* extern.h: Don't declare the functions to do it (need uid_t).
* main.c [__MSDOS__]: Ignore the -R option.
* system.h: Define makedev if defining major and minor.
* copyin.c, copyout.c [__MSDOS__]: setmode on archive_des, not
0 and 1.
Sat Jul 18 14:30:55 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu)
* tar.c, stripslash.c, userspec.c, cpiohdr.h, tar.h, tarhdr.h,
system.h: New files.
* Move portability stuff from various files to system.h.
* cpio.h: Rename header structure and members, and add
new structure for SVR4 format.
* copyin.c, copyout.c: Use the new structure internally, the
old one only for I/O in the old formats.
* copyin.c (read_in_header): Recognize the new archive formats.
(read_in_new_ascii, read_pattern_file, skip_padding): New functions.
(swab_array): Do the swapping using char pointers instead of
bitwise arithmetic.
(process_copy_in): Handle byte and halfword swapping and new formats.
Ok if a directory we want to make already exists, but set its perms.
Do chmod after chown to fix any set[ug]id bits.
Use `struct utimbuf' instead of a long array.
* copyout.c (write_out_header): Handle new formats.
(process_copy_out): Use `struct utimbuf'.
Handle appending and new formats.
Remove any leading `./' from filenames.
(read_for_checksum, clear_rest_of_block, pad_output): New functions.
* copypass.c (process_copy_pass): Use `struct utimbuf'.
Ok if a directory we want to make already exists, but set its perms.
Do chmod after chown to fix any set[ug]id bits.
Don't change perms of `.'.
* extern.h, global.c: Replace the separate format flags with
one variable. Add new variables for the new options.
* main.c: Add new options -A --append, -H --format, -C --io-size,
-M --message, --no-preserve-owner, -R --owner, -E --pattern-file,
-V --dot, -s --swap-bytes, -S --swap-halfwords, -b, -I, -k, -O.
(usage): Document them.
(process_args): Recognize them. Use open_archive.
(initialize_buffers): Allow room for tar archives and double buffers.
* util.c (empty_output_buffer_swap): New function.
(empty_output_buffer): Call it if swapping current file.
Check additional end of media indicators.
(swahw_array, peek_in_buf, prepare_append, open_archive,
set_new_media_message): New functions.
(fill_input_buffer): Don't print error message if end of media.
(toss_input): Don't seek, always read.
(copy_files): Update crc if needed.
(find_inode_file, add_inode): Check major and minor numbers as
well as dev.
(get_next_reel): Prompt user if archive name is unknown.
Print fancy messages.
Close the archive and reopen it.
Above primarily from John Oleynick <juo@klinzhai.rutgers.edu>.
* util.c (find_inode_file): Use modulus when computing initial
loop index.
(add_inode): Zero out new entry.
From scott@sctc.com (Scott Hammond).
* cpio.h, copyin.c, copyout.c: Rename `struct cpio_header'
members from h_foo to c_foo.
Wed May 20 00:09:26 1992 David J. MacKenzie (djm@churchy.gnu.ai.mit.edu)
* copyin.c: If we include a header file specifically to get
major et al., assume we have them.
Mon Mar 9 19:29:20 1992 David J. MacKenzie (djm@nutrimat.gnu.ai.mit.edu)
* mt.c (main): rmtclose the tape file descriptor.
* main.c (main): rmtclose the archive, if not in copy-pass mode.
* util.c (create_all_directories): Don't print a message when
creating a directory, for UNIX compat.
* copyin.c (process_copy_in), copypass.c (process_copy_pass):
Skip file if it has the same timestamp as existing file, not just
if it is older than existing file, for UNIX compat.
Tue Mar 3 12:06:58 1992 David J. MacKenzie (djm@wookumz.gnu.ai.mit.edu)
* main.c, mt.c (usage): Document long options as starting with
-- instead of +.
* extern.h: Only declare lseek if not _POSIX_VERSION.
Tue Dec 24 00:19:45 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
* copyin.c: Use MAJOR_IN_MKDEV and MAJOR_IN_SYSMACROS instead
of USG and _POSIX_VERSION to find major and minor macros.
* mt.c: Use unistd.h and stdlib.h if available.
* copyin.c, copyout.c, copypass.c, util.c, extern.h: Change
POSIX ifdefs to HAVE_UNISTD_H and _POSIX_VERSION.
Sun Aug 25 06:31:08 1991 David J. MacKenzie (djm at apple-gunkies)
* Version 1.5.
* bcopy.c: New file (moved from util.c).
* mt.c (print_status): Not all hpux machines have mt_fileno
and mt_blkno; rather than trying to track HP's product line,
just assume none of them have them.
* util.c (copy_buf_out, copy_in_buf): Use more efficient
copying technique for a big speedup.
Fri Aug 2 04:06:45 1991 David J. MacKenzie (djm at apple-gunkies)
* configure: Support +srcdir. Create config.status.
Remove it and Makefile if interrupted while creating them.
Thu Jul 18 09:43:40 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
* Many files: use __MSDOS__ instead of MSDOS.
* util.c, configure: Use NO_MTIO instead of HAVE_MTIO, to keep
up with tar and rtapelib.c.
Mon Jul 15 13:45:30 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
* configure: Also look in sys/signal.h for signal decl.
Thu Jul 11 01:50:32 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
* Version 1.4.
* configure: Remove /etc and /usr/etc from PATH to avoid
finding /etc/install.
Wed Jul 10 01:40:07 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
* makefile.pc: Rewrite for Turbo C 2.0.
* util.c [__TURBOC__] (utime): New function.
* alloca.c, tcexparg.c: New files.
* extern.h [STDC_HEADERS]: Don't declare malloc and realloc.
* main.c [MSDOS]: Make binary mode the default.
* copyin.c, copyout.c: Make stdin or stdout binary mode as
appropriate (so cpio archives don't get corrupted).
* Many files: Use <string.h> if STDC_HEADERS as well as if USG.
* configure, Makefile.in: $(INSTALLPROG) -> $(INSTALL),
$(INSTALLTEXT) -> $(INSTALLDATA).
Mon Jul 8 23:18:28 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
* configure: For some library functions that might be missing,
conditionally add the .o files to Makefile instead of
defining func_MISSING.
* mkdir.c: Renamed from mkrmdir.c.
Sat Jul 6 02:27:22 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu)
* configure: echo messages to stdout, not stderr.
Use a test program to see if alloca needs -lPW.
Thu Jun 27 16:15:15 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu)
* copyin.c (process_copy_in), copyout.c (process_copy_out),
copypass.c (process_copy_pass): Check close return value for
delayed error notification because of NFS.
Thu Jun 20 02:43:33 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu)
* configure: Include $DEFS when compiling test programs.
* util.c: Only declare getpwuid and getgrgid if not POSIX.
* Version 1.3.
* copyin.c: Use time_t, not long, for time values.
* mt.c (print_status): Special cases for HP-UX and Ultrix.
* util.c: Compile bcopy if USG or STDC_HEADERS, not BCOPY_MISSING.
Tue Jun 11 16:40:02 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu)
* copyin.c: Don't include sys/sysmacros.h if _POSIX_SOURCE.
* copyin.c, copyout.c, copypass.c: Don't include sys/file.h if POSIX.
* util.c: Include sys/types.h before, not after, pwd.h and grp.h.
* configure: New shell script to aid configuration and create
Makefile from Makefile.in.
* copyin.c (process_copy_in): Use POSIX.2 fnmatch instead of
glob_match.
Mon Jun 10 22:11:19 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu)
* global.c, extern.h: New variable, name_end.
* main.c (process_args, usage): Add -0 +null option to set it.
* copypass.c (process_copy_pass), copyout.c (process_copy_out):
Use it.
* dstring.c (ds_fgetstr): New function made from ds_fgets.
(ds_fgets, ds_fgetname): Implement as front ends to ds_fgetstr.
Sun Jun 2 15:45:24 1991 David J. MacKenzie (djm at wheat-chex)
* most files: use GPL version 2.
Sat May 18 11:39:22 1991 David J. MacKenzie (djm at geech.gnu.ai.mit.edu)
* copyin.c, copypass.c: Take out #ifdef MSDOS around chown.
* util.c [MSDOS]: Provide dummy chown.
Fri May 17 21:29:05 1991 David J. MacKenzie (djm at churchy.gnu.ai.mit.edu)
* Version 1.2.
* makefile.pc, cpio.cs: Update for new source and object files.
Fri Mar 15 05:48:36 1991 David J. MacKenzie (djm at geech.ai.mit.edu)
* global.c, extern.h: New variable `archive_desc'.
* main.c (process_args): Set it.
* copyout.c (process_copy_out), copyin.c (process_copy_in):
Use it.
* copyout.c (process_copy_out), copyin.c (process_copy_in):
Remote tapes are special and not seekable; don't fstat them.
* main.c (main, usage): Add -F, +file option. Use rmtopen.
(main): Exit after printing version number.
* util.c (empty_output_buffer): Use rmtwrite instead of write.
(fill_input_buffer): Use rmtread instead of read.
(tape_offline): Use rmtioctl instead of ioctl.
Test HAVE_MTIO instead of MTIO_MISSING, for tar compatibility.
Thu Mar 14 17:49:57 1991 David J. MacKenzie (djm at geech.ai.mit.edu)
* util.c (create_all_directories): Use make_path to do the work.
Sat Jan 12 15:32:15 1991 David J. MacKenzie (djm at geech.ai.mit.edu)
* copyin.c, copyout.c, copypass.c, util.c: Only declare
`errno' if not MSDOS. Some Unix errno.h do, some don't . . . .
* global.c, extern.h: Make `input_size' and `output_size'
unsigned, for 16 bit machines.
* copyin.c (print_name_with_quoting): All non-ctrl chars are
printable on MS-DOS.
* util.c (empty_output_buffer): Never make sparse files;
can create unrunnable executables.
* copyin.c, copyout.c, copypass.c: Callers changed.
* util.c (finish_output_file): Function removed.
Tue Nov 6 15:47:16 1990 David J. MacKenzie (djm at apple-gunkies)
* copyin.c, util.c, extern.h: Rename copystring to xstrdup.
Mon Oct 29 02:24:41 1990 David J. MacKenzie (djm at apple-gunkies)
* util.c (empty_output_buffer): Only make sparse files if
NO_SPARSE_FILES is undefined, to accomodate dumb kernels.
Wed Jul 25 18:48:35 1990 David J. MacKenzie (djm at albert.ai.mit.edu)
* util.c (getuser, getgroup): Make uid and gid unsigned short,
not int.
Sat Jul 21 00:44:44 1990 David J. MacKenzie (djm at apple-gunkies)
* copyin.c, copyout.c, copypass.c, util.c, cpio.h: Add ifdefs
for MSDOS.
Sun Jul 15 23:51:48 1990 David J. MacKenzie (djm at albert.ai.mit.edu)
* copyin.c, copyout.c, copypass.c, global.c, extern.h, util.c:
Use longs where appropriate, for 16 bit machines.
Sun Jul 8 22:58:06 1990 David J. MacKenzie (djm at apple-gunkies)
* main.c (process_args, usage): Change -b option to -O (old), to
allow adding byte swapping later.
Sat Jul 7 14:48:35 1990 David J. MacKenzie (dave at edfmd)
* Version 1.1.
* cpio.h: Make `mtime' and `filesize' unsigned long.
* copyin.c (read_in_binary), copyout.c (write_out_header):
High short-word of `mtime' and `filesize' always comes first.
* (read_in_ascii, read_in_binary): New functions, from code in
read_in_header.
(read_in_header): Search for valid magic number, then fill in
rest of header using read_in_ascii and read_in_binary.
* global.c, extern.h: New variable, `binary_flag'.
* main.c (process_args): Recognize new -b +binary option.
* util.c [BCOPY_MISSING] (bcopy): New function.
Wed Jul 4 00:40:58 1990 David J. MacKenzie (djm at apple-gunkies)
* main.c (process_args): Add local pointers to functions to
work around a pcc bug found on a Convex.
* copyin.c (process_copy_in), util.c (toss_input,
create_all_directories, add_inode): Don't use `index' as a
variable name.
Tue Jul 3 02:33:36 1990 David J. MacKenzie (djm at apple-gunkies)
* version 1.0.
Mon Jul 2 23:18:56 1990 David J. MacKenzie (djm at twiddle)
* copyin.c (process_copy_in), copyout.c (process_copy_out),
copypass.c (process_copy_pass): Print "1 block", not "1 blocks".
* copyin.c (process_copy_in), copypass.c (process_copy_pass):
Unlink existing dest. file unless either it is newer and
not unconditional, or it is a directory.
Mon Jul 2 03:57:41 1990 David J. MacKenzie (dave at edfmd)
* util.c (xrealloc): New function.
* dstring.c (ds_resize): Use xrealloc instead of free and
xmalloc. Never shrink the string.
* copypass.c (process_copy_pass): More efficient
string handling while constructing output filename.
* global.c, extern.h, main.c, cpio.h: Change from an enum,
`copy_command', to a pointer to a void function, `copy_function'.
* cpio.h (struct cpio_header): Make most fields unsigned.
Rename h_filesize to h_filesizes and h_mtime to h_mtimes, and
add new `long' fields with the old names at the end of the
structure.
* copyin.c (read_in_header): Set the long fields from the
short arrays, making sure longs are aligned properly.
(process_copy_in, long_format): Use the long fields.
* copyout.c (write_out_header): Set the short arrays from the
long fields, making sure longs are aligned properly.
(process_copy_out): Use the long fields.
* global.c, extern.h: New variable `output_is_seekable'.
* util.c (empty_output_buffer): If output_is_seekable, use
lseek to write blocks of zeros.
(finish_output_file): New function.
* copyin.c (process_copy_in), copyout.c (process_copy_out),
copypass.c (process_copy_pass): Set `output_is_seekable'
correctly and call finish_output_file.
* main.c (initialize_buffers): Allocate space for sentinel in
`output_buffer'.
* global.c, extern.h: New variable `numeric_uid'.
* main.c (process_args): Accept -n +numeric-uid-gid option, like ls.
* copyin.c (long_format): Use numeric_uid.
* copyin.c (process_copy_in), copyout.c (process_copy_out),
copypass.c (process_copy_pass): Don't (for verbose) print the
names of files that are not copied because of errors. Try to
create missing directories for all file types. Free temporary
buffers on error.
Sat Jun 30 14:28:45 1990 David J. MacKenzie (djm at apple-gunkies)
* version.c: New file.
* main.c: Add -V, +version option.
* Makefile [dist]: Extract version number from version.c.
Sat Jun 30 12:44:47 1990 David J. MacKenzie (dave at edfmd)
* global.c, extern.h, copyin.c, copyout.c, util.c: Rename
`{input,output}_is_regular' to `{input,output}_is_special' and
reverse the truth value.
* global.c, extern.h: New variable `input_is_seekable' to
control whether to skip data with lseek or read.
* copyin.c (process_copy_in): Set it.
* util.c (toss_input): Use it.
* global.c, extern.h: New variable `xstat' that selects stat
or lstat for input files.
* main.c (process_args): New option -L, +dereference to set
xstat to stat instead of lstat.
(usage): Document it.
* copyout.c (process_copy_out), copypass.c
(process_copy_pass): Use *xstat on input file.
Sat Jun 30 01:53:12 1990 David J. MacKenzie (dave at edfmd)
* dstring.c (ds_init): Return void because return value was
never used.
(ds_resize): Ditto, and free old value instead of new one.
* util.c (empty_output_buffer, fill_input_buffer,
copy_out_buf, copy_in_buf, toss_input, copy_files): Return
void instead of an error value and make errors fatal
immediately instead of several levels up, to prevent printing
of multiple error messages by different levels of functions.
* copyin.c (read_in_header): Return void, because the error
handling all happens at lower levels.
(print_name_with_quoting): New function.
(long_format): Call print_name_with_quoting. Take additional
arg for name of linked-to file, and print it if nonzero.
(process_copy_in): For verbose listing of symlinks, read in
the linkname and pass it to long_format.
* extern.h: Declare some more functions.
Thu Jun 28 16:07:15 1990 David J. MacKenzie (dave at edfmd)
* copypass.c (process_copy_pass): Warn about unknown file types.
* copyout.c (process_copy_out): Check fstat return for error.
Record filesize of 0 for special files. Warn about unknown
file types.
* copyin.c (process_copy_in): Warn about unknown file types.
(read_in_header): Warn about byte-reversed binary headers.
Sat Jun 23 22:50:45 1990 David J. MacKenzie (dave at edfmd)
* main.c (main): Set umask to 0 so permissions of created
files are preserved.
* copyin.c, copyout.c, copypass.c, util.c: Pass file
descriptors as ints, not pointers to ints.
Cast file timestamps and sizes to long *, not int *, for 16
bit machines.
Use lstat instead of stat, if available.
Handle FIFO's, sockets, and symlinks, if supported by O.S.
* copyin.c (process_copy_in), copyout.c (process_copy_out):
Don't consider FIFO'S, sockets, etc. to be possible tape drives.
* util.c (create_all_directories): Fix incorrect loop
termination check. Only copy string if it contains slashes.
Don't check whether directory "" exists.
(tape_offline): Code moved from get_next_reel.
(get_next_reel): Print message before taking tape offline.
Read a line of arbitrary length.
* copyout.c, copyin.c, copypass.c: Always use utime, not utimes.
* copyin.c (swab_short): New macro.
(swab_array): New function.
(read_in_header): In binary mode, if a byte-swapped header is
read, swap the bytes back.
(process_copy_in, process_copy_pass): Don't stat each file to
create unless !unconditional_flag. Create device files correctly.
Don't temporarily allow files being created to be read by
other users. Don't unnecessarily chmod special files.
Thu May 31 20:51:43 1990 David J. MacKenzie (djm at albert.ai.mit.edu)
* copyin.c (long_format): Use mode_string to format
file protections instead of doing it ourselves.
(protections): Function removed.
Sat Apr 14 02:31:01 1990 David J. MacKenzie (djm at albert.ai.mit.edu)
* cpio.h (struct cpio_header): Make inode, mode, uid, gid
fields unsigned.
* util.c (getgroup): New function.
* copyin.c (long_format): Print group name of files.
Print file size, etc. as unsigned integers, not signed.
* main.c (process_args): If -t is given and neither -i, -o, or
-p is given, assume -i.
* Add -f, +nonmatching option.
* main.c: Rename +out to +create, +in to +extract,
+modification-time to +preserve-modification-time,
+pass to +pass-through.
* copyin.c (process_copy_in), copypass.c (process_copy_pass):
Don't complain in chown fails because the user doesn't have
permission.
Fri Apr 13 13:53:20 1990 David J. MacKenzie (djm at albert.ai.mit.edu)
* Add ifdefs for USG/Xenix.
* util.c (cpio_error): Function removed.
* Use error instead of cpio_error, so system error messages
will be included.
* cpio.h: Rename 'hdr_struct' to 'struct cpio_header'.
* Move definition of xmalloc from dstring.c to util.c.
* global.c, extern.c: Add global `program_name'.
* main.c (main): Set program_name.
(process_args): Rename +reset-atime to +reset-access-time,
+table to +list.
Have +block-size take an argument.
Thu Apr 12 13:33:32 1990 David J. MacKenzie (djm at rice-chex)
* util.c (find_inode_file): Make inode an int, not a short.
* Make functions that don't return a value have type void.
Add some casts to function calls.
Wed Apr 11 14:55:28 1990 David J. MacKenzie (djm at albert.ai.mit.edu)
* main.c (process_args): -i, -o, and -p don't take arguments.
* main.c (process_args): Get the non-option args from the
correct elements of argv.
Tue Apr 10 00:20:26 1990 David J. MacKenzie (djm at albert.ai.mit.edu)
* Indent source code and update copyrights.
* cpio.c (usage): Change `collection' to `archive' in message.
Thu Dec 28 03:03:55 1989 David J. MacKenzie (djm at hobbes.ai.mit.edu)
* dstring.c (xmalloc): Don't return a null pointer if size is 0,
on the assumption that trying to allocate 0 bytes is a bug that
should be trapped.
Wed Dec 20 03:24:48 1989 David J. MacKenzie (djm at hobbes.ai.mit.edu)
* All files: Change from GNU CPIO General Public License to
GNU General Public License.
Mon Dec 18 13:18:36 1989 David J. MacKenzie (djm at hobbes.ai.mit.edu)
* Makefile: Add clean target and defines for CC and LDFLAGS.
Add dist target and SRCS, DISTFILES macros. Add tags and TAGS targets.
* dstring.c (ds_fgets): Read characters into an int, not char.
(xmalloc): New function.
(out_of_memory): Function removed.
Global: use xmalloc instead of malloc and out_of_memory.
* extern.h, global.c: Make flag variables ints instead of chars for
compatibility with getopt_long.
* extern.h: Declare more functions.
* main.c (usage): Put the whole usage message into a single string
and fix errors.
* util.c (create_all_directories): Remove unused variable.
(get_next_reel): Ditto.
* dstring.h: Declare function.
Sat Dec 2 13:22:37 1989 David J. MacKenzie (djm at hobbes.ai.mit.edu)
* main.c: Change +copy-pass option to +pass, +copy-in to +in,
+copy-out to +out, and +mkdir to +make-directories, and add null
option to terminate table.
(process_args): Use the same code to handle long and short named
options.
(usage): Mention long options in message.
Local Variables:
mode: indented-text
left-margin: 8
version-control: never
End:

View File

@ -0,0 +1,9 @@
PROG= cpio
CFLAGS+= -I${.CURDIR} -DRETSIGTYPE=void -DHAVE_SYS_MTIO_H=1 -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DHAVE_FCNTL_H=1 -DHAVE_UTIME_H=1 -DHAVE_STRERROR=1 -DHAVE_VPRINTF=1 -DDIRENT=1
SRCS = copyin.c copyout.c copypass.c defer.c dstring.c fnmatch.c global.c \
main.c tar.c util.c error.c filemode.c getopt.c getopt1.c version.c \
rtapelib.c dirname.c idcache.c makepath.c xmalloc.c stripslash.c \
userspec.c xstrdup.c
.include <bsd.prog.mk>

55
gnu/usr.bin/cpio/NEWS Normal file
View File

@ -0,0 +1,55 @@
Major changes in version 2.3:
* in newc and crc format archives, only store 1 copy of multiply linked files
* handle multiply linked devices properly
* handle multiply linked files with cpio -pl even when the source and
destination are on different file systems
* support HPUX Context Dependent Files
* read and write HPUX cpio archives
* read System V.4 POSIX tar archives and HPUX POSIX tar archives
* use rmdir, instead of unlink, to delete existing directories
Major changes in version 2.2:
* handle link counts correctly when reading binary cpio archives
* configure checks for some libraries that SVR4 needs
Major changes in version 2.1:
* cpio can access remote non-device files as well as remote devices
* fix bugs in the MS-DOS port
* add --swap equivalent to -b option
Version 2.0 adds the following features:
Support for the SVR4 cpio formats, which can store inodes >65535, and
for traditional and POSIX tar archives. Also adds these options:
-A --append append to instead of replacing the archive
-V --dot print a dot for each file processed
-H --format select archive format
-C --io-size select I/O block size in bytes
-M --message print a message at end of media volumes
--no-preserve-owner don't change files' owners when extracting
-R --owner set files' owners when extracting
-E --pattern-file list of shell filename patterns to process
-s --swap-bytes handle byte-order differences when extracting files
-S --swap-halfwords ditto
-b like -sS
-I input archive filename
-k recognize corrupted archives (we alawys do it, though)
-O output archive filename
Some options of previous versions have been renamed in 2.0:
--binary was replaced by --format=bin
--portability was replaced by --format=odc
Some options have changed meaning in 2.0, for SVR4 compatibility:
-O used to select the binary archive format, now selects the output file
-V used to print the version number, now prints a dot for each file
Version 2.0 also fixes several bugs in the handling of files with
multiple links and of multi-volume archives on floppy disks.

56
gnu/usr.bin/cpio/README Normal file
View File

@ -0,0 +1,56 @@
This is GNU cpio, a program to manage archives of files.
As of version 2.0, it supports the features of the System V release 4
cpio, including support for tar archives.
The main advantages of GNU cpio over Unix versions are:
* It can access tape drives on other hosts using TCP/IP.
* `-o' and `-p' can copy symbolic links either as symbolic links or,
with `-L', as the files they point to.
* `-i' automatically recognizes the archive format and tries to
recover from corrupted archives.
* The output of '-itv' looks like 'ls -l'.
* It accepts long-named options as well as traditional
single-character options.
A few features of other versions of cpio are missing from GNU cpio, including:
* The `-6' option to support Sixth Edition Unix cpio archives with `-i'.
* An option to limit volume size, like afio -s.
GNU cpio supports the POSIX.1 "ustar" tar format. GNU tar supports a
somewhat different, early draft of that format. That draft format has
a slightly different magic number in the tar header and doesn't
include the path prefix part of the header, which allows storing file
names that are longer than 100 characters. GNU cpio knows to
recognize the nonstandard GNU tar "ustar" archives.
The following patch to GNU tar 1.11.1 makes GNU tar recognize standard
"ustar" archives, such as GNU cpio produces, except that it won't use
the path prefix. Without this patch, GNU tar thinks that standard
"ustar" archives are old-format tar archives and can not use the extra
information that "ustar" format contains. If you use this patch,
remember that you will lose the beginnings of paths that are longer
than 100 characters. That's why it's not an official part of GNU tar.
(Adding support for the path prefix to GNU tar is not trivial.)
--- list.c.orig Mon Sep 14 17:04:03 1992
+++ list.c Wed Oct 14 14:02:28 1992
@@ -439,7 +439,7 @@
st->st_ctime = from_oct(1+12, header->header.ctime);
}
- if (0==strcmp(header->header.magic, TMAGIC)) {
+ if (0==strncmp(header->header.magic, TMAGIC, 5)) {
/* Unix Standard tar archive */
*stdp = 1;
if (wantug) {
Mail suggestions and bug reports for GNU cpio to
bug-gnu-utils@prep.ai.mit.edu.

475
gnu/usr.bin/cpio/alloca.c Normal file
View File

@ -0,0 +1,475 @@
/* alloca.c -- allocate automatically reclaimed memory
(Mostly) portable public-domain implementation -- D A Gwyn
This implementation of the PWB library alloca function,
which is used to allocate space off the run-time stack so
that it is automatically reclaimed upon procedure exit,
was inspired by discussions with J. Q. Johnson of Cornell.
J.Otto Tennant <jot@cray.com> contributed the Cray support.
There are some preprocessor constants that can
be defined when compiling for your specific system, for
improved efficiency; however, the defaults should be okay.
The general concept of this implementation is to keep
track of all alloca-allocated blocks, and reclaim any
that are found to be deeper in the stack than the current
invocation. This heuristic does not reclaim storage as
soon as it becomes invalid, but it will do so eventually.
As a special case, alloca(0) reclaims storage without
allocating any. It is a good idea to use alloca(0) in
your main control loop, etc. to force garbage collection. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* If compiling with GCC, this file's not needed. */
#ifndef alloca
#ifdef emacs
#ifdef static
/* actually, only want this if static is defined as ""
-- this is for usg, in which emacs must undefine static
in order to make unexec workable
*/
#ifndef STACK_DIRECTION
you
lose
-- must know STACK_DIRECTION at compile-time
#endif /* STACK_DIRECTION undefined */
#endif /* static */
#endif /* emacs */
/* If your stack is a linked list of frames, you have to
provide an "address metric" ADDRESS_FUNCTION macro. */
#ifdef CRAY
long i00afunc ();
#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
#else
#define ADDRESS_FUNCTION(arg) &(arg)
#endif
#if __STDC__
typedef void *pointer;
#else
typedef char *pointer;
#endif
#define NULL 0
/* Different portions of Emacs need to call different versions of
malloc. The Emacs executable needs alloca to call xmalloc, because
ordinary malloc isn't protected from input signals. On the other
hand, the utilities in lib-src need alloca to call malloc; some of
them are very simple, and don't have an xmalloc routine.
Non-Emacs programs expect this to call use xmalloc.
Callers below should use malloc. */
#ifndef emacs
#define malloc xmalloc
extern pointer xmalloc ();
#endif
/* Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* Direction unknown. */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
#else /* STACK_DIRECTION == 0; need run-time code. */
static int stack_dir; /* 1 or -1 once known. */
#define STACK_DIR stack_dir
static void
find_stack_direction ()
{
static char *addr = NULL; /* Address of first `dummy', once known. */
auto char dummy; /* To get stack address. */
if (addr == NULL)
{ /* Initial entry. */
addr = ADDRESS_FUNCTION (dummy);
find_stack_direction (); /* Recurse once. */
}
else
{
/* Second entry. */
if (ADDRESS_FUNCTION (dummy) > addr)
stack_dir = 1; /* Stack grew upward. */
else
stack_dir = -1; /* Stack grew downward. */
}
}
#endif /* STACK_DIRECTION == 0 */
/* An "alloca header" is used to:
(a) chain together all alloca'ed blocks;
(b) keep track of stack depth.
It is very important that sizeof(header) agree with malloc
alignment chunk size. The following default should work okay. */
#ifndef ALIGN_SIZE
#define ALIGN_SIZE sizeof(double)
#endif
typedef union hdr
{
char align[ALIGN_SIZE]; /* To force sizeof(header). */
struct
{
union hdr *next; /* For chaining headers. */
char *deep; /* For stack depth measure. */
} h;
} header;
static header *last_alloca_header = NULL; /* -> last alloca header. */
/* Return a pointer to at least SIZE bytes of storage,
which will be automatically reclaimed upon exit from
the procedure that called alloca. Originally, this space
was supposed to be taken from the current stack frame of the
caller, but that method cannot be made to work for some
implementations of C, for example under Gould's UTX/32. */
pointer
alloca (size)
unsigned size;
{
auto char probe; /* Probes stack depth: */
register char *depth = ADDRESS_FUNCTION (probe);
#if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* Unknown growth direction. */
find_stack_direction ();
#endif
/* Reclaim garbage, defined as all alloca'd storage that
was allocated from deeper in the stack than currently. */
{
register header *hp; /* Traverses linked list. */
for (hp = last_alloca_header; hp != NULL;)
if ((STACK_DIR > 0 && hp->h.deep > depth)
|| (STACK_DIR < 0 && hp->h.deep < depth))
{
register header *np = hp->h.next;
free ((pointer) hp); /* Collect garbage. */
hp = np; /* -> next header. */
}
else
break; /* Rest are not deeper. */
last_alloca_header = hp; /* -> last valid storage. */
}
if (size == 0)
return NULL; /* No allocation required. */
/* Allocate combined header + user data storage. */
{
register pointer new = malloc (sizeof (header) + size);
/* Address of header. */
((header *) new)->h.next = last_alloca_header;
((header *) new)->h.deep = depth;
last_alloca_header = (header *) new;
/* User storage begins just after header. */
return (pointer) ((char *) new + sizeof (header));
}
}
#ifdef CRAY
#ifdef DEBUG_I00AFUNC
#include <stdio.h>
#endif
#ifndef CRAY_STACK
#define CRAY_STACK
#ifndef CRAY2
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
struct stack_control_header
{
long shgrow:32; /* Number of times stack has grown. */
long shaseg:32; /* Size of increments to stack. */
long shhwm:32; /* High water mark of stack. */
long shsize:32; /* Current size of stack (all segments). */
};
/* The stack segment linkage control information occurs at
the high-address end of a stack segment. (The stack
grows from low addresses to high addresses.) The initial
part of the stack segment linkage control information is
0200 (octal) words. This provides for register storage
for the routine which overflows the stack. */
struct stack_segment_linkage
{
long ss[0200]; /* 0200 overflow words. */
long sssize:32; /* Number of words in this segment. */
long ssbase:32; /* Offset to stack base. */
long:32;
long sspseg:32; /* Offset to linkage control of previous
segment of stack. */
long:32;
long sstcpt:32; /* Pointer to task common address block. */
long sscsnm; /* Private control structure number for
microtasking. */
long ssusr1; /* Reserved for user. */
long ssusr2; /* Reserved for user. */
long sstpid; /* Process ID for pid based multi-tasking. */
long ssgvup; /* Pointer to multitasking thread giveup. */
long sscray[7]; /* Reserved for Cray Research. */
long ssa0;
long ssa1;
long ssa2;
long ssa3;
long ssa4;
long ssa5;
long ssa6;
long ssa7;
long sss0;
long sss1;
long sss2;
long sss3;
long sss4;
long sss5;
long sss6;
long sss7;
};
#else /* CRAY2 */
/* The following structure defines the vector of words
returned by the STKSTAT library routine. */
struct stk_stat
{
long now; /* Current total stack size. */
long maxc; /* Amount of contiguous space which would
be required to satisfy the maximum
stack demand to date. */
long high_water; /* Stack high-water mark. */
long overflows; /* Number of stack overflow ($STKOFEN) calls. */
long hits; /* Number of internal buffer hits. */
long extends; /* Number of block extensions. */
long stko_mallocs; /* Block allocations by $STKOFEN. */
long underflows; /* Number of stack underflow calls ($STKRETN). */
long stko_free; /* Number of deallocations by $STKRETN. */
long stkm_free; /* Number of deallocations by $STKMRET. */
long segments; /* Current number of stack segments. */
long maxs; /* Maximum number of stack segments so far. */
long pad_size; /* Stack pad size. */
long current_address; /* Current stack segment address. */
long current_size; /* Current stack segment size. This
number is actually corrupted by STKSTAT to
include the fifteen word trailer area. */
long initial_address; /* Address of initial segment. */
long initial_size; /* Size of initial segment. */
};
/* The following structure describes the data structure which trails
any stack segment. I think that the description in 'asdef' is
out of date. I only describe the parts that I am sure about. */
struct stk_trailer
{
long this_address; /* Address of this block. */
long this_size; /* Size of this block (does not include
this trailer). */
long unknown2;
long unknown3;
long link; /* Address of trailer block of previous
segment. */
long unknown5;
long unknown6;
long unknown7;
long unknown8;
long unknown9;
long unknown10;
long unknown11;
long unknown12;
long unknown13;
long unknown14;
};
#endif /* CRAY2 */
#endif /* not CRAY_STACK */
#ifdef CRAY2
/* Determine a "stack measure" for an arbitrary ADDRESS.
I doubt that "lint" will like this much. */
static long
i00afunc (long *address)
{
struct stk_stat status;
struct stk_trailer *trailer;
long *block, size;
long result = 0;
/* We want to iterate through all of the segments. The first
step is to get the stack status structure. We could do this
more quickly and more directly, perhaps, by referencing the
$LM00 common block, but I know that this works. */
STKSTAT (&status);
/* Set up the iteration. */
trailer = (struct stk_trailer *) (status.current_address
+ status.current_size
- 15);
/* There must be at least one stack segment. Therefore it is
a fatal error if "trailer" is null. */
if (trailer == 0)
abort ();
/* Discard segments that do not contain our argument address. */
while (trailer != 0)
{
block = (long *) trailer->this_address;
size = trailer->this_size;
if (block == 0 || size == 0)
abort ();
trailer = (struct stk_trailer *) trailer->link;
if ((block <= address) && (address < (block + size)))
break;
}
/* Set the result to the offset in this segment and add the sizes
of all predecessor segments. */
result = address - block;
if (trailer == 0)
{
return result;
}
do
{
if (trailer->this_size <= 0)
abort ();
result += trailer->this_size;
trailer = (struct stk_trailer *) trailer->link;
}
while (trailer != 0);
/* We are done. Note that if you present a bogus address (one
not in any segment), you will get a different number back, formed
from subtracting the address of the first block. This is probably
not what you want. */
return (result);
}
#else /* not CRAY2 */
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
Determine the number of the cell within the stack,
given the address of the cell. The purpose of this
routine is to linearize, in some sense, stack addresses
for alloca. */
static long
i00afunc (long address)
{
long stkl = 0;
long size, pseg, this_segment, stack;
long result = 0;
struct stack_segment_linkage *ssptr;
/* Register B67 contains the address of the end of the
current stack segment. If you (as a subprogram) store
your registers on the stack and find that you are past
the contents of B67, you have overflowed the segment.
B67 also points to the stack segment linkage control
area, which is what we are really interested in. */
stkl = CRAY_STACKSEG_END ();
ssptr = (struct stack_segment_linkage *) stkl;
/* If one subtracts 'size' from the end of the segment,
one has the address of the first word of the segment.
If this is not the first segment, 'pseg' will be
nonzero. */
pseg = ssptr->sspseg;
size = ssptr->sssize;
this_segment = stkl - size;
/* It is possible that calling this routine itself caused
a stack overflow. Discard stack segments which do not
contain the target address. */
while (!(this_segment <= address && address <= stkl))
{
#ifdef DEBUG_I00AFUNC
fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
#endif
if (pseg == 0)
break;
stkl = stkl - pseg;
ssptr = (struct stack_segment_linkage *) stkl;
size = ssptr->sssize;
pseg = ssptr->sspseg;
this_segment = stkl - size;
}
result = address - this_segment;
/* If you subtract pseg from the current end of the stack,
you get the address of the previous stack segment's end.
This seems a little convoluted to me, but I'll bet you save
a cycle somewhere. */
while (pseg != 0)
{
#ifdef DEBUG_I00AFUNC
fprintf (stderr, "%011o %011o\n", pseg, size);
#endif
stkl = stkl - pseg;
ssptr = (struct stack_segment_linkage *) stkl;
size = ssptr->sssize;
pseg = ssptr->sspseg;
result += size;
}
return (result);
}
#endif /* not CRAY2 */
#endif /* CRAY */
#endif /* no alloca */

1272
gnu/usr.bin/cpio/copyin.c Normal file

File diff suppressed because it is too large Load Diff

801
gnu/usr.bin/cpio/copyout.c Normal file
View File

@ -0,0 +1,801 @@
/* 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 clear_rest_of_block ();
static void 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);
copy_buf_out (ascii_header, out_des, 110L);
/* Write file name to output. */
copy_buf_out (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
pad_output (out_des, file_hdr->c_namesize + 110);
}
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,
"%06lo%06lo%06lo%06lo%06lo%06lo%06lo%06lo%011lo%06lo%011lo",
file_hdr->c_magic & 0xFFFF, dev & 0xFFFF,
file_hdr->c_ino & 0xFFFF, file_hdr->c_mode & 0xFFFF,
file_hdr->c_uid & 0xFFFF, file_hdr->c_gid & 0xFFFF,
file_hdr->c_nlink & 0xFFFF, rdev & 0xFFFF,
file_hdr->c_mtime, file_hdr->c_namesize & 0xFFFF,
file_hdr->c_filesize);
copy_buf_out (ascii_header, out_des, 76L);
/* Write file name to output. */
copy_buf_out (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. */
copy_buf_out ((char *) &short_hdr, out_des, 26L);
/* Write file name to output. */
copy_buf_out (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
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 (in_file_des, out_file_des, file_hdr.c_filesize);
#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
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);
if (readlink (input_name.ds_string, link_name,
file_stat.st_size) < 0)
{
error (0, errno, "%s", input_name.ds_string);
free (link_name);
continue;
}
if (archive_format == arf_tar || archive_format == arf_ustar)
{
if (file_stat.st_size + 1 > 100)
{
error (0, 0, "%s: symbolic link too long",
file_hdr.c_name);
}
else
{
link_name[file_stat.st_size] = '\0';
file_hdr.c_tar_linkname = link_name;
write_out_header (&file_hdr, out_file_des);
}
}
else
{
write_out_header (&file_hdr, out_file_des);
copy_buf_out (link_name, out_file_des, file_stat.st_size);
pad_output (out_file_des, file_hdr.c_filesize);
}
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
{
copy_buf_out (zeros_512, out_file_des, 512);
copy_buf_out (zeros_512, out_file_des, 512);
}
/* Fill up the output block. */
clear_rest_of_block (out_file_des);
empty_output_buffer (out_file_des);
if (dot_flag)
fputc ('\n', stderr);
res = (output_bytes + io_block_size - 1) / io_block_size;
if (res == 1)
fprintf (stderr, "1 block\n");
else
fprintf (stderr, "%d blocks\n", res);
}
/* 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
clear_rest_of_block (out_file_des)
int out_file_des;
{
while (output_size < io_block_size)
{
if ((io_block_size - output_size) > 512)
copy_buf_out (zeros_512, out_file_des, 512);
else
copy_buf_out (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
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)
copy_buf_out (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;
int count;
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 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 (in_file_des, out_file_des, file_hdr.c_filesize);
#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
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;
}

449
gnu/usr.bin/cpio/copypass.c Normal file
View File

@ -0,0 +1,449 @@
/* 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 (in_file_des, out_file_des, in_file_stat.st_size);
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)
{
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;
link_name = (char *) xmalloc ((unsigned int) in_file_stat.st_size + 1);
if (readlink (input_name.ds_string, link_name,
in_file_stat.st_size) < 0)
{
error (0, errno, "%s", input_name.ds_string);
free (link_name);
continue;
}
link_name[in_file_stat.st_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);
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;
}

310
gnu/usr.bin/cpio/cpio.1 Normal file
View File

@ -0,0 +1,310 @@
.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]
[\-\-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]
[\-\-help] [\-\-version] [pattern...] [< archive]
.B 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]] [\-\-no-preserve-owner]
[\-\-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
pathname, 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-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 "\-p, \-\-pass-through"
Run in copy-pass mode.
.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 "\-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.

69
gnu/usr.bin/cpio/cpio.h Normal file
View File

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

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

43
gnu/usr.bin/cpio/defer.c Normal file
View File

@ -0,0 +1,43 @@
/* 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);
}

8
gnu/usr.bin/cpio/defer.h Normal file
View File

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

@ -0,0 +1,66 @@
/* 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 STDC_HEADERS
#include <stdlib.h>
#else
char *malloc ();
#endif
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#ifndef rindex
#define rindex strrchr
#endif
#else
#include <strings.h>
#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 = rindex (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 = malloc (length + 1);
if (newpath == 0)
return 0;
strncpy (newpath, path, length);
newpath[length] = 0;
return newpath;
}

114
gnu/usr.bin/cpio/dstring.c Normal file
View File

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

@ -0,0 +1,49 @@
/* 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 ();

106
gnu/usr.bin/cpio/error.c Normal file
View File

@ -0,0 +1,106 @@
/* error.c -- error handler for noninteractive utilities
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 David MacKenzie. */
#include <stdio.h>
#ifdef HAVE_VPRINTF
#if __STDC__
#include <stdarg.h>
#define VA_START(args, lastarg) va_start(args, lastarg)
#else /* !__STDC__ */
#include <varargs.h>
#define VA_START(args, lastarg) va_start(args)
#endif /* !__STDC__ */
#else /* !HAVE_VPRINTF */
#ifdef HAVE_DOPRNT
#define va_alist args
#define va_dcl int args;
#else /* !HAVE_DOPRNT */
#define va_alist a1, a2, a3, a4, a5, a6, a7, a8
#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
#endif /* !HAVE_DOPRNT */
#endif /* !HAVE_VPRINTF */
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#else /* !STDC_HEADERS */
void exit ();
#endif /* !STDC_HEADERS */
extern char *program_name;
#ifndef HAVE_STRERROR
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 /* !HAVE_STRERROR */
/* Print the program name and error message MESSAGE, which is a printf-style
format string with optional args.
If ERRNUM is nonzero, print its corresponding system error message.
Exit with status STATUS if it is nonzero. */
/* VARARGS */
void
#if defined (HAVE_VPRINTF) && __STDC__
error (int status, int errnum, char *message, ...)
#else /* !HAVE_VPRINTF or !__STDC__ */
error (status, errnum, message, va_alist)
int status;
int errnum;
char *message;
va_dcl
#endif /* !HAVE_VPRINTF or !__STDC__ */
{
#ifdef HAVE_VPRINTF
va_list args;
#endif /* HAVE_VPRINTF */
fprintf (stderr, "%s: ", program_name);
#ifdef HAVE_VPRINTF
VA_START (args, message);
vfprintf (stderr, message, args);
va_end (args);
#else /* !HAVE_VPRINTF */
#ifdef HAVE_DOPRNT
_doprnt (message, &args, stderr);
#else /* !HAVE_DOPRNT */
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
#endif /* !HAVE_DOPRNT */
#endif /* !HAVE_VPRINTF */
if (errnum)
fprintf (stderr, ": %s", strerror (errnum));
putc ('\n', stderr);
fflush (stderr);
if (status)
exit (status);
}

176
gnu/usr.bin/cpio/extern.h Normal file
View File

@ -0,0 +1,176 @@
/* 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 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 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_size, output_size;
extern long input_bytes, output_bytes;
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));
/* 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 empty_output_buffer P_((int out_des));
void swahw_array P_((char *ptr, int count));
void fill_input_buffer P_((int in_des, int num_bytes));
void copy_buf_out P_((char *in_buf, int out_des, long num_bytes));
void copy_in_buf P_((char *in_buf, int in_des, long num_bytes));
int peek_in_buf P_((char *peek_buf, int in_des, int num_bytes));
void toss_input P_((int in_des, long num_bytes));
void copy_files P_((int in_des, int out_des, long num_bytes));
void 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));
#ifdef __MSDOS__
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));

229
gnu/usr.bin/cpio/filemode.c Normal file
View File

@ -0,0 +1,229 @@
/* filemode.c -- make a string describing file modes
Copyright (C) 1985, 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 <sys/types.h>
#include <sys/stat.h>
#ifndef S_IREAD
#define S_IREAD S_IRUSR
#define S_IWRITE S_IWUSR
#define S_IEXEC S_IXUSR
#endif
#if !defined(S_ISREG) || defined(NO_MODE_T)
/* Doesn't have POSIX.1 stat stuff or doesn't have mode_t. */
#define mode_t unsigned short
#endif
#if !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 (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)
mode_t 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_IREAD) ? 'r' : '-';
chars[1] = (bits & S_IWRITE) ? 'w' : '-';
chars[2] = (bits & S_IEXEC) ? '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

@ -0,0 +1,84 @@
/* 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 ();

200
gnu/usr.bin/cpio/fnmatch.c Normal file
View File

@ -0,0 +1,200 @@
/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
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; see the file COPYING.LIB. 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 <errno.h>
#include <fnmatch.h>
#include <ctype.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__)
#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
extern int errno;
#endif
/* Match STRING against the filename pattern PATTERN, returning zero if
it matches, nonzero if not. */
int
fnmatch (pattern, string, flags)
const char *pattern;
const char *string;
int flags;
{
register const char *p = pattern, *n = string;
register char c;
/* Note that this evalutes C many times. */
#define FOLD(c) ((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c))
while ((c = *p++) != '\0')
{
c = FOLD (c);
switch (c)
{
case '?':
if (*n == '\0')
return FNM_NOMATCH;
else if ((flags & FNM_FILE_NAME) && *n == '/')
return FNM_NOMATCH;
else if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
return FNM_NOMATCH;
break;
case '\\':
if (!(flags & FNM_NOESCAPE))
{
c = *p++;
c = FOLD (c);
}
if (FOLD (*n) != c)
return FNM_NOMATCH;
break;
case '*':
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
return FNM_NOMATCH;
for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
if (((flags & FNM_FILE_NAME) && *n == '/') ||
(c == '?' && *n == '\0'))
return FNM_NOMATCH;
if (c == '\0')
return 0;
{
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
c1 = FOLD (c1);
for (--p; *n != '\0'; ++n)
if ((c == '[' || FOLD (*n) == c1) &&
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
return 0;
return FNM_NOMATCH;
}
case '[':
{
/* Nonzero if the sense of the character class is inverted. */
register int not;
if (*n == '\0')
return FNM_NOMATCH;
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
return FNM_NOMATCH;
not = (*p == '!' || *p == '^');
if (not)
++p;
c = *p++;
for (;;)
{
register char cstart = c, cend = c;
if (!(flags & FNM_NOESCAPE) && c == '\\')
cstart = cend = *p++;
cstart = cend = FOLD (cstart);
if (c == '\0')
/* [ (unterminated) loses. */
return FNM_NOMATCH;
c = *p++;
c = FOLD (c);
if ((flags & FNM_FILE_NAME) && c == '/')
/* [/] can never match. */
return FNM_NOMATCH;
if (c == '-' && *p != ']')
{
cend = *p++;
if (!(flags & FNM_NOESCAPE) && cend == '\\')
cend = *p++;
if (cend == '\0')
return FNM_NOMATCH;
cend = FOLD (cend);
c = *p++;
}
if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
goto matched;
if (c == ']')
break;
}
if (!not)
return FNM_NOMATCH;
break;
matched:;
/* Skip the rest of the [...] that already matched. */
while (c != ']')
{
if (c == '\0')
/* [... (unterminated) loses. */
return FNM_NOMATCH;
c = *p++;
if (!(flags & FNM_NOESCAPE) && c == '\\')
/* XXX 1003.2d11 is unclear if this is right. */
++p;
}
if (not)
return FNM_NOMATCH;
}
break;
default:
if (c != FOLD (*n))
return FNM_NOMATCH;
}
++n;
}
if (*n == '\0')
return 0;
if ((flags & FNM_LEADING_DIR) && *n == '/')
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
return 0;
return FNM_NOMATCH;
}
#endif /* _LIBC or not __GNU_LIBRARY__. */

View File

@ -0,0 +1,60 @@
/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
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; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#ifndef _FNMATCH_H
#define _FNMATCH_H 1
#ifdef __cplusplus
extern "C" {
#endif
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
#undef __P
#define __P(args) args
#else /* Not C++ or ANSI C. */
#undef __P
#define __P(args) ()
/* We can get away without defining `const' here only because in this file
it is used only inside the prototype for `fnmatch', which is elided in
non-ANSI C where `const' is problematical. */
#endif /* C++ or ANSI C. */
/* Bits set in the FLAGS argument to `fnmatch'. */
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE)
#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
#endif
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
#define FNM_NOMATCH 1
/* Match STRING against the filename pattern PATTERN,
returning zero if it matches, FNM_NOMATCH if not. */
extern int fnmatch __P ((const char *__pattern, const char *__string,
int __flags));
#ifdef __cplusplus
}
#endif
#endif /* fnmatch.h */

744
gnu/usr.bin/cpio/getopt.c Normal file
View File

@ -0,0 +1,744 @@
/* 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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if !__STDC__ && !defined(const) && IN_GCC
#define const
#endif
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
#ifndef _NO_PROTO
#define _NO_PROTO
#endif
#include <stdio.h>
/* 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. */
/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
long-named option. Because this is not POSIX.2 compliant, it is
being phased out. */
/* #define GETOPT_COMPAT */
/* 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 = 0;
/* 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;
#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__
#ifdef IN_GCC
#include "gstddef.h"
#else
#include <stddef.h>
#endif
extern size_t strlen (const char *);
#endif
#endif /* GNU C 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;
}
/* 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;
{
int option_index;
optarg = 0;
/* Initialize the internal data when the first call is made.
Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
if (optind == 0)
{
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (getenv ("POSIXLY_CORRECT") != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
}
if (nextchar == NULL || *nextchar == '\0')
{
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;
/* Now skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
optind++;
last_nonopt = optind;
}
/* 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')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Start decoding its characters. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
if (longopts != NULL
&& ((argv[optind][0] == '-'
&& (argv[optind][1] == '-' || long_only))
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
))
{
const struct option *p;
char *s = nextchar;
int exact = 0;
int ambig = 0;
const struct option *pfound = NULL;
int indfound;
while (*s && *s != '=')
s++;
/* Test all options for either exact match or abbreviated matches. */
for (p = longopts, option_index = 0; p->name;
p++, option_index++)
if (!strncmp (p->name, nextchar, s - nextchar))
{
if (s - 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 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 (*s)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = s + 1;
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] == '-'
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, "%s: unrecognized option `--%s'\n",
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 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 0
if (c < 040 || c >= 0177)
fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
argv[0], c);
else
fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
#else
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
#endif
}
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 = 0;
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)
{
#if 0
fprintf (stderr, "%s: option `-%c' requires an argument\n",
argv[0], c);
#else
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: option requires an argument -- %c\n",
argv[0], c);
#endif
}
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 */

129
gnu/usr.bin/cpio/getopt.h Normal file
View File

@ -0,0 +1,129 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992, 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, 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 __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 __STDC__
#if defined(__GNU_LIBRARY__)
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* not __GNU_LIBRARY__ */
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 /* not __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

176
gnu/usr.bin/cpio/getopt1.c Normal file
View File

@ -0,0 +1,176 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987, 88, 89, 90, 91, 92, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "getopt.h"
#if !__STDC__ && !defined(const) && IN_GCC
#define const
#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 */

168
gnu/usr.bin/cpio/global.c Normal file
View File

@ -0,0 +1,168 @@
/* 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 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;
#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;
/* 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. */
long input_bytes, output_bytes;
/* 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;

206
gnu/usr.bin/cpio/idcache.c Normal file
View File

@ -0,0 +1,206 @@
/* 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. */
#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;
}

479
gnu/usr.bin/cpio/main.c Normal file
View File

@ -0,0 +1,479 @@
/* 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-preserve-owner", 0, 0, 134},
{"nonmatching", 0, &copy_matching_files, FALSE},
{"numeric-uid-gid", 0, &numeric_uid, TRUE},
{"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},
{"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]\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] [--help] [--version] [pattern...] [< archive]\n",
program_name);
fprintf (fp, "\
%s {-p|--pass-through} [-0adlmuvLV] [-R [user][:.][group]]\n\
[--null] [--reset-access-time] [--make-directories] [--link]\n\
[--preserve-modification-time] [--unconditional] [--verbose] [--dot]\n\
[--dereference] [--owner=[user][:.][group]] [--no-preserve-owner]\n\
[--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 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 '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 '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 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
|| 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))
|| 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)
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 buf_size;
/* Make sure buffers can always hold 2 blocks and that they
are big enough to hold 1 tar record (512 bytes) even if it
is not aligned on a block boundary. The extra buffer space
is needed by process_copyin and peek_in_buf to automatically
figure out what kind of archive it is reading. */
if (io_block_size >= 512)
buf_size = 2 * io_block_size;
else
buf_size = 1024;
input_buffer = (char *) xmalloc (buf_size);
in_buff = input_buffer;
input_size = 0;
input_bytes = 0;
/* Leave space for an `int' sentinel for `empty_output_buffer',
in case we ever put back sparseness checking. */
output_buffer = (char *) xmalloc (buf_size + sizeof (int) * 2);
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);
}

297
gnu/usr.bin/cpio/makepath.c Normal file
View File

@ -0,0 +1,297 @@
/* 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
#ifdef STDC_HEADERS
#include <errno.h>
#include <stdlib.h>
#else
extern int errno;
#endif
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#define index strchr
#else
#include <strings.h>
#endif
#ifdef __MSDOS__
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))
{
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;
}

107
gnu/usr.bin/cpio/mt.1 Normal file
View File

@ -0,0 +1,107 @@
.TH MT 1L \" -*- nroff -*-
.SH NAME
mt \- control magnetic tape drive operation
.SH SYNOPSIS
.B mt
[\-V] [\-f device] [\-\-file=device] [\-\-version]
operation [count]
.SH DESCRIPTION
This manual page
documents the GNU version of
.BR mt .
.B mt
performs the given
.IR operation ,
which must be one of the tape operations listed below, on a tape
drive.
.PP
The default tape device to operate on is taken from the file
.I /usr/include/sys/mtio.h
when
.B mt
is compiled. It can be overridden by giving a device file name in
the environment variable
.BR TAPE
or by a command line option (see below), which also overrides the
environment variable.
.PP
The device must be either a character special file or a
remote tape drive. 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).
.PP
The available operations are listed below. Unique abbreviations are
accepted. Not all operations are available on all systems, or work on
all types of tape drives.
Some operations optionally take a repeat count, which can be given
after the operation name and defaults to 1.
.IP "eof, weof"
Write
.I count
EOF marks at current position.
.IP fsf
Forward space
.I count
files.
The tape is positioned on the first block of the next file.
.IP bsf
Backward space
.I count
files.
The tape is positioned on the first block of the next file.
.IP fsr
Forward space
.I count
records.
.IP bsr
Backward space
.I count
records.
.IP bsfm
Backward space
.I count
file marks.
The tape is positioned on the beginning-of-the-tape side of
the file mark.
.IP asf
Absolute space to file number
.IR count .
Equivalent to rewind followed by fsf
.IR count .
.IP eom
Space to the end of the recorded media on the tape
(for appending files onto tapes).
.IP rewind
Rewind the tape.
.IP "offline, rewoffl"
Rewind the tape and, if applicable, unload the tape.
.IP status
Print status information about the tape unit.
.IP retension
Rewind the tape, then wind it to the end of the reel,
then rewind it again.
.IP erase
Erase the tape.
.PP
.B mt
exits with a status of 0 if the operation succeeded, 1 if the
operation or device name given was invalid, or 2 if the operation
failed.
.SS OPTIONS
.TP
.I "\-f, \-\-file=device"
Use
.I device
as the file name of the tape drive to operate on.
To use a
tape drive on another machine, 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 "\-V, \-\-version"
Print the version number of
.BR mt .

281
gnu/usr.bin/cpio/rmt.c Normal file
View File

@ -0,0 +1,281 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1983 Regents of the University of California.\n\
All rights reserved.\n";
#endif /* not lint */
/*
* rmt
*/
#include <stdio.h>
#include <sgtty.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_GENTAPE_H /* e.g., ISC UNIX */
#include <sys/gentape.h>
#else
#include <sys/mtio.h>
#endif
#include <errno.h>
#if defined (_I386) && defined (_AIX)
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#else
long lseek ();
#endif
#ifdef STDC_HEADERS
#include <string.h>
#include <stdlib.h>
#else
extern char *malloc ();
#endif
int tape = -1;
char *record;
int maxrecsize = -1;
char *checkbuf ();
void getstring ();
void error ();
#define SSIZE 64
char device[SSIZE];
char count[SSIZE], mode[SSIZE], pos[SSIZE], op[SSIZE];
extern errno;
extern char *sys_errlist[];
char resp[BUFSIZ];
FILE *debug;
#define DEBUG(f) if (debug) fprintf(debug, f)
#define DEBUG1(f,a) if (debug) fprintf(debug, f, a)
#define DEBUG2(f,a1,a2) if (debug) fprintf(debug, f, a1, a2)
int
main (argc, argv)
int argc;
char **argv;
{
int rval;
char c;
int n, i, cc;
argc--, argv++;
if (argc > 0)
{
debug = fopen (*argv, "w");
if (debug == 0)
exit (1);
(void) setbuf (debug, (char *) 0);
}
top:
errno = 0;
rval = 0;
if (read (0, &c, 1) != 1)
exit (0);
switch (c)
{
case 'O':
if (tape >= 0)
(void) close (tape);
getstring (device);
getstring (mode);
DEBUG2 ("rmtd: O %s %s\n", device, mode);
#if defined (i386) && defined (AIX)
/* This is alleged to fix a byte ordering problem. */
/* I'm quite suspicious if it's right. -- mib */
{
int oflag = atoi (mode);
int nflag = 0;
if ((oflag & 3) == 0)
nflag |= O_RDONLY;
if (oflag & 1)
nflag |= O_WRONLY;
if (oflag & 2)
nflag |= O_RDWR;
if (oflag & 0x0008)
nflag |= O_APPEND;
if (oflag & 0x0200)
nflag |= O_CREAT;
if (oflag & 0x0400)
nflag |= O_TRUNC;
if (oflag & 0x0800)
nflag |= O_EXCL;
tape = open (device, nflag, 0666);
}
#else
tape = open (device, atoi (mode), 0666);
#endif
if (tape < 0)
goto ioerror;
goto respond;
case 'C':
DEBUG ("rmtd: C\n");
getstring (device); /* discard */
if (close (tape) < 0)
goto ioerror;
tape = -1;
goto respond;
case 'L':
getstring (count);
getstring (pos);
DEBUG2 ("rmtd: L %s %s\n", count, pos);
rval = lseek (tape, (long) atoi (count), atoi (pos));
if (rval < 0)
goto ioerror;
goto respond;
case 'W':
getstring (count);
n = atoi (count);
DEBUG1 ("rmtd: W %s\n", count);
record = checkbuf (record, n);
for (i = 0; i < n; i += cc)
{
cc = read (0, &record[i], n - i);
if (cc <= 0)
{
DEBUG ("rmtd: premature eof\n");
exit (2);
}
}
rval = write (tape, record, n);
if (rval < 0)
goto ioerror;
goto respond;
case 'R':
getstring (count);
DEBUG1 ("rmtd: R %s\n", count);
n = atoi (count);
record = checkbuf (record, n);
rval = read (tape, record, n);
if (rval < 0)
goto ioerror;
(void) sprintf (resp, "A%d\n", rval);
(void) write (1, resp, strlen (resp));
(void) write (1, record, rval);
goto top;
case 'I':
getstring (op);
getstring (count);
DEBUG2 ("rmtd: I %s %s\n", op, count);
#ifdef MTIOCTOP
{
struct mtop mtop;
mtop.mt_op = atoi (op);
mtop.mt_count = atoi (count);
if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0)
goto ioerror;
rval = mtop.mt_count;
}
#endif
goto respond;
case 'S': /* status */
DEBUG ("rmtd: S\n");
{
#ifdef MTIOCGET
struct mtget mtget;
if (ioctl (tape, MTIOCGET, (char *) &mtget) < 0)
goto ioerror;
rval = sizeof (mtget);
(void) sprintf (resp, "A%d\n", rval);
(void) write (1, resp, strlen (resp));
(void) write (1, (char *) &mtget, sizeof (mtget));
#endif
goto top;
}
default:
DEBUG1 ("rmtd: garbage command %c\n", c);
exit (3);
}
respond:
DEBUG1 ("rmtd: A %d\n", rval);
(void) sprintf (resp, "A%d\n", rval);
(void) write (1, resp, strlen (resp));
goto top;
ioerror:
error (errno);
goto top;
}
void
getstring (bp)
char *bp;
{
int i;
char *cp = bp;
for (i = 0; i < SSIZE; i++)
{
if (read (0, cp + i, 1) != 1)
exit (0);
if (cp[i] == '\n')
break;
}
cp[i] = '\0';
}
char *
checkbuf (record, size)
char *record;
int size;
{
if (size <= maxrecsize)
return (record);
if (record != 0)
free (record);
record = malloc (size);
if (record == 0)
{
DEBUG ("rmtd: cannot allocate buffer space\n");
exit (4);
}
maxrecsize = size;
#ifdef SO_RCVBUF
while (size > 1024 &&
setsockopt (0, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof (size)) < 0)
size -= 1024;
#else
size = 1 + ((size - 1) % 1024);
#endif
return (record);
}
void
error (num)
int num;
{
DEBUG2 ("rmtd: E %d (%s)\n", num, sys_errlist[num]);
(void) sprintf (resp, "E%d\n%s\n", num, sys_errlist[num]);
(void) write (1, resp, strlen (resp));
}

98
gnu/usr.bin/cpio/rmt.h Normal file
View File

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

582
gnu/usr.bin/cpio/rtapelib.c Normal file
View File

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

@ -0,0 +1,39 @@
/* 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. */
#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';
}

139
gnu/usr.bin/cpio/system.h Normal file
View File

@ -0,0 +1,139 @@
/* 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
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
#ifdef __MSDOS__
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 */

522
gnu/usr.bin/cpio/tar.c Normal file
View File

@ -0,0 +1,522 @@
/* 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);
copy_buf_out ((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
copy_in_buf ((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! */
copy_in_buf ((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);
copy_in_buf (((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;
}

112
gnu/usr.bin/cpio/tar.h Normal file
View File

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

62
gnu/usr.bin/cpio/tarhdr.h Normal file
View File

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

240
gnu/usr.bin/cpio/tcexparg.c Normal file
View File

@ -0,0 +1,240 @@
/* 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;
}

180
gnu/usr.bin/cpio/userspec.c Normal file
View File

@ -0,0 +1,180 @@
/* 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>. */
#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>
#else
char *malloc ();
#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
#define isdigit(c) ((c) >= '0' && (c) <= '9')
char *strdup ();
static int isnumber ();
/* 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.
Might write NULs into NAME.
Return NULL if successful, a static error message string if not. */
char *
parse_user_spec (name, uid, gid, username, groupname)
char *name;
uid_t *uid;
gid_t *gid;
char **username, **groupname;
{
static char *tired = "virtual memory exhausted";
struct passwd *pwd;
struct group *grp;
char *cp;
int use_login_group = 0;
*username = *groupname = NULL;
/* Check whether a group is given. */
cp = index (name, ':');
if (cp == NULL)
cp = index (name, '.');
if (cp != NULL)
{
*cp++ = '\0';
if (*cp == '\0')
{
if (cp == name + 1)
/* Neither user nor group given, just "." or ":". */
return "can not omit both user and group";
else
/* "user.". */
use_login_group = 1;
}
else
{
/* Explicit group. */
*groupname = strdup (cp);
if (*groupname == NULL)
return tired;
grp = getgrnam (cp);
if (grp == NULL)
{
if (!isnumber (cp))
return "invalid group";
*gid = atoi (cp);
}
else
*gid = grp->gr_gid;
endgrent (); /* Save a file descriptor. */
}
}
/* Parse the user name, now that any group has been removed. */
if (name[0] == '\0')
/* No user name was given, just a group. */
return NULL;
*username = strdup (name);
if (*username == NULL)
return tired;
pwd = getpwnam (name);
if (pwd == NULL)
{
if (!isnumber (name))
return "invalid user";
if (use_login_group)
return "cannot get the login group of a numeric UID";
*uid = atoi (name);
}
else
{
*uid = pwd->pw_uid;
if (use_login_group)
{
*gid = pwd->pw_gid;
grp = getgrgid (pwd->pw_gid);
if (grp == NULL)
{
*groupname = malloc (15);
if (*groupname == NULL)
return tired;
sprintf (*groupname, "%u", pwd->pw_gid);
}
else
{
*groupname = strdup (grp->gr_name);
if (*groupname == NULL)
return tired;
}
endgrent ();
}
}
endpwent ();
return NULL;
}
/* Return nonzero if STR represents an unsigned decimal integer,
otherwise return 0. */
static int
isnumber (str)
char *str;
{
for (; *str; str++)
if (!isdigit (*str))
return 0;
return 1;
}

1102
gnu/usr.bin/cpio/util.c Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -0,0 +1,65 @@
/* xmalloc.c -- malloc with out of memory checking
Copyright (C) 1990, 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. */
#ifdef STDC_HEADERS
#include <stdlib.h>
#else
char *malloc ();
char *realloc ();
void free ();
#endif
void error ();
/* Allocate N bytes of memory dynamically, with error checking. */
char *
xmalloc (n)
unsigned n;
{
char *p;
p = malloc (n);
if (p == 0)
/* Must exit with 2 for `cmp'. */
error (2, 0, "virtual memory exhausted");
return p;
}
/* Change the size of an allocated block of memory P to N bytes,
with error checking.
If P is NULL, run xmalloc.
If N is 0, run free and return NULL. */
char *
xrealloc (p, n)
char *p;
unsigned n;
{
if (p == 0)
return xmalloc (n);
if (n == 0)
{
free (p);
return 0;
}
p = realloc (p, n);
if (p == 0)
/* Must exit with 2 for `cmp'. */
error (2, 0, "virtual memory exhausted");
return p;
}

View File

@ -0,0 +1,32 @@
/* 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. */
#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);
}