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:
parent
db8789d38e
commit
8843e04abc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=253
339
gnu/usr.bin/cpio/COPYING
Normal file
339
gnu/usr.bin/cpio/COPYING
Normal 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.
|
481
gnu/usr.bin/cpio/COPYING.LIB
Normal file
481
gnu/usr.bin/cpio/COPYING.LIB
Normal 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
781
gnu/usr.bin/cpio/ChangeLog
Normal 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:
|
9
gnu/usr.bin/cpio/Makefile
Normal file
9
gnu/usr.bin/cpio/Makefile
Normal 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
55
gnu/usr.bin/cpio/NEWS
Normal 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
56
gnu/usr.bin/cpio/README
Normal 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
475
gnu/usr.bin/cpio/alloca.c
Normal 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
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
801
gnu/usr.bin/cpio/copyout.c
Normal 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 (×, 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, ×) < 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 (×, 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, ×) < 0)
|
||||||
|
error (0, errno, "%s", file_hdr.c_name);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
449
gnu/usr.bin/cpio/copypass.c
Normal file
449
gnu/usr.bin/cpio/copypass.c
Normal 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 (×, 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, ×) < 0)
|
||||||
|
error (0, errno, "%s", input_name.ds_string);
|
||||||
|
if (utime (output_name.ds_string, ×) < 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, ×) < 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, ×) < 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, ×) < 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
310
gnu/usr.bin/cpio/cpio.1
Normal 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
69
gnu/usr.bin/cpio/cpio.h
Normal 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 */
|
90
gnu/usr.bin/cpio/cpiohdr.h
Normal file
90
gnu/usr.bin/cpio/cpiohdr.h
Normal 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
43
gnu/usr.bin/cpio/defer.c
Normal 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
8
gnu/usr.bin/cpio/defer.h
Normal 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));
|
66
gnu/usr.bin/cpio/dirname.c
Normal file
66
gnu/usr.bin/cpio/dirname.c
Normal 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
114
gnu/usr.bin/cpio/dstring.c
Normal 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');
|
||||||
|
}
|
49
gnu/usr.bin/cpio/dstring.h
Normal file
49
gnu/usr.bin/cpio/dstring.h
Normal 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
106
gnu/usr.bin/cpio/error.c
Normal 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
176
gnu/usr.bin/cpio/extern.h
Normal 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
229
gnu/usr.bin/cpio/filemode.c
Normal 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
|
||||||
|
}
|
84
gnu/usr.bin/cpio/filetypes.h
Normal file
84
gnu/usr.bin/cpio/filetypes.h
Normal 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
200
gnu/usr.bin/cpio/fnmatch.c
Normal 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__. */
|
60
gnu/usr.bin/cpio/fnmatch.h
Normal file
60
gnu/usr.bin/cpio/fnmatch.h
Normal 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
744
gnu/usr.bin/cpio/getopt.c
Normal 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
129
gnu/usr.bin/cpio/getopt.h
Normal 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
176
gnu/usr.bin/cpio/getopt1.c
Normal 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
168
gnu/usr.bin/cpio/global.c
Normal 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
206
gnu/usr.bin/cpio/idcache.c
Normal 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
479
gnu/usr.bin/cpio/main.c
Normal 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, ©_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
297
gnu/usr.bin/cpio/makepath.c
Normal 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
107
gnu/usr.bin/cpio/mt.1
Normal 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
281
gnu/usr.bin/cpio/rmt.c
Normal 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
98
gnu/usr.bin/cpio/rmt.h
Normal 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
582
gnu/usr.bin/cpio/rtapelib.c
Normal 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
|
39
gnu/usr.bin/cpio/stripslash.c
Normal file
39
gnu/usr.bin/cpio/stripslash.c
Normal 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
139
gnu/usr.bin/cpio/system.h
Normal 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
522
gnu/usr.bin/cpio/tar.c
Normal 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
112
gnu/usr.bin/cpio/tar.h
Normal 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
62
gnu/usr.bin/cpio/tarhdr.h
Normal 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
240
gnu/usr.bin/cpio/tcexparg.c
Normal 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
180
gnu/usr.bin/cpio/userspec.c
Normal 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
1102
gnu/usr.bin/cpio/util.c
Normal file
File diff suppressed because it is too large
Load Diff
2
gnu/usr.bin/cpio/version.c
Normal file
2
gnu/usr.bin/cpio/version.c
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/* The version number of cpio and mt. */
|
||||||
|
char *version_string = "version 2.3\n";
|
65
gnu/usr.bin/cpio/xmalloc.c
Normal file
65
gnu/usr.bin/cpio/xmalloc.c
Normal 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;
|
||||||
|
}
|
32
gnu/usr.bin/cpio/xstrdup.c
Normal file
32
gnu/usr.bin/cpio/xstrdup.c
Normal 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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user