Remove GNU cpio after fix of CVE-2010-0624.
Note that this is actually a no-op for most users, as this GNU cpio was broken on -HEAD and 8-STABLE since last March until the recent fix. FreeBSD 8.0+ uses BSD cpio by default and the code is being actively maintained. Blessed by: kientzle With hat: secteam MFC after: 3 days
This commit is contained in:
parent
8e6a6c380c
commit
c77aa7eff5
@ -14,6 +14,11 @@
|
||||
# The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last.
|
||||
#
|
||||
|
||||
# 20100326: gcpio removal
|
||||
OLD_FILES+=usr/bin/gcpio
|
||||
OLD_FILES+=usr/share/info/cpio.info.gz
|
||||
OLD_FILES+=usr/share/man/man1/gcpio.1.gz
|
||||
|
||||
# 20100322: libz update
|
||||
OLD_LIBS+=lib/libz.so.5
|
||||
.if ${TARGET_ARCH} == "amd64"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +0,0 @@
|
||||
Authors of GNU cpio
|
||||
|
||||
Phil Nelson <phil@cs.wwu.edu>
|
||||
David MacKenzie <djm@gnu.ai.mit.edu>
|
||||
John Oleynick <juo@klinzhai.rutgers.edu>
|
||||
Sergey Poznyakoff <gray@mirddin.farlep.net>
|
@ -1,340 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
|
||||
|
||||
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) <year> <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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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.
|
File diff suppressed because it is too large
Load Diff
@ -1,29 +0,0 @@
|
||||
$FreeBSD$
|
||||
|
||||
GNU cpio:
|
||||
|
||||
Originals can be found at: ftp://ftp.gnu.org/pub/gnu/cpio
|
||||
|
||||
Configure by:
|
||||
|
||||
./configure --disable-nls --without-libiconv-prefix \
|
||||
--without-libintl-prefix
|
||||
|
||||
Trim by:
|
||||
|
||||
rm Makefile.am Makefile.in aclocal.m4 config.h.in configure \
|
||||
configure.ac
|
||||
rm -r headers m4 rmt tests scripts po
|
||||
rm doc/Makefile.am doc/Makefile.in doc/mt.1 doc/cpio.info
|
||||
rm src/Makefile.am src/Makefile.in
|
||||
rm src/mt.c
|
||||
rm lib/Makefile.am lib/Makefile.in lib/Makefile.tmpl lib/alloca.c \
|
||||
lib/argmatch.[ch] lib/bcopy.c lib/fnmatch.c lib/fnmatch_.h \
|
||||
lib/fnmatch_loop.c lib/mkdir.c lib/quote.[ch] \
|
||||
lib/quotearg.[ch] lib/stdbool_.h lib/strcasecmp.c \
|
||||
lib/strdup.c lib/strerror.c lib/strncasecmp.c lib/sysexit_.h
|
||||
|
||||
Import by:
|
||||
|
||||
cvs import -m "Import GNU cpio 2.6 (trimmed)" src/contrib/cpio \
|
||||
GNU v2_6
|
@ -1,234 +0,0 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
@ -1,155 +0,0 @@
|
||||
GNU cpio NEWS -- history of user-visible changes. 2007-06-08
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
See the end of file for copying conditions.
|
||||
|
||||
Please send cpio bug reports to <bug-cpio@gnu.org>.
|
||||
|
||||
Version 2.8 - Sergey Poznyakoff, 2007-06-08
|
||||
|
||||
* Option --owner can be used in copy-out mode, allowing to uniformly override
|
||||
ownership of the files being added to the archive.
|
||||
|
||||
* Bugfixes:
|
||||
|
||||
** Symlinks were handled incorrectly in copy-out mode.
|
||||
** Fix handling of large files.
|
||||
** Fix setting the file permissions in copy-out mode.
|
||||
** Fix CAN-2005-1111
|
||||
|
||||
|
||||
Version 2.7 - Sergey Poznyakoff, 2006-10-21
|
||||
|
||||
* Improved error checking and diagnostics
|
||||
|
||||
* Bugfixes
|
||||
** Fixed CAN-1999-1572
|
||||
** Allow to use --sparse in both copy-in and copy-pass.
|
||||
** Fix bug that eventually caused copying out the same hard-linked
|
||||
file several times to archive.
|
||||
** Fix several LFS-related issues.
|
||||
** Fix Debian bug 335580.
|
||||
|
||||
|
||||
Version 2.6 - Sergey Poznyakoff, 2004-12-20
|
||||
|
||||
* Added NLS support
|
||||
|
||||
* Improved configure script
|
||||
|
||||
* Improved invocation consistency checking and help output
|
||||
|
||||
* Printing warning about truncation of inode numbers is suppressed by
|
||||
default. See below.
|
||||
|
||||
* New option --warning (-W) controls the level of output warnings:
|
||||
|
||||
-Wnone Disables all warnings
|
||||
-Wtruncate Enable warning about truncation of the inode number
|
||||
-Wall Enables all warnings
|
||||
|
||||
To disable a particular warning, prefix its name with 'no-', just
|
||||
like in gcc.
|
||||
|
||||
* New option --to-stdout extracts files to standard output.
|
||||
|
||||
* The output of `cpio --help' is largely improved.
|
||||
|
||||
* Bugfixes:
|
||||
** If a file grew n bytes in copy-pass mode, these n bytes got prepended
|
||||
to the contents of all subsequent files.
|
||||
** Padding the archive with zero bytes upon truncation of the file being
|
||||
archived was broken.
|
||||
|
||||
|
||||
Major changes in version 2.5:
|
||||
|
||||
* bug fixes from Debian, Red Hat, and SuSE GNU/Linux Distribution patches
|
||||
* --rsh-command option
|
||||
|
||||
Major changes in version 2.4:
|
||||
|
||||
* new texinfo documentation
|
||||
* --sparse option to write sparse files
|
||||
* --only-verify-crc option to verify a CRC format archive
|
||||
* --no-absolute-paths option to ignore absolute paths
|
||||
* --quiet option to supress printing number of blocks copied
|
||||
* handle disk input errors more gracefully
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Copyright information:
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to anyone to make or distribute verbatim copies
|
||||
of this document as received, in any medium, provided that the
|
||||
copyright notice and this permission notice are preserved,
|
||||
thus giving the recipient permission to redistribute in turn.
|
||||
|
||||
Permission is granted to distribute modified versions
|
||||
of this document, or of portions of it,
|
||||
under the above conditions, provided also that they
|
||||
carry prominent notices stating who last changed them.
|
||||
|
||||
Local variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
time-stamp-start: "changes. "
|
||||
time-stamp-format: "%:y-%02m-%02d"
|
||||
time-stamp-end: "\n"
|
||||
end:
|
@ -1,71 +0,0 @@
|
||||
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.
|
||||
|
||||
This package also includes rmt, the remote tape server, and mt, a tape
|
||||
drive control program; these two programs will only be compiled if
|
||||
your system supports remote command execution, and tape drive control
|
||||
operations, respectively.
|
||||
|
||||
See the file INSTALL for compilation and installation instructions for Unix.
|
||||
|
||||
For non-Unix systems [ Note: The non-Unix makefiles have not been tested
|
||||
for this release ]
|
||||
|
||||
makefile.pc is a makefile for Turbo C or C++ or Borland C++ on MS-DOS.
|
||||
|
||||
makefile.os2 is a makefile for MS C and GNU C (emx/gcc) on OS/2.
|
||||
cpio.def is a linker definition file for the MS C OS/2 version.
|
||||
|
||||
|
||||
The main advantages of GNU cpio over Unix versions are:
|
||||
|
||||
* It can access tape drives on other hosts using TCP/IP.
|
||||
|
||||
* `-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-cpio@gnu.org.
|
@ -1,20 +0,0 @@
|
||||
GNU cpio THANKS file
|
||||
|
||||
GNU cpio has originally been written by Phil Nelson <phil@cs.wwu.edu>
|
||||
and David MacKenzie <djm@gnu.ai.mit.edu>. It was further modified
|
||||
by John Oleynick <juo@gnu.org> and Sergey Poznyakoff <gray@gnu.org>
|
||||
who currently maintains it.
|
||||
|
||||
The following is a list of people who contributed to GNU cpio by
|
||||
reporting problems, suggesting various improvements or submitting actual
|
||||
code. Help us keep it complete and exempt of errors.
|
||||
|
||||
Benigno B. Junior <bbj@gentux.com.br>
|
||||
Brian Mays <brian@debian.org>
|
||||
Dmitry V. Levin <ldv@altlinux.org>
|
||||
Jim Castleberry <bhg9aha02@sneakemail.com>
|
||||
Holger Fleischmann <holger_fleischmann@mra.man.de>
|
||||
Matthew Braithwaite <mab@cnet.com>
|
||||
Mike Frysinger <vapier@gentoo.org>
|
||||
Mitsuru Chinen <mchinen@yamato.ibm.com>
|
||||
Peter Vrabec <pvrabec@redhat.com>
|
@ -1,159 +0,0 @@
|
||||
Following is the list of cpio-related reports to bug-gnu-utils.
|
||||
Many of them appear to be fixed, but quite a number of them is
|
||||
probably still waiting for being handled. The list is divided
|
||||
into two parts, the messages are in somehow arbitrary order.
|
||||
|
||||
* Bug reports
|
||||
--------------
|
||||
|
||||
** cpio -d bug (fwd) (score: 47)
|
||||
Author: Christian Smith <csmith@micromuse.com>
|
||||
Date: Wed, 14 Nov 2001 02:06:46 +0000 (GMT)
|
||||
This was bounced from bug-cpio@bogus.example.com I guess that
|
||||
isn't set up yet. -- /"\ \ / ASCII RIBBON CAMPAIGN - AGAINST
|
||||
HTML MAIL X - AGAINST MS ATTACHMENTS / \ $ cpio --version GNU
|
||||
cpio version 2
|
||||
/archive/html/bug-gnu-utils/2001-11/msg00170.html (4,548 bytes)
|
||||
|
||||
** bug in cpio with tapechange in copy-in-mode (score: 34)
|
||||
Author: Bernd =?ISO-8859-1?Q?Sch=FCler?=
|
||||
<b.schueler@eckert-buerotechnik.de>
|
||||
Date: 05 Aug 2002 18:37:56 +0200
|
||||
Hello, last i made a restore from tape, and no request for next
|
||||
tape happend, only an read-error occured. Here is an quick
|
||||
patch, please verify the problem and the patch-code. I'm not
|
||||
sure, if the pr
|
||||
/archive/html/bug-gnu-utils/2002-08/msg00122.html (4,518 bytes)
|
||||
|
||||
** Re: bug in cpio? (score: 40)
|
||||
Author: kasal@matsrv.math.cas.cz (Stepan Kasal)
|
||||
Date: Thu, 13 Jun 2002 07:44:14 +0000 (UTC)
|
||||
Hallo, the following option should help: -d, --make-directories
|
||||
Create leading directories where needed. Details: cpio won't
|
||||
create the directory for the file. Observe: kasal$ echo
|
||||
/home/kasal/tmp/db
|
||||
/archive/html/bug-gnu-utils/2002-06/msg00306.html (4,862 bytes)
|
||||
|
||||
** cpio 2.4.2 bug? (score: 40)
|
||||
Author: "H.J. Thomassen" <H.J.Thomassen@ATComputing.nl>
|
||||
Date: Thu, 10 Jan 2002 18:09:10 +0100 (CET)
|
||||
Hello, We use GNU-cpio 2.4.2 and have the following problem:
|
||||
Short: Assume I have a directory with two filenames, which are
|
||||
hardlinks to the same i-node. I make a crc-cpio archive with
|
||||
both files; th
|
||||
/archive/html/bug-gnu-utils/2002-01/msg00161.html (5,624 bytes)
|
||||
|
||||
** These two seem to be related:
|
||||
*** cpio copy-in and multiply-linked files (score: 35)
|
||||
Author: Chris Jaeger <cjaeger@ensim.com>
|
||||
Date: Tue, 07 Aug 2001 23:46:04 -0700
|
||||
Hi, I was wondering whether it was a bug or a feature that GNU
|
||||
cpio, while in copy-in mode, will create a multiply-linked set
|
||||
of files all of size 0 if the last linked file is not copied in
|
||||
due to th
|
||||
/archive/html/bug-gnu-utils/2001-08/msg00074.html (4,142 bytes)
|
||||
|
||||
*** (no subject) (score: 2)
|
||||
Author: brian@debian.org (Brian Mays)
|
||||
Date: Sat, 07 Jul 2001 16:35:13 -0400
|
||||
When hard-linked files (along with many other files) are
|
||||
archived to a cpio ustar format archive, the files are _not_
|
||||
all archived as hard links to each other in the archive. When
|
||||
the same set of fil
|
||||
/archive/html/bug-gnu-utils/2001-07/msg00080.html (5,666 bytes)
|
||||
|
||||
** These too:
|
||||
|
||||
*** Re: minor problems with slackware-current (score: 7)
|
||||
Author: Cezary Sliwa <sliwa@cft.edu.pl>
|
||||
Date: Wed, 1 Aug 2001 10:43:37 +0200
|
||||
"cpio --sparse" corrupts data. A fix attached. C.S. Attachment:
|
||||
cpio-2.4.2-sparse.diff Description: Text document
|
||||
/archive/html/bug-gnu-utils/2001-08/msg00000.html (3,989 bytes)
|
||||
|
||||
*** cpio --sparse (score: 34)
|
||||
Author: Cezary Sliwa <sliwa@cft.edu.pl>
|
||||
Date: Mon, 26 Mar 2001 10:43:34 +0200 (CEST)
|
||||
the '--sparse' option of gnu cpio causes data corruption
|
||||
(blocks of zeros are lost or appended to other files). C.S.
|
||||
/archive/html/bug-gnu-utils/2001-03/msg00235.html (3,671 bytes)
|
||||
|
||||
** And these too
|
||||
*** cpio-2.4.2: data corruption bug (score: 35)
|
||||
Author: Todd Kelley <toddk@oeone.com>
|
||||
Date: Fri, 09 Feb 2001 17:00:06 -0500
|
||||
Hello, Recently at OEone we fixed a bug in GNU cpio-2.4.2: When
|
||||
a file over about 0.5 megabyes grows while it is being
|
||||
archived, it and all files following it in the archive are
|
||||
corrupted. The crc do
|
||||
/archive/html/bug-gnu-utils/2001-02/msg00062.html (4,297 bytes)
|
||||
|
||||
*** cpio pass-through can corrupt files (score: 36)
|
||||
Author: "Parrott, Jeff" <Jeff.Parrott@sea.siemens.com>
|
||||
Date: Mon, 16 Oct 2000 13:32:57 -0400
|
||||
I have seen corrupted files as a result of using the
|
||||
pass-through option in cpio. The corruption occurs when
|
||||
active/in-use (and growing) files are being copied. The problem
|
||||
is that the file size has
|
||||
/archive/html/bug-gnu-utils/2000-10/msg00087.html (4,974 bytes)
|
||||
|
||||
** cpio 2.4.2 unconditionally takes the tape drive offline (score:
|
||||
39)
|
||||
Author: Scott Larson <scowl@plaza.ds.adp.com>
|
||||
Date: Thu, 11 Jan 2001 13:15:52 -0800
|
||||
We have been copying multiple volumes to a single tape with the
|
||||
System 5 version of cpio. The gnu version of cpio doesn't
|
||||
support this since it takes the tape offline (i.e. ejects the
|
||||
tape) after rea
|
||||
/archive/html/bug-gnu-utils/2001-01/msg00087.html (4,264 bytes)
|
||||
|
||||
** cpio -t can see international filenames, find -ls also suffers
|
||||
(score: 35)
|
||||
Author: "Dan Jacobson" <jidanni@kimo.FiXcomTHiS.tw>
|
||||
Date: Tue, 26 Dec 2000 07:38:53 +0800
|
||||
GNU cpio version 2.4.2 with cpio -t I can see Chinese [big5]
|
||||
filenames. with -tv, they become \267\247 etc Just like what
|
||||
happens with find . -print vs. find . -ls --
|
||||
http://www.geocities.com/jidanni
|
||||
/archive/html/bug-gnu-utils/2000-12/msg00143.html (4,084 bytes)
|
||||
|
||||
* Suggestions
|
||||
-------------
|
||||
|
||||
** GNU cpio suggestion (score: 42)
|
||||
Author: "H.J.Thomassen" <hjt@ATComputing.nl>
|
||||
Date: Mon, 17 Dec 2001 11:27:11 +0100
|
||||
Re: suggestion for GNU-cpio extension (plus reference
|
||||
implementation) We use cpio for our backup purposes. The backup
|
||||
is started automatically in the middle of the night. To chase
|
||||
away all users we d
|
||||
/archive/html/bug-gnu-utils/2001-12/msg00244.html (7,474 bytes)
|
||||
|
||||
** cpio suggestion + patch (score: 38)
|
||||
Author: Taylor Gautier <tgautier@s8.com>
|
||||
Date: Fri, 20 Apr 2001 09:40:05 -0700
|
||||
I have a suggestion for cpio. The suggestion is to make it copy
|
||||
files into a temporary name and then rename the file as the
|
||||
last operation. Since UNIX filesystems are supposed to
|
||||
gaurantee atomicity
|
||||
/archive/html/bug-gnu-utils/2001-04/msg00169.html (10,674
|
||||
bytes)
|
||||
|
||||
** [cpio] man page enhancement: a Example section ? (score: 5)
|
||||
Author: Yannick Patois <patois@calvix.org>
|
||||
Date: Wed, 24 Oct 2001 12:48:33 +0200 (CEST)
|
||||
Hello, I seldom use cpio (as I think many people) and only had
|
||||
to use it once or twice. IMHA, would be good to have a small
|
||||
section with an example of most often performed actions
|
||||
(creating an archiv
|
||||
/archive/html/bug-gnu-utils/2001-10/msg00270.html (4,336 bytes)
|
||||
|
||||
** Patch to cpio to enable verbose *skipping* of files (score: 40)
|
||||
Author: Tomas Pospisek <tpo@sourcepole.ch>
|
||||
Date: Mon, 8 Oct 2001 13:54:14 +0200 (CEST)
|
||||
This patch enables cpio to be verbose about the files that it
|
||||
does not copy, which is very handy for seeing cpio's progress
|
||||
through a tape or simply for debuging. The patch along with a
|
||||
Debian packag
|
||||
/archive/html/bug-gnu-utils/2001-10/msg00083.html (4,548 bytes)
|
||||
|
@ -1,41 +0,0 @@
|
||||
.TH CPIO 1L \" -*- nroff -*-
|
||||
.SH NAME
|
||||
cpio \- copy files to and from archives
|
||||
.SH SYNOPSIS
|
||||
.B cpio
|
||||
{\-o|\-\-create} [\-0acvABLV] [\-C bytes] [\-H format] [\-M message]
|
||||
[\-O [[user@]host:]archive] [\-F [[user@]host:]archive]
|
||||
[\-\-file=[[user@]host:]archive] [\-\-format=format] [\-\-message=message]
|
||||
[\-\-null] [\-\-reset-access-time] [\-\-verbose] [\-\-dot] [\-\-append]
|
||||
[\-\-block-size=blocks] [\-\-dereference] [\-\-io-size=bytes] [\-\-quiet]
|
||||
[\-\-force\-local] [\-\-rsh-command=command] [\-\-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] [\-t|\-\-list] [\-\-swap-bytes] [\-\-swap] [\-\-dot]
|
||||
[\-\-unconditional] [\-\-verbose] [\-\-block-size=blocks] [\-\-swap-halfwords]
|
||||
[\-\-io-size=bytes] [\-\-pattern-file=file] [\-\-format=format]
|
||||
[\-\-owner=[user][:.][group]] [\-\-no-preserve-owner] [\-\-message=message]
|
||||
[\-\-force\-local] [\-\-absolute\-filenames] [\-\-sparse]
|
||||
[\-\-only\-verify\-crc] [\-\-quiet] [\-\-rsh-command=command] [\-\-help]
|
||||
[\-\-version] [pattern...] [< archive]
|
||||
|
||||
.B cpio
|
||||
{\-p|\-\-pass-through} [\-0adlmuvLV] [\-R [user][:.][group]]
|
||||
[\-\-null] [\-\-reset-access-time] [\-\-make-directories] [\-\-link] [\-\-quiet]
|
||||
[\-\-preserve-modification-time] [\-\-unconditional] [\-\-verbose] [\-\-dot]
|
||||
[\-\-dereference] [\-\-owner=[user][:.][group]] [\-\-no-preserve-owner]
|
||||
[\-\-sparse] [\-\-help] [\-\-version] destination-directory < name-list
|
||||
.SH DESCRIPTION
|
||||
GNU cpio is fully documented in the texinfo documentation. To access the
|
||||
help from your command line, type
|
||||
.PP
|
||||
\fBinfo cpio
|
||||
.PP
|
||||
The online copy of the documentation is available at the following address:
|
||||
.PP
|
||||
http://www.gnu.org/software/cpio/manual
|
@ -1,602 +0,0 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header
|
||||
@setfilename cpio.info
|
||||
@settitle cpio
|
||||
@setchapternewpage off
|
||||
@c %**end of header
|
||||
|
||||
@dircategory Archiving
|
||||
@direntry
|
||||
* Cpio: (cpio). Copy-in-copy-out archiver to tape or disk.
|
||||
@end direntry
|
||||
|
||||
@include version.texi
|
||||
|
||||
@copying
|
||||
This manual documents GNU cpio (version @value{VERSION}, @value{UPDATED}).
|
||||
|
||||
Copyright @copyright{} 1995, 2001, 2002, 2004 Free Software Foundation, Inc.
|
||||
@sp 1
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.2 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with the Front-Cover texts being ``A GNU Manual'',
|
||||
and with the Back-Cover Texts as in (a) below. A copy of the license
|
||||
is included in the section entitled ``GNU Free Documentation License''.
|
||||
|
||||
(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
|
||||
this GNU Manual, like GNU software. Copies published by the Free
|
||||
Software Foundation raise funds for GNU development.''
|
||||
@end quotation
|
||||
@end copying
|
||||
|
||||
@titlepage
|
||||
@title GNU CPIO
|
||||
@subtitle @value{VERSION} @value{UPDATED}
|
||||
@author by Robert Carleton
|
||||
@c copyright page
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
@sp 2
|
||||
Published by the Free Software Foundation @*
|
||||
51 Franklin Street, Fifth Floor, @*
|
||||
Boston, MA 02110-1301, USA @*
|
||||
@end titlepage
|
||||
|
||||
@node Top, Introduction, (dir), (dir)
|
||||
@comment node-name, next, previous, up
|
||||
|
||||
@ifinfo
|
||||
@top
|
||||
|
||||
GNU cpio is a tool for creating and extracting archives, or copying
|
||||
files from one place to another. It handles a number of cpio formats as
|
||||
well as reading and writing tar files. This is the first edition of the
|
||||
GNU cpio documentation and is consistent with @value{VERSION}.
|
||||
|
||||
@end ifinfo
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
* Tutorial:: Getting started.
|
||||
* Invoking cpio:: How to invoke @command{cpio}.
|
||||
* Media:: Using tapes and other archive media.
|
||||
* Reports:: Reporting bugs or suggestions
|
||||
* Concept Index:: Concept index.
|
||||
|
||||
@detailmenu
|
||||
--- The Detailed Node Listing ---
|
||||
|
||||
Invoking cpio
|
||||
|
||||
* Copy-out mode::
|
||||
* Copy-in mode::
|
||||
* Copy-pass mode::
|
||||
* Options::
|
||||
|
||||
@end detailmenu
|
||||
@end menu
|
||||
|
||||
@node Introduction, Tutorial, Top, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Introduction
|
||||
|
||||
GNU cpio copies files into or out of a cpio or tar archive, The archive
|
||||
can be another file on the disk, a magnetic tape, or a pipe.
|
||||
|
||||
GNU cpio supports the following archive formats: binary, old ASCII, new
|
||||
ASCII, crc, HPUX binary, HPUX old ASCII, old tar, and POSIX.1 tar. The
|
||||
tar format is provided for compatibility with the tar program. By
|
||||
default, cpio creates binary format archives, for compatibility with
|
||||
older cpio programs. When extracting from archives, cpio automatically
|
||||
recognizes which kind of archive it is reading and can read archives
|
||||
created on machines with a different byte-order.
|
||||
|
||||
@node Tutorial, Invoking cpio, Introduction, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Tutorial
|
||||
@cindex creating a cpio archive
|
||||
@cindex extracting a cpio archive
|
||||
@cindex copying directory structures
|
||||
@cindex passing directory structures
|
||||
|
||||
|
||||
GNU cpio performs three primary functions. Copying files to an
|
||||
archive, Extracting files from an archive, and passing files to another
|
||||
directory tree. An archive can be a file on disk, one or more floppy
|
||||
disks, or one or more tapes.
|
||||
|
||||
When creating an archive, cpio takes the list of files to be processed
|
||||
from the standard input, and then sends the archive to the standard
|
||||
output, or to the device defined by the @option{-F} option.
|
||||
@xref{Copy-out mode}. Usually find or ls is used to provide this list
|
||||
to the standard input. In the following example you can see the
|
||||
possibilities for archiving the contents of a single directory.
|
||||
|
||||
|
||||
@example
|
||||
@cartouche
|
||||
% ls | cpio -ov > directory.cpio
|
||||
@end cartouche
|
||||
@end example
|
||||
|
||||
The @option{-o} option creates the archive, and the @option{-v} option
|
||||
prints the names of the files archived as they are added. Notice that
|
||||
the options can be put together after a single @option{-} or can be placed
|
||||
separately on the command line. The @samp{>} redirects the cpio output
|
||||
to the file @samp{directory.cpio}.
|
||||
|
||||
|
||||
If you wanted to archive an entire directory tree, the find command can
|
||||
provide the file list to cpio:
|
||||
|
||||
|
||||
@example
|
||||
@cartouche
|
||||
% find . -print -depth | cpio -ov > tree.cpio
|
||||
@end cartouche
|
||||
@end example
|
||||
|
||||
|
||||
This will take all the files in the current directory, the directories
|
||||
below and place them in the archive tree.cpio. Again the @option{-o}
|
||||
creates an archive, and the @option{-v} option shows you the name of the
|
||||
files as they are archived. @xref{Copy-out mode}. Using the @samp{.} in the
|
||||
find statement will give you more flexibility when doing restores, as it
|
||||
will save file names with a relative path vice a hard wired, absolute
|
||||
path. The @option{-depth} option forces @samp{find} to print of the
|
||||
entries in a directory before printing the directory itself. This
|
||||
limits the effects of restrictive directory permissions by printing the
|
||||
directory entries in a directory before the directory name itself.
|
||||
|
||||
|
||||
|
||||
|
||||
Extracting an archive requires a bit more thought because cpio will not
|
||||
create directories by default. Another characteristic, is it will not
|
||||
overwrite existing files unless you tell it to.
|
||||
|
||||
|
||||
@example
|
||||
@cartouche
|
||||
% cpio -iv < directory.cpio
|
||||
@end cartouche
|
||||
@end example
|
||||
|
||||
This will retrieve the files archived in the file directory.cpio and
|
||||
place them in the present directory. The @option{-i} option extracts the
|
||||
archive and the @option{-v} shows the file names as they are extracted.
|
||||
If you are dealing with an archived directory tree, you need to use the
|
||||
@option{-d} option to create directories as necessary, something like:
|
||||
|
||||
@example
|
||||
@cartouche
|
||||
% cpio -idv < tree.cpio
|
||||
@end cartouche
|
||||
@end example
|
||||
|
||||
This will take the contents of the archive tree.cpio and extract it to
|
||||
the current directory. If you try to extract the files on top of files
|
||||
of the same name that already exist (and have the same or later
|
||||
modification time) cpio will not extract the file unless told to do so
|
||||
by the -u option. @xref{Copy-in mode}.
|
||||
|
||||
|
||||
In copy-pass mode, cpio copies files from one directory tree to another,
|
||||
combining the copy-out and copy-in steps without actually using an
|
||||
archive. It reads the list of files to copy from the standard input;
|
||||
the directory into which it will copy them is given as a non-option
|
||||
argument. @xref{Copy-pass mode}.
|
||||
|
||||
@example
|
||||
@cartouche
|
||||
% find . -depth -print0 | cpio --null -pvd new-dir
|
||||
@end cartouche
|
||||
@end example
|
||||
|
||||
|
||||
The example shows copying the files of the present directory, and
|
||||
sub-directories to a new directory called new-dir. Some new options are
|
||||
the @option{-print0} available with GNU find, combined with the
|
||||
@option{--null} option of cpio. These two options act together to send
|
||||
file names between find and cpio, even if special characters are
|
||||
embedded in the file names. Another is @option{-p}, which tells cpio to
|
||||
pass the files it finds to the directory @samp{new-dir}.
|
||||
|
||||
@node Invoking cpio, Media, Tutorial, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Invoking cpio
|
||||
@cindex invoking cpio
|
||||
@cindex command line options
|
||||
|
||||
@menu
|
||||
* Copy-out mode::
|
||||
* Copy-in mode::
|
||||
* Copy-pass mode::
|
||||
* Options::
|
||||
@end menu
|
||||
|
||||
@node Copy-out mode, Copy-in mode, Invoking cpio, Invoking cpio
|
||||
@comment node-name, next, previous, up
|
||||
@section Copy-out mode
|
||||
|
||||
In copy-out mode, cpio copies files into an archive. It reads a list
|
||||
of filenames, one per line, on the standard input, and writes the
|
||||
archive onto the standard output. A typical way to generate the list
|
||||
of filenames is with the find command; you should give find the -depth
|
||||
option to minimize problems with permissions on directories that are
|
||||
unreadable.
|
||||
@xref{Options}.
|
||||
|
||||
@example
|
||||
cpio @{-o|--create@} [-0acvABLV] [-C bytes] [-H format]
|
||||
[-M message] [-O [[user@@]host:]archive] [-F [[user@@]host:]archive]
|
||||
[--file=[[user@@]host:]archive] [--format=format]
|
||||
[--message=message][--null] [--reset-access-time] [--verbose]
|
||||
[--dot] [--append] [--block-size=blocks] [--dereference]
|
||||
[--io-size=bytes] [--rsh-command=command] [--help] [--version]
|
||||
< name-list [> archive]
|
||||
@end example
|
||||
|
||||
@node Copy-in mode, Copy-pass mode, Copy-out mode, Invoking cpio
|
||||
@comment node-name, next, previous, up
|
||||
@section Copy-in mode
|
||||
|
||||
In copy-in mode, cpio copies files out of an archive or lists the
|
||||
archive contents. It reads the archive from the standard input. Any
|
||||
non-option command line arguments are shell globbing patterns; only
|
||||
files in the archive whose names match one or more of those patterns are
|
||||
copied from the archive. Unlike in the shell, an initial @samp{.} in a
|
||||
filename does match a wildcard at the start of a pattern, and a @samp{/} in a
|
||||
filename can match wildcards. If no patterns are given, all files are
|
||||
extracted. @xref{Options}.
|
||||
|
||||
@example
|
||||
cpio @{-i|--extract@} [-bcdfmnrtsuvBSV] [-C bytes] [-E file]
|
||||
[-H format] [-M message] [-R [user][:.][group]]
|
||||
[-I [[user@@]host:]archive] [-F [[user@@]host:]archive]
|
||||
[--file=[[user@@]host:]archive] [--make-directories]
|
||||
[--nonmatching] [--preserve-modification-time]
|
||||
[--numeric-uid-gid] [--rename] [--list] [--swap-bytes] [--swap]
|
||||
[--dot] [--unconditional] [--verbose] [--block-size=blocks]
|
||||
[--swap-halfwords] [--io-size=bytes] [--pattern-file=file]
|
||||
[--format=format] [--owner=[user][:.][group]]
|
||||
[--no-preserve-owner] [--message=message] [--help] [--version]
|
||||
[--absolute-filenames] [--sparse] [-only-verify-crc] [-quiet]
|
||||
[--rsh-command=command] [pattern...] [< archive]
|
||||
@end example
|
||||
|
||||
@node Copy-pass mode, Options, Copy-in mode, Invoking cpio
|
||||
@comment node-name, next, previous, up
|
||||
@section Copy-pass mode
|
||||
|
||||
In copy-pass mode, cpio copies files from one directory tree to
|
||||
another, combining the copy-out and copy-in steps without actually
|
||||
using an archive. It reads the list of files to copy from the
|
||||
standard input; the directory into which it will copy them is given as
|
||||
a non-option argument.
|
||||
@xref{Options}.
|
||||
|
||||
@example
|
||||
cpio @{-p|--pass-through@} [-0adlmuvLV] [-R [user][:.][group]]
|
||||
[--null] [--reset-access-time] [--make-directories] [--link]
|
||||
[--preserve-modification-time] [--unconditional] [--verbose]
|
||||
[--dot] [--dereference] [--owner=[user][:.][group]] [--sparse]
|
||||
[--no-preserve-owner] [--help] [--version] destination-directory
|
||||
< name-list
|
||||
@end example
|
||||
|
||||
|
||||
|
||||
@node Options, , Copy-pass mode, Invoking cpio
|
||||
@comment node-name, next, previous, up
|
||||
@section Options
|
||||
|
||||
|
||||
@table @code
|
||||
|
||||
|
||||
@item -0
|
||||
@itemx --null
|
||||
Read a list of filenames terminated by a null character, instead of a
|
||||
newline, so that files whose names contain newlines can be archived.
|
||||
GNU find is one way to produce a list of null-terminated filenames.
|
||||
This option may be used in copy-out and copy-pass modes.
|
||||
|
||||
@item -a
|
||||
@itemx --reset-access-time
|
||||
Reset the access times of files after reading them, so
|
||||
that it does not look like they have just been read.
|
||||
|
||||
@item -A
|
||||
@itemx --append
|
||||
Append to an existing archive. Only works in copy-out
|
||||
mode. The archive must be a disk file specified with
|
||||
the @option{-O} or @option{-F} (@option{--file}) option.
|
||||
|
||||
@item -b
|
||||
@itemx --swap
|
||||
Swap both halfwords of words and bytes of halfwords in the data.
|
||||
Equivalent to -sS. This option may be used in copy-in mode. Use this
|
||||
option to convert 32-bit integers between big-endian and little-endian
|
||||
machines.
|
||||
|
||||
@item -B
|
||||
Set the I/O block size to 5120 bytes. Initially the
|
||||
block size is 512 bytes.
|
||||
|
||||
@item --block-size=@var{block-size}
|
||||
Set the I/O block size to @var{block-size} * 512 bytes.
|
||||
|
||||
@item -c
|
||||
Use the old portable (ASCII) archive format.
|
||||
|
||||
@item -C @var{io-size}
|
||||
@itemx --io-size=@var{io-size}
|
||||
Set the I/O block size to @var{io-size} bytes.
|
||||
|
||||
@item -d
|
||||
@itemx --make-directories
|
||||
Create leading directories where needed.
|
||||
|
||||
@item -E @var{file}
|
||||
@itemx --pattern-file=@var{file}
|
||||
Read additional patterns specifying filenames to extract or list from
|
||||
@var{file}. The lines of @var{file} are treated as if they had been non-option
|
||||
arguments to cpio. This option is used in copy-in mode,
|
||||
|
||||
@item -f
|
||||
@itemx --nonmatching
|
||||
Only copy files that do not match any of the given
|
||||
patterns.
|
||||
|
||||
@item -F @var{archive}
|
||||
@itemx --file=@var{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 @samp{@var{hostname}:}, where @var{hostname} is the name or IP
|
||||
address of the machine. The hostname can be preceded by a username and an
|
||||
@samp{@@} to access the remote tape drive as that user, if you have
|
||||
permission to do so (typically an entry in that user's @file{~/.rhosts}
|
||||
file).
|
||||
|
||||
@item --force-local
|
||||
With @option{-F}, @option{-I}, or @option{-O}, take the archive file name to be a
|
||||
local file even if it contains a colon, which would
|
||||
ordinarily indicate a remote host name.
|
||||
|
||||
@item -H @var{format}
|
||||
@itemx --format=@var{format}
|
||||
Use archive format @var{format}. The valid formats are listed below; the same
|
||||
names are also recognized in all-caps. The default in copy-in mode is
|
||||
to automatically detect the archive format, and in copy-out mode is
|
||||
@samp{bin}.
|
||||
|
||||
@table @samp
|
||||
@item bin
|
||||
The obsolete binary format.
|
||||
|
||||
@item odc
|
||||
The old (POSIX.1) portable format.
|
||||
|
||||
@item newc
|
||||
The new (SVR4) portable format, which supports file systems having more
|
||||
than 65536 i-nodes.
|
||||
|
||||
@item crc
|
||||
The new (SVR4) portable format with a checksum added.
|
||||
|
||||
@item tar
|
||||
The old tar format.
|
||||
|
||||
@item ustar
|
||||
The POSIX.1 tar format. Also recognizes GNU tar archives, which are
|
||||
similar but not identical.
|
||||
|
||||
@item hpbin
|
||||
The obsolete binary format used by HPUX's cpio (which stores device
|
||||
files differently).
|
||||
|
||||
@item hpodc
|
||||
The portable format used by HPUX's cpio (which stores device files
|
||||
differently).
|
||||
@end table
|
||||
|
||||
@item -i
|
||||
@itemx --extract
|
||||
Run in copy-in mode.
|
||||
@xref{Copy-in mode}.
|
||||
|
||||
@item -I @var{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
|
||||
@samp{@var{hostname}:}, where @var{hostname} is the name or IP address
|
||||
of the remote host. The hostname can be preceded by a username and an @samp{@@} to
|
||||
access the remote tape drive as that user, if you have permission to do
|
||||
so (typically an entry in that user's @file{~/.rhosts} file).
|
||||
|
||||
@item -k
|
||||
Ignored; for compatibility with other versions of cpio.
|
||||
|
||||
@item -l
|
||||
@itemx --link
|
||||
Link files instead of copying them, when possible.
|
||||
|
||||
@item -L
|
||||
@itemx --dereference
|
||||
Copy the file that a symbolic link points to, rather than the symbolic
|
||||
link itself.
|
||||
|
||||
@item -m
|
||||
@itemx --preserve-modification-time
|
||||
Retain previous file modification times when creating files.
|
||||
|
||||
@item -M @var{message}
|
||||
@itemx --message=@var{message}
|
||||
Print @var{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 @var{message} contains the string @samp{%d}, it is replaced by the
|
||||
current volume number (starting at 1).
|
||||
|
||||
@item -n
|
||||
@itemx --numeric-uid-gid
|
||||
Show numeric UID and GID instead of translating them into names when using the
|
||||
@option{--verbose} option.
|
||||
|
||||
@item --absolute-filenames
|
||||
Do not strip leading file name components that contain ".." and
|
||||
leading slashes from file names in copy-in mode
|
||||
|
||||
@item --no-preserve-owner
|
||||
Do not change the ownership of the files; leave them owned by the user
|
||||
extracting them. This is the default for non-root users, so that users
|
||||
on System V don't inadvertantly give away files. This option can be
|
||||
used in copy-in mode and copy-pass mode
|
||||
|
||||
@item -o
|
||||
@itemx --create
|
||||
Run in copy-out mode.
|
||||
@xref{Copy-out mode}.
|
||||
|
||||
@item -O @var{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
|
||||
@samp{@var{hostname}:}, where @var{hostname} is the name or IP address
|
||||
of the machine. The hostname can be preceded by a username and an @samp{@@} to
|
||||
access the remote tape drive as that user, if you have permission to do
|
||||
so (typically an entry in that user's @file{~/.rhosts} file).
|
||||
|
||||
@item --only-verify-crc
|
||||
Verify the CRC's of each file in the archive, when reading a CRC format
|
||||
archive. Don't actually extract the files.
|
||||
|
||||
@item -p
|
||||
@itemx --pass-through
|
||||
Run in copy-pass mode.
|
||||
@xref{Copy-pass mode}.
|
||||
|
||||
@item --quiet
|
||||
Do not print the number of blocks copied.
|
||||
|
||||
@item -r
|
||||
@itemx --rename
|
||||
Interactively rename files.
|
||||
|
||||
@item -R @var{owner}
|
||||
@itemx --owner @var{owner}
|
||||
|
||||
In copy-in and copy-pass mode, set the ownership of all files created
|
||||
to the specified @var{owner} (this operation is allowed only for the
|
||||
super-user). In copy-out mode, store the supplied owner information in
|
||||
the archive.
|
||||
|
||||
The argument can be either the user name or the user name
|
||||
and group name, separated by a dot or a colon, or the group name,
|
||||
preceeded by a dot or a colon, as shown in the examples below:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
cpio --owner smith
|
||||
cpio --owner smith:
|
||||
cpio --owner smith:users
|
||||
cpio --owner :users
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
If the group is omitted but the @samp{:} or @samp{.} separator is
|
||||
given, as in the second example. the given user's login group will be
|
||||
used.
|
||||
|
||||
@item --rsh-command=@var{command}
|
||||
Notifies cpio that is should use @var{command} to communicate with remote
|
||||
devices.
|
||||
|
||||
@item -s
|
||||
@itemx --swap-bytes
|
||||
Swap the bytes of each halfword (pair of bytes) in the files. This option
|
||||
can be used in copy-in mode.
|
||||
|
||||
@item -S
|
||||
@itemx --swap-halfwords
|
||||
Swap the halfwords of each word (4 bytes) in the files. This option may
|
||||
be used in copy-in mode.
|
||||
|
||||
@item --sparse
|
||||
Write files with large blocks of zeros as sparse files. This option is
|
||||
used in copy-in and copy-pass modes.
|
||||
|
||||
@item -t
|
||||
@itemx --list
|
||||
Print a table of contents of the input.
|
||||
|
||||
@item -u
|
||||
@itemx --unconditional
|
||||
Replace all files, without asking whether to replace
|
||||
existing newer files with older files.
|
||||
|
||||
@item -v
|
||||
@itemx --verbose
|
||||
List the files processed, or with @option{-t}, give an @samp{ls -l} style
|
||||
table of contents listing. In a verbose table of contents of a ustar
|
||||
archive, user and group names in the archive that do not exist on the
|
||||
local system are replaced by the names that correspond locally to the
|
||||
numeric UID and GID stored in the archive.
|
||||
|
||||
@item -V
|
||||
@itemx --dot
|
||||
Print a @samp{.} for each file processed.
|
||||
|
||||
@item --version
|
||||
Print the cpio program version number and exit.
|
||||
@end table
|
||||
|
||||
|
||||
@node Media, Reports, Invoking cpio, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Magnetic Media
|
||||
@cindex magnetic media
|
||||
|
||||
Archives are usually written on removable media--tape cartridges, mag
|
||||
tapes, or floppy disks.
|
||||
|
||||
The amount of data a tape or disk holds depends not only on its size,
|
||||
but also on how it is formatted. A 2400 foot long reel of mag tape
|
||||
holds 40 megabytes of data when formated at 1600 bits per inch. The
|
||||
physically smaller EXABYTE tape cartridge holds 2.3 gigabytes.
|
||||
|
||||
Magnetic media are re-usable--once the archive on a tape is no longer
|
||||
needed, the archive can be erased and the tape or disk used over. Media
|
||||
quality does deteriorate with use, however. Most tapes or disks should
|
||||
be disgarded when they begin to produce data errors.
|
||||
|
||||
Magnetic media are written and erased using magnetic fields, and should
|
||||
be protected from such fields to avoid damage to stored data. Sticking
|
||||
a floppy disk to a filing cabinet using a magnet is probably not a good
|
||||
idea.
|
||||
|
||||
@node Reports, Concept Index, Media, Top
|
||||
@chapter Reporting bugs or suggestions
|
||||
|
||||
It is possible you will encounter a bug in @command{cpio}.
|
||||
If this happens, we would like to hear about it. As the purpose of bug
|
||||
reporting is to improve software, please be sure to include maximum
|
||||
information when reporting a bug. The information needed is:
|
||||
|
||||
@itemize @bullet
|
||||
@item Version of the package you are using.
|
||||
@item Compilation options used when configuring the package.
|
||||
@item Conditions under which the bug appears.
|
||||
@end itemize
|
||||
|
||||
Send your report to <bug-cpio@@gnu.org>. Allow us a couple of
|
||||
days to answer.
|
||||
|
||||
@node Concept Index, , Reports, Top
|
||||
@comment node-name, next, previous, up
|
||||
@unnumbered Concept Index
|
||||
@printindex cp
|
||||
@contents
|
||||
@bye
|
@ -1,4 +0,0 @@
|
||||
@set UPDATED 7 June 2007
|
||||
@set UPDATED-MONTH June 2007
|
||||
@set EDITION 2.8
|
||||
@set VERSION 2.8
|
@ -1,54 +0,0 @@
|
||||
/* Memory allocation on the stack.
|
||||
|
||||
Copyright (C) 1995, 1999, 2001-2004, 2006-2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
USA. */
|
||||
|
||||
/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
|
||||
means there is a real alloca function. */
|
||||
#ifndef _GL_ALLOCA_H
|
||||
#define _GL_ALLOCA_H
|
||||
|
||||
/* alloca (N) returns a pointer to N bytes of memory
|
||||
allocated on the stack, which will last until the function returns.
|
||||
Use of alloca should be avoided:
|
||||
- inside arguments of function calls - undefined behaviour,
|
||||
- in inline functions - the allocation may actually last until the
|
||||
calling function returns,
|
||||
- for huge N (say, N >= 65536) - you never know how large (or small)
|
||||
the stack is, and when the stack cannot fulfill the memory allocation
|
||||
request, the program just crashes.
|
||||
*/
|
||||
|
||||
#ifndef alloca
|
||||
# ifdef __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
# elif defined _AIX
|
||||
# define alloca __alloca
|
||||
# elif defined _MSC_VER
|
||||
# include <malloc.h>
|
||||
# define alloca _alloca
|
||||
# else
|
||||
# include <stddef.h>
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
void *alloca (size_t);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _GL_ALLOCA_H */
|
@ -1,25 +0,0 @@
|
||||
/* Default definition for ARGP_PROGRAM_BUG_ADDRESS.
|
||||
Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* If set by the user program, it should point to string that is the
|
||||
bug-reporting address for the program. It will be printed by argp_help if
|
||||
the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help
|
||||
messages), embedded in a sentence that says something like `Report bugs to
|
||||
ADDR.'. */
|
||||
const char *argp_program_bug_address;
|
@ -1,31 +0,0 @@
|
||||
/* Default definition for ARGP_ERR_EXIT_STATUS
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sysexits.h>
|
||||
|
||||
#include "argp.h"
|
||||
|
||||
/* The exit status that argp will use when exiting due to a parsing error.
|
||||
If not defined or set by the user program, this defaults to EX_USAGE from
|
||||
<sysexits.h>. */
|
||||
error_t argp_err_exit_status = EX_USAGE;
|
@ -1,435 +0,0 @@
|
||||
/* Word-wrapping and line-truncating streams
|
||||
Copyright (C) 1997-1999,2001,2002,2003,2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* This package emulates glibc `line_wrap_stream' semantics for systems that
|
||||
don't have that. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "argp-fmtstream.h"
|
||||
#include "argp-namefrob.h"
|
||||
|
||||
#ifndef ARGP_FMTSTREAM_USE_LINEWRAP
|
||||
|
||||
#ifndef isblank
|
||||
#define isblank(ch) ((ch)==' ' || (ch)=='\t')
|
||||
#endif
|
||||
|
||||
#if defined _LIBC && defined USE_IN_LIBIO
|
||||
# include <wchar.h>
|
||||
# include <libio/libioP.h>
|
||||
# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
|
||||
#endif
|
||||
|
||||
#define INIT_BUF_SIZE 200
|
||||
#define PRINTF_SIZE_GUESS 150
|
||||
|
||||
/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
|
||||
written on it with LMARGIN spaces and limits them to RMARGIN columns
|
||||
total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
|
||||
replacing the whitespace before them with a newline and WMARGIN spaces.
|
||||
Otherwise, chars beyond RMARGIN are simply dropped until a newline.
|
||||
Returns NULL if there was an error. */
|
||||
argp_fmtstream_t
|
||||
__argp_make_fmtstream (FILE *stream,
|
||||
size_t lmargin, size_t rmargin, ssize_t wmargin)
|
||||
{
|
||||
argp_fmtstream_t fs;
|
||||
|
||||
fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream));
|
||||
if (fs != NULL)
|
||||
{
|
||||
fs->stream = stream;
|
||||
|
||||
fs->lmargin = lmargin;
|
||||
fs->rmargin = rmargin;
|
||||
fs->wmargin = wmargin;
|
||||
fs->point_col = 0;
|
||||
fs->point_offs = 0;
|
||||
|
||||
fs->buf = (char *) malloc (INIT_BUF_SIZE);
|
||||
if (! fs->buf)
|
||||
{
|
||||
free (fs);
|
||||
fs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fs->p = fs->buf;
|
||||
fs->end = fs->buf + INIT_BUF_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return fs;
|
||||
}
|
||||
#if 0
|
||||
/* Not exported. */
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_make_fmtstream, argp_make_fmtstream)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Flush FS to its stream, and free it (but don't close the stream). */
|
||||
void
|
||||
__argp_fmtstream_free (argp_fmtstream_t fs)
|
||||
{
|
||||
__argp_fmtstream_update (fs);
|
||||
if (fs->p > fs->buf)
|
||||
{
|
||||
#ifdef USE_IN_LIBIO
|
||||
__fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
|
||||
#else
|
||||
fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
|
||||
#endif
|
||||
}
|
||||
free (fs->buf);
|
||||
free (fs);
|
||||
}
|
||||
#if 0
|
||||
/* Not exported. */
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the
|
||||
end of its buffer. This code is mostly from glibc stdio/linewrap.c. */
|
||||
void
|
||||
__argp_fmtstream_update (argp_fmtstream_t fs)
|
||||
{
|
||||
char *buf, *nl;
|
||||
size_t len;
|
||||
|
||||
/* Scan the buffer for newlines. */
|
||||
buf = fs->buf + fs->point_offs;
|
||||
while (buf < fs->p)
|
||||
{
|
||||
size_t r;
|
||||
|
||||
if (fs->point_col == 0 && fs->lmargin != 0)
|
||||
{
|
||||
/* We are starting a new line. Print spaces to the left margin. */
|
||||
const size_t pad = fs->lmargin;
|
||||
if (fs->p + pad < fs->end)
|
||||
{
|
||||
/* We can fit in them in the buffer by moving the
|
||||
buffer text up and filling in the beginning. */
|
||||
memmove (buf + pad, buf, fs->p - buf);
|
||||
fs->p += pad; /* Compensate for bigger buffer. */
|
||||
memset (buf, ' ', pad); /* Fill in the spaces. */
|
||||
buf += pad; /* Don't bother searching them. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No buffer space for spaces. Must flush. */
|
||||
size_t i;
|
||||
for (i = 0; i < pad; i++)
|
||||
{
|
||||
#ifdef USE_IN_LIBIO
|
||||
if (_IO_fwide (fs->stream, 0) > 0)
|
||||
putwc_unlocked (L' ', fs->stream);
|
||||
else
|
||||
#endif
|
||||
putc_unlocked (' ', fs->stream);
|
||||
}
|
||||
}
|
||||
fs->point_col = pad;
|
||||
}
|
||||
|
||||
len = fs->p - buf;
|
||||
nl = memchr (buf, '\n', len);
|
||||
|
||||
if (fs->point_col < 0)
|
||||
fs->point_col = 0;
|
||||
|
||||
if (!nl)
|
||||
{
|
||||
/* The buffer ends in a partial line. */
|
||||
|
||||
if (fs->point_col + len < fs->rmargin)
|
||||
{
|
||||
/* The remaining buffer text is a partial line and fits
|
||||
within the maximum line width. Advance point for the
|
||||
characters to be written and stop scanning. */
|
||||
fs->point_col += len;
|
||||
break;
|
||||
}
|
||||
else
|
||||
/* Set the end-of-line pointer for the code below to
|
||||
the end of the buffer. */
|
||||
nl = fs->p;
|
||||
}
|
||||
else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin)
|
||||
{
|
||||
/* The buffer contains a full line that fits within the maximum
|
||||
line width. Reset point and scan the next line. */
|
||||
fs->point_col = 0;
|
||||
buf = nl + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This line is too long. */
|
||||
r = fs->rmargin - 1;
|
||||
|
||||
if (fs->wmargin < 0)
|
||||
{
|
||||
/* Truncate the line by overwriting the excess with the
|
||||
newline and anything after it in the buffer. */
|
||||
if (nl < fs->p)
|
||||
{
|
||||
memmove (buf + (r - fs->point_col), nl, fs->p - nl);
|
||||
fs->p -= buf + (r - fs->point_col) - nl;
|
||||
/* Reset point for the next line and start scanning it. */
|
||||
fs->point_col = 0;
|
||||
buf += r + 1; /* Skip full line plus \n. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The buffer ends with a partial line that is beyond the
|
||||
maximum line width. Advance point for the characters
|
||||
written, and discard those past the max from the buffer. */
|
||||
fs->point_col += len;
|
||||
fs->p -= fs->point_col - r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do word wrap. Go to the column just past the maximum line
|
||||
width and scan back for the beginning of the word there.
|
||||
Then insert a line break. */
|
||||
|
||||
char *p, *nextline;
|
||||
int i;
|
||||
|
||||
p = buf + (r + 1 - fs->point_col);
|
||||
while (p >= buf && !isblank (*p))
|
||||
--p;
|
||||
nextline = p + 1; /* This will begin the next line. */
|
||||
|
||||
if (nextline > buf)
|
||||
{
|
||||
/* Swallow separating blanks. */
|
||||
if (p >= buf)
|
||||
do
|
||||
--p;
|
||||
while (p >= buf && isblank (*p));
|
||||
nl = p + 1; /* The newline will replace the first blank. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A single word that is greater than the maximum line width.
|
||||
Oh well. Put it on an overlong line by itself. */
|
||||
p = buf + (r + 1 - fs->point_col);
|
||||
/* Find the end of the long word. */
|
||||
if (p < nl)
|
||||
do
|
||||
++p;
|
||||
while (p < nl && !isblank (*p));
|
||||
if (p == nl)
|
||||
{
|
||||
/* It already ends a line. No fussing required. */
|
||||
fs->point_col = 0;
|
||||
buf = nl + 1;
|
||||
continue;
|
||||
}
|
||||
/* We will move the newline to replace the first blank. */
|
||||
nl = p;
|
||||
/* Swallow separating blanks. */
|
||||
do
|
||||
++p;
|
||||
while (isblank (*p));
|
||||
/* The next line will start here. */
|
||||
nextline = p;
|
||||
}
|
||||
|
||||
/* Note: There are a bunch of tests below for
|
||||
NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall
|
||||
at the end of the buffer, and NEXTLINE is in fact empty (and so
|
||||
we need not be careful to maintain its contents). */
|
||||
|
||||
if ((nextline == buf + len + 1
|
||||
? fs->end - nl < fs->wmargin + 1
|
||||
: nextline - (nl + 1) < fs->wmargin)
|
||||
&& fs->p > nextline)
|
||||
{
|
||||
/* The margin needs more blanks than we removed. */
|
||||
if (fs->end - fs->p > fs->wmargin + 1)
|
||||
/* Make some space for them. */
|
||||
{
|
||||
size_t mv = fs->p - nextline;
|
||||
memmove (nl + 1 + fs->wmargin, nextline, mv);
|
||||
nextline = nl + 1 + fs->wmargin;
|
||||
len = nextline + mv - buf;
|
||||
*nl++ = '\n';
|
||||
}
|
||||
else
|
||||
/* Output the first line so we can use the space. */
|
||||
{
|
||||
#ifdef _LIBC
|
||||
__fxprintf (fs->stream, "%.*s\n",
|
||||
(int) (nl - fs->buf), fs->buf);
|
||||
#else
|
||||
if (nl > fs->buf)
|
||||
fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
|
||||
putc_unlocked ('\n', fs->stream);
|
||||
#endif
|
||||
|
||||
len += buf - fs->buf;
|
||||
nl = buf = fs->buf;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* We can fit the newline and blanks in before
|
||||
the next word. */
|
||||
*nl++ = '\n';
|
||||
|
||||
if (nextline - nl >= fs->wmargin
|
||||
|| (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin))
|
||||
/* Add blanks up to the wrap margin column. */
|
||||
for (i = 0; i < fs->wmargin; ++i)
|
||||
*nl++ = ' ';
|
||||
else
|
||||
for (i = 0; i < fs->wmargin; ++i)
|
||||
#ifdef USE_IN_LIBIO
|
||||
if (_IO_fwide (fs->stream, 0) > 0)
|
||||
putwc_unlocked (L' ', fs->stream);
|
||||
else
|
||||
#endif
|
||||
putc_unlocked (' ', fs->stream);
|
||||
|
||||
/* Copy the tail of the original buffer into the current buffer
|
||||
position. */
|
||||
if (nl < nextline)
|
||||
memmove (nl, nextline, buf + len - nextline);
|
||||
len -= nextline - buf;
|
||||
|
||||
/* Continue the scan on the remaining lines in the buffer. */
|
||||
buf = nl;
|
||||
|
||||
/* Restore bufp to include all the remaining text. */
|
||||
fs->p = nl + len;
|
||||
|
||||
/* Reset the counter of what has been output this line. If wmargin
|
||||
is 0, we want to avoid the lmargin getting added, so we set
|
||||
point_col to a magic value of -1 in that case. */
|
||||
fs->point_col = fs->wmargin ? fs->wmargin : -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember that we've scanned as far as the end of the buffer. */
|
||||
fs->point_offs = fs->p - fs->buf;
|
||||
}
|
||||
|
||||
/* Ensure that FS has space for AMOUNT more bytes in its buffer, either by
|
||||
growing the buffer, or by flushing it. True is returned iff we succeed. */
|
||||
int
|
||||
__argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
|
||||
{
|
||||
if ((size_t) (fs->end - fs->p) < amount)
|
||||
{
|
||||
ssize_t wrote;
|
||||
|
||||
/* Flush FS's buffer. */
|
||||
__argp_fmtstream_update (fs);
|
||||
|
||||
#ifdef _LIBC
|
||||
__fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
|
||||
wrote = fs->p - fs->buf;
|
||||
#else
|
||||
wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
|
||||
#endif
|
||||
if (wrote == fs->p - fs->buf)
|
||||
{
|
||||
fs->p = fs->buf;
|
||||
fs->point_offs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fs->p -= wrote;
|
||||
fs->point_offs -= wrote;
|
||||
memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t) (fs->end - fs->buf) < amount)
|
||||
/* Gotta grow the buffer. */
|
||||
{
|
||||
size_t old_size = fs->end - fs->buf;
|
||||
size_t new_size = old_size + amount;
|
||||
char *new_buf;
|
||||
|
||||
if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size)))
|
||||
{
|
||||
__set_errno (ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fs->buf = new_buf;
|
||||
fs->end = new_buf + new_size;
|
||||
fs->p = fs->buf;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
__argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...)
|
||||
{
|
||||
int out;
|
||||
size_t avail;
|
||||
size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */
|
||||
|
||||
do
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (! __argp_fmtstream_ensure (fs, size_guess))
|
||||
return -1;
|
||||
|
||||
va_start (args, fmt);
|
||||
avail = fs->end - fs->p;
|
||||
out = __vsnprintf (fs->p, avail, fmt, args);
|
||||
va_end (args);
|
||||
if ((size_t) out >= avail)
|
||||
size_guess = out + 1;
|
||||
}
|
||||
while ((size_t) out >= avail);
|
||||
|
||||
fs->p += out;
|
||||
|
||||
return out;
|
||||
}
|
||||
#if 0
|
||||
/* Not exported. */
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */
|
@ -1,301 +0,0 @@
|
||||
/* Word-wrapping and line-truncating streams.
|
||||
Copyright (C) 1997, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* This package emulates glibc `line_wrap_stream' semantics for systems that
|
||||
don't have that. If the system does have it, it is just a wrapper for
|
||||
that. This header file is only used internally while compiling argp, and
|
||||
shouldn't be installed. */
|
||||
|
||||
#ifndef _ARGP_FMTSTREAM_H
|
||||
#define _ARGP_FMTSTREAM_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef __attribute__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
/* The __-protected variants of `format' and `printf' attributes
|
||||
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__
|
||||
# define __format__ format
|
||||
# define __printf__ printf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \
|
||||
|| (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H))
|
||||
/* line_wrap_stream is available, so use that. */
|
||||
#define ARGP_FMTSTREAM_USE_LINEWRAP
|
||||
#endif
|
||||
|
||||
#ifdef ARGP_FMTSTREAM_USE_LINEWRAP
|
||||
/* Just be a simple wrapper for line_wrap_stream; the semantics are
|
||||
*slightly* different, as line_wrap_stream doesn't actually make a new
|
||||
object, it just modifies the given stream (reversibly) to do
|
||||
line-wrapping. Since we control who uses this code, it doesn't matter. */
|
||||
|
||||
#include <linewrap.h>
|
||||
|
||||
typedef FILE *argp_fmtstream_t;
|
||||
|
||||
#define argp_make_fmtstream line_wrap_stream
|
||||
#define __argp_make_fmtstream line_wrap_stream
|
||||
#define argp_fmtstream_free line_unwrap_stream
|
||||
#define __argp_fmtstream_free line_unwrap_stream
|
||||
|
||||
#define __argp_fmtstream_putc(fs,ch) putc(ch,fs)
|
||||
#define argp_fmtstream_putc(fs,ch) putc(ch,fs)
|
||||
#define __argp_fmtstream_puts(fs,str) fputs(str,fs)
|
||||
#define argp_fmtstream_puts(fs,str) fputs(str,fs)
|
||||
#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
|
||||
#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
|
||||
#define __argp_fmtstream_printf fprintf
|
||||
#define argp_fmtstream_printf fprintf
|
||||
|
||||
#define __argp_fmtstream_lmargin line_wrap_lmargin
|
||||
#define argp_fmtstream_lmargin line_wrap_lmargin
|
||||
#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin
|
||||
#define argp_fmtstream_set_lmargin line_wrap_set_lmargin
|
||||
#define __argp_fmtstream_rmargin line_wrap_rmargin
|
||||
#define argp_fmtstream_rmargin line_wrap_rmargin
|
||||
#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin
|
||||
#define argp_fmtstream_set_rmargin line_wrap_set_rmargin
|
||||
#define __argp_fmtstream_wmargin line_wrap_wmargin
|
||||
#define argp_fmtstream_wmargin line_wrap_wmargin
|
||||
#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin
|
||||
#define argp_fmtstream_set_wmargin line_wrap_set_wmargin
|
||||
#define __argp_fmtstream_point line_wrap_point
|
||||
#define argp_fmtstream_point line_wrap_point
|
||||
|
||||
#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
|
||||
/* Guess we have to define our own version. */
|
||||
|
||||
struct argp_fmtstream
|
||||
{
|
||||
FILE *stream; /* The stream we're outputting to. */
|
||||
|
||||
size_t lmargin, rmargin; /* Left and right margins. */
|
||||
ssize_t wmargin; /* Margin to wrap to, or -1 to truncate. */
|
||||
|
||||
/* Point in buffer to which we've processed for wrapping, but not output. */
|
||||
size_t point_offs;
|
||||
/* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin. */
|
||||
ssize_t point_col;
|
||||
|
||||
char *buf; /* Output buffer. */
|
||||
char *p; /* Current end of text in BUF. */
|
||||
char *end; /* Absolute end of BUF. */
|
||||
};
|
||||
|
||||
typedef struct argp_fmtstream *argp_fmtstream_t;
|
||||
|
||||
/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
|
||||
written on it with LMARGIN spaces and limits them to RMARGIN columns
|
||||
total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
|
||||
replacing the whitespace before them with a newline and WMARGIN spaces.
|
||||
Otherwise, chars beyond RMARGIN are simply dropped until a newline.
|
||||
Returns NULL if there was an error. */
|
||||
extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream,
|
||||
size_t __lmargin,
|
||||
size_t __rmargin,
|
||||
ssize_t __wmargin);
|
||||
extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream,
|
||||
size_t __lmargin,
|
||||
size_t __rmargin,
|
||||
ssize_t __wmargin);
|
||||
|
||||
/* Flush __FS to its stream, and free it (but don't close the stream). */
|
||||
extern void __argp_fmtstream_free (argp_fmtstream_t __fs);
|
||||
extern void argp_fmtstream_free (argp_fmtstream_t __fs);
|
||||
|
||||
extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs,
|
||||
const char *__fmt, ...)
|
||||
__attribute__ ((__format__ (printf, 2, 3)));
|
||||
extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
|
||||
const char *__fmt, ...)
|
||||
__attribute__ ((__format__ (printf, 2, 3)));
|
||||
|
||||
extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
|
||||
extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
|
||||
|
||||
extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str);
|
||||
extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str);
|
||||
|
||||
extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs,
|
||||
const char *__str, size_t __len);
|
||||
extern size_t argp_fmtstream_write (argp_fmtstream_t __fs,
|
||||
const char *__str, size_t __len);
|
||||
|
||||
/* Access macros for various bits of state. */
|
||||
#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin)
|
||||
#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin)
|
||||
#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin)
|
||||
#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
|
||||
#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
|
||||
#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
|
||||
|
||||
/* Set __FS's left margin to LMARGIN and return the old value. */
|
||||
extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
|
||||
size_t __lmargin);
|
||||
extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
|
||||
size_t __lmargin);
|
||||
|
||||
/* Set __FS's right margin to __RMARGIN and return the old value. */
|
||||
extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
|
||||
size_t __rmargin);
|
||||
extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
|
||||
size_t __rmargin);
|
||||
|
||||
/* Set __FS's wrap margin to __WMARGIN and return the old value. */
|
||||
extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
|
||||
size_t __wmargin);
|
||||
extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
|
||||
size_t __wmargin);
|
||||
|
||||
/* Return the column number of the current output point in __FS. */
|
||||
extern size_t argp_fmtstream_point (argp_fmtstream_t __fs);
|
||||
extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs);
|
||||
|
||||
/* Internal routines. */
|
||||
extern void _argp_fmtstream_update (argp_fmtstream_t __fs);
|
||||
extern void __argp_fmtstream_update (argp_fmtstream_t __fs);
|
||||
extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
|
||||
extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
/* Inline versions of above routines. */
|
||||
|
||||
#if !_LIBC
|
||||
#define __argp_fmtstream_putc argp_fmtstream_putc
|
||||
#define __argp_fmtstream_puts argp_fmtstream_puts
|
||||
#define __argp_fmtstream_write argp_fmtstream_write
|
||||
#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
|
||||
#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
|
||||
#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
|
||||
#define __argp_fmtstream_point argp_fmtstream_point
|
||||
#define __argp_fmtstream_update _argp_fmtstream_update
|
||||
#define __argp_fmtstream_ensure _argp_fmtstream_ensure
|
||||
#endif
|
||||
|
||||
#ifndef ARGP_FS_EI
|
||||
#define ARGP_FS_EI extern inline
|
||||
#endif
|
||||
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_write (argp_fmtstream_t __fs,
|
||||
const char *__str, size_t __len)
|
||||
{
|
||||
if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
|
||||
{
|
||||
memcpy (__fs->p, __str, __len);
|
||||
__fs->p += __len;
|
||||
return __len;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ARGP_FS_EI int
|
||||
__argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str)
|
||||
{
|
||||
size_t __len = strlen (__str);
|
||||
if (__len)
|
||||
{
|
||||
size_t __wrote = __argp_fmtstream_write (__fs, __str, __len);
|
||||
return __wrote == __len ? 0 : -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ARGP_FS_EI int
|
||||
__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch)
|
||||
{
|
||||
if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1))
|
||||
return *__fs->p++ = __ch;
|
||||
else
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* Set __FS's left margin to __LMARGIN and return the old value. */
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin)
|
||||
{
|
||||
size_t __old;
|
||||
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
|
||||
__argp_fmtstream_update (__fs);
|
||||
__old = __fs->lmargin;
|
||||
__fs->lmargin = __lmargin;
|
||||
return __old;
|
||||
}
|
||||
|
||||
/* Set __FS's right margin to __RMARGIN and return the old value. */
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin)
|
||||
{
|
||||
size_t __old;
|
||||
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
|
||||
__argp_fmtstream_update (__fs);
|
||||
__old = __fs->rmargin;
|
||||
__fs->rmargin = __rmargin;
|
||||
return __old;
|
||||
}
|
||||
|
||||
/* Set FS's wrap margin to __WMARGIN and return the old value. */
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin)
|
||||
{
|
||||
size_t __old;
|
||||
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
|
||||
__argp_fmtstream_update (__fs);
|
||||
__old = __fs->wmargin;
|
||||
__fs->wmargin = __wmargin;
|
||||
return __old;
|
||||
}
|
||||
|
||||
/* Return the column number of the current output point in __FS. */
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_point (argp_fmtstream_t __fs)
|
||||
{
|
||||
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
|
||||
__argp_fmtstream_update (__fs);
|
||||
return __fs->point_col >= 0 ? __fs->point_col : 0;
|
||||
}
|
||||
|
||||
#if !_LIBC
|
||||
#undef __argp_fmtstream_putc
|
||||
#undef __argp_fmtstream_puts
|
||||
#undef __argp_fmtstream_write
|
||||
#undef __argp_fmtstream_set_lmargin
|
||||
#undef __argp_fmtstream_set_rmargin
|
||||
#undef __argp_fmtstream_set_wmargin
|
||||
#undef __argp_fmtstream_point
|
||||
#undef __argp_fmtstream_update
|
||||
#undef __argp_fmtstream_ensure
|
||||
#endif
|
||||
|
||||
#endif /* __OPTIMIZE__ */
|
||||
|
||||
#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */
|
||||
|
||||
#endif /* argp-fmtstream.h */
|
@ -1,43 +0,0 @@
|
||||
/* Real definitions for extern inline functions in argp-fmtstream.h
|
||||
Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#define ARGP_FS_EI
|
||||
#undef __OPTIMIZE__
|
||||
#define __OPTIMIZE__ 1
|
||||
#include "argp-fmtstream.h"
|
||||
|
||||
#if 0
|
||||
/* Not exported. */
|
||||
/* Add weak aliases. */
|
||||
#if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias)
|
||||
|
||||
weak_alias (__argp_fmtstream_putc, argp_fmtstream_putc)
|
||||
weak_alias (__argp_fmtstream_puts, argp_fmtstream_puts)
|
||||
weak_alias (__argp_fmtstream_write, argp_fmtstream_write)
|
||||
weak_alias (__argp_fmtstream_set_lmargin, argp_fmtstream_set_lmargin)
|
||||
weak_alias (__argp_fmtstream_set_rmargin, argp_fmtstream_set_rmargin)
|
||||
weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin)
|
||||
weak_alias (__argp_fmtstream_point, argp_fmtstream_point)
|
||||
|
||||
#endif
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,158 +0,0 @@
|
||||
/* Name frobnication for compiling argp outside of glibc
|
||||
Copyright (C) 1997, 2003, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if !_LIBC
|
||||
/* This code is written for inclusion in gnu-libc, and uses names in the
|
||||
namespace reserved for libc. If we're not compiling in libc, define those
|
||||
names to be the normal ones instead. */
|
||||
|
||||
/* argp-parse functions */
|
||||
#undef __argp_parse
|
||||
#define __argp_parse argp_parse
|
||||
#undef __option_is_end
|
||||
#define __option_is_end _option_is_end
|
||||
#undef __option_is_short
|
||||
#define __option_is_short _option_is_short
|
||||
#undef __argp_input
|
||||
#define __argp_input _argp_input
|
||||
|
||||
/* argp-help functions */
|
||||
#undef __argp_help
|
||||
#define __argp_help argp_help
|
||||
#undef __argp_error
|
||||
#define __argp_error argp_error
|
||||
#undef __argp_failure
|
||||
#define __argp_failure argp_failure
|
||||
#undef __argp_state_help
|
||||
#define __argp_state_help argp_state_help
|
||||
#undef __argp_usage
|
||||
#define __argp_usage argp_usage
|
||||
|
||||
/* argp-fmtstream functions */
|
||||
#undef __argp_make_fmtstream
|
||||
#define __argp_make_fmtstream argp_make_fmtstream
|
||||
#undef __argp_fmtstream_free
|
||||
#define __argp_fmtstream_free argp_fmtstream_free
|
||||
#undef __argp_fmtstream_putc
|
||||
#define __argp_fmtstream_putc argp_fmtstream_putc
|
||||
#undef __argp_fmtstream_puts
|
||||
#define __argp_fmtstream_puts argp_fmtstream_puts
|
||||
#undef __argp_fmtstream_write
|
||||
#define __argp_fmtstream_write argp_fmtstream_write
|
||||
#undef __argp_fmtstream_printf
|
||||
#define __argp_fmtstream_printf argp_fmtstream_printf
|
||||
#undef __argp_fmtstream_set_lmargin
|
||||
#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
|
||||
#undef __argp_fmtstream_set_rmargin
|
||||
#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
|
||||
#undef __argp_fmtstream_set_wmargin
|
||||
#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
|
||||
#undef __argp_fmtstream_point
|
||||
#define __argp_fmtstream_point argp_fmtstream_point
|
||||
#undef __argp_fmtstream_update
|
||||
#define __argp_fmtstream_update _argp_fmtstream_update
|
||||
#undef __argp_fmtstream_ensure
|
||||
#define __argp_fmtstream_ensure _argp_fmtstream_ensure
|
||||
#undef __argp_fmtstream_lmargin
|
||||
#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
|
||||
#undef __argp_fmtstream_rmargin
|
||||
#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
|
||||
#undef __argp_fmtstream_wmargin
|
||||
#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
|
||||
|
||||
/* normal libc functions we call */
|
||||
#undef __flockfile
|
||||
#define __flockfile flockfile
|
||||
#undef __funlockfile
|
||||
#define __funlockfile funlockfile
|
||||
#undef __mempcpy
|
||||
#define __mempcpy mempcpy
|
||||
#undef __sleep
|
||||
#define __sleep sleep
|
||||
#undef __strcasecmp
|
||||
#define __strcasecmp strcasecmp
|
||||
#undef __strchrnul
|
||||
#define __strchrnul strchrnul
|
||||
#undef __strerror_r
|
||||
#define __strerror_r strerror_r
|
||||
#undef __strndup
|
||||
#define __strndup strndup
|
||||
#undef __vsnprintf
|
||||
#define __vsnprintf vsnprintf
|
||||
|
||||
#if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED
|
||||
# define clearerr_unlocked(x) clearerr (x)
|
||||
#endif
|
||||
#if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED
|
||||
# define feof_unlocked(x) feof (x)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED
|
||||
# define ferror_unlocked(x) ferror (x)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED
|
||||
# define fflush_unlocked(x) fflush (x)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED
|
||||
# define fgets_unlocked(x,y,z) fgets (x,y,z)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED
|
||||
# define fputc_unlocked(x,y) fputc (x,y)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED
|
||||
# define fputs_unlocked(x,y) fputs (x,y)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED
|
||||
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED
|
||||
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED
|
||||
# define getc_unlocked(x) getc (x)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED
|
||||
# define getchar_unlocked() getchar ()
|
||||
# endif
|
||||
#if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED
|
||||
# define putc_unlocked(x,y) putc (x,y)
|
||||
# endif
|
||||
#if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED
|
||||
# define putchar_unlocked(x) putchar (x)
|
||||
# endif
|
||||
|
||||
#endif /* !_LIBC */
|
||||
|
||||
#ifndef __set_errno
|
||||
#define __set_errno(e) (errno = (e))
|
||||
#endif
|
||||
|
||||
#if defined GNULIB_ARGP_DISABLE_DIRNAME
|
||||
# define __argp_base_name(arg) arg
|
||||
#elif defined GNULIB_ARGP_EXTERN_BASENAME
|
||||
extern char *__argp_base_name(const char *arg);
|
||||
#else
|
||||
# include "dirname.h"
|
||||
# define __argp_base_name base_name
|
||||
#endif
|
||||
|
||||
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
# define __argp_short_program_name() (program_invocation_short_name)
|
||||
#else
|
||||
extern char *__argp_short_program_name (void);
|
||||
#endif
|
@ -1,953 +0,0 @@
|
||||
/* Hierarchial argument parsing, layered over getopt
|
||||
Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <getopt.h>
|
||||
#include <getopt_int.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <libintl.h>
|
||||
# undef dgettext
|
||||
# define dgettext(domain, msgid) \
|
||||
INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
|
||||
#else
|
||||
# include "gettext.h"
|
||||
#endif
|
||||
#define N_(msgid) msgid
|
||||
|
||||
#include "argp.h"
|
||||
#include "argp-namefrob.h"
|
||||
|
||||
#define alignof(type) offsetof (struct { char c; type x; }, x)
|
||||
#define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d))
|
||||
|
||||
/* Getopt return values. */
|
||||
#define KEY_END (-1) /* The end of the options. */
|
||||
#define KEY_ARG 1 /* A non-option argument. */
|
||||
#define KEY_ERR '?' /* An error parsing the options. */
|
||||
|
||||
/* The meta-argument used to prevent any further arguments being interpreted
|
||||
as options. */
|
||||
#define QUOTE "--"
|
||||
|
||||
/* The number of bits we steal in a long-option value for our own use. */
|
||||
#define GROUP_BITS CHAR_BIT
|
||||
|
||||
/* The number of bits available for the user value. */
|
||||
#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS)
|
||||
#define USER_MASK ((1 << USER_BITS) - 1)
|
||||
|
||||
/* EZ alias for ARGP_ERR_UNKNOWN. */
|
||||
#define EBADKEY ARGP_ERR_UNKNOWN
|
||||
|
||||
/* Default options. */
|
||||
|
||||
/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep
|
||||
for one second intervals, decrementing _ARGP_HANG until it's zero. Thus
|
||||
you can force the program to continue by attaching a debugger and setting
|
||||
it to 0 yourself. */
|
||||
static volatile int _argp_hang;
|
||||
|
||||
#define OPT_PROGNAME -2
|
||||
#define OPT_USAGE -3
|
||||
#define OPT_HANG -4
|
||||
|
||||
static const struct argp_option argp_default_options[] =
|
||||
{
|
||||
{"help", '?', 0, 0, N_("give this help list"), -1},
|
||||
{"usage", OPT_USAGE, 0, 0, N_("give a short usage message"), 0},
|
||||
{"program-name",OPT_PROGNAME,N_("NAME"), OPTION_HIDDEN, N_("set the program name"), 0},
|
||||
{"HANG", OPT_HANG, N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
|
||||
N_("hang for SECS seconds (default 3600)"), 0},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
static error_t
|
||||
argp_default_parser (int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case '?':
|
||||
__argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
|
||||
break;
|
||||
case OPT_USAGE:
|
||||
__argp_state_help (state, state->out_stream,
|
||||
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
|
||||
break;
|
||||
|
||||
case OPT_PROGNAME: /* Set the program name. */
|
||||
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME
|
||||
program_invocation_name = arg;
|
||||
#endif
|
||||
/* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka
|
||||
__PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined
|
||||
to be that, so we have to be a bit careful here.] */
|
||||
|
||||
/* Update what we use for messages. */
|
||||
state->name = __argp_base_name (arg);
|
||||
|
||||
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
program_invocation_short_name = state->name;
|
||||
#endif
|
||||
|
||||
if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS))
|
||||
== ARGP_PARSE_ARGV0)
|
||||
/* Update what getopt uses too. */
|
||||
state->argv[0] = arg;
|
||||
|
||||
break;
|
||||
|
||||
case OPT_HANG:
|
||||
_argp_hang = atoi (arg ? arg : "3600");
|
||||
while (_argp_hang-- > 0)
|
||||
__sleep (1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return EBADKEY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct argp argp_default_argp =
|
||||
{argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"};
|
||||
|
||||
|
||||
static const struct argp_option argp_version_options[] =
|
||||
{
|
||||
{"version", 'V', 0, 0, N_("print program version"), -1},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
static error_t
|
||||
argp_version_parser (int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case 'V':
|
||||
if (argp_program_version_hook)
|
||||
(*argp_program_version_hook) (state->out_stream, state);
|
||||
else if (argp_program_version)
|
||||
fprintf (state->out_stream, "%s\n", argp_program_version);
|
||||
else
|
||||
__argp_error (state, dgettext (state->root_argp->argp_domain,
|
||||
"(PROGRAM ERROR) No version known!?"));
|
||||
if (! (state->flags & ARGP_NO_EXIT))
|
||||
exit (0);
|
||||
break;
|
||||
default:
|
||||
return EBADKEY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct argp argp_version_argp =
|
||||
{argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"};
|
||||
|
||||
/* Returns the offset into the getopt long options array LONG_OPTIONS of a
|
||||
long option with called NAME, or -1 if none is found. Passing NULL as
|
||||
NAME will return the number of options. */
|
||||
static int
|
||||
find_long_option (struct option *long_options, const char *name)
|
||||
{
|
||||
struct option *l = long_options;
|
||||
while (l->name != NULL)
|
||||
if (name != NULL && strcmp (l->name, name) == 0)
|
||||
return l - long_options;
|
||||
else
|
||||
l++;
|
||||
if (name == NULL)
|
||||
return l - long_options;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* The state of a `group' during parsing. Each group corresponds to a
|
||||
particular argp structure from the tree of such descending from the top
|
||||
level argp passed to argp_parse. */
|
||||
struct group
|
||||
{
|
||||
/* This group's parsing function. */
|
||||
argp_parser_t parser;
|
||||
|
||||
/* Which argp this group is from. */
|
||||
const struct argp *argp;
|
||||
|
||||
/* Points to the point in SHORT_OPTS corresponding to the end of the short
|
||||
options for this group. We use it to determine from which group a
|
||||
particular short options is from. */
|
||||
char *short_end;
|
||||
|
||||
/* The number of non-option args sucessfully handled by this parser. */
|
||||
unsigned args_processed;
|
||||
|
||||
/* This group's parser's parent's group. */
|
||||
struct group *parent;
|
||||
unsigned parent_index; /* And the our position in the parent. */
|
||||
|
||||
/* These fields are swapped into and out of the state structure when
|
||||
calling this group's parser. */
|
||||
void *input, **child_inputs;
|
||||
void *hook;
|
||||
};
|
||||
|
||||
/* Call GROUP's parser with KEY and ARG, swapping any group-specific info
|
||||
from STATE before calling, and back into state afterwards. If GROUP has
|
||||
no parser, EBADKEY is returned. */
|
||||
static error_t
|
||||
group_parse (struct group *group, struct argp_state *state, int key, char *arg)
|
||||
{
|
||||
if (group->parser)
|
||||
{
|
||||
error_t err;
|
||||
state->hook = group->hook;
|
||||
state->input = group->input;
|
||||
state->child_inputs = group->child_inputs;
|
||||
state->arg_num = group->args_processed;
|
||||
err = (*group->parser)(key, arg, state);
|
||||
group->hook = state->hook;
|
||||
return err;
|
||||
}
|
||||
else
|
||||
return EBADKEY;
|
||||
}
|
||||
|
||||
struct parser
|
||||
{
|
||||
const struct argp *argp;
|
||||
|
||||
/* SHORT_OPTS is the getopt short options string for the union of all the
|
||||
groups of options. */
|
||||
char *short_opts;
|
||||
/* LONG_OPTS is the array of getop long option structures for the union of
|
||||
all the groups of options. */
|
||||
struct option *long_opts;
|
||||
/* OPT_DATA is the getopt data used for the re-entrant getopt. */
|
||||
struct _getopt_data opt_data;
|
||||
|
||||
/* States of the various parsing groups. */
|
||||
struct group *groups;
|
||||
/* The end of the GROUPS array. */
|
||||
struct group *egroup;
|
||||
/* An vector containing storage for the CHILD_INPUTS field in all groups. */
|
||||
void **child_inputs;
|
||||
|
||||
/* True if we think using getopt is still useful; if false, then
|
||||
remaining arguments are just passed verbatim with ARGP_KEY_ARG. This is
|
||||
cleared whenever getopt returns KEY_END, but may be set again if the user
|
||||
moves the next argument pointer backwards. */
|
||||
int try_getopt;
|
||||
|
||||
/* State block supplied to parsing routines. */
|
||||
struct argp_state state;
|
||||
|
||||
/* Memory used by this parser. */
|
||||
void *storage;
|
||||
};
|
||||
|
||||
/* The next usable entries in the various parser tables being filled in by
|
||||
convert_options. */
|
||||
struct parser_convert_state
|
||||
{
|
||||
struct parser *parser;
|
||||
char *short_end;
|
||||
struct option *long_end;
|
||||
void **child_inputs_end;
|
||||
};
|
||||
|
||||
/* Converts all options in ARGP (which is put in GROUP) and ancestors
|
||||
into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and
|
||||
CVT->LONG_END are the points at which new options are added. Returns the
|
||||
next unused group entry. CVT holds state used during the conversion. */
|
||||
static struct group *
|
||||
convert_options (const struct argp *argp,
|
||||
struct group *parent, unsigned parent_index,
|
||||
struct group *group, struct parser_convert_state *cvt)
|
||||
{
|
||||
/* REAL is the most recent non-alias value of OPT. */
|
||||
const struct argp_option *real = argp->options;
|
||||
const struct argp_child *children = argp->children;
|
||||
|
||||
if (real || argp->parser)
|
||||
{
|
||||
const struct argp_option *opt;
|
||||
|
||||
if (real)
|
||||
for (opt = real; !__option_is_end (opt); opt++)
|
||||
{
|
||||
if (! (opt->flags & OPTION_ALIAS))
|
||||
/* OPT isn't an alias, so we can use values from it. */
|
||||
real = opt;
|
||||
|
||||
if (! (real->flags & OPTION_DOC))
|
||||
/* A real option (not just documentation). */
|
||||
{
|
||||
if (__option_is_short (opt))
|
||||
/* OPT can be used as a short option. */
|
||||
{
|
||||
*cvt->short_end++ = opt->key;
|
||||
if (real->arg)
|
||||
{
|
||||
*cvt->short_end++ = ':';
|
||||
if (real->flags & OPTION_ARG_OPTIONAL)
|
||||
*cvt->short_end++ = ':';
|
||||
}
|
||||
*cvt->short_end = '\0'; /* keep 0 terminated */
|
||||
}
|
||||
|
||||
if (opt->name
|
||||
&& find_long_option (cvt->parser->long_opts, opt->name) < 0)
|
||||
/* OPT can be used as a long option. */
|
||||
{
|
||||
cvt->long_end->name = opt->name;
|
||||
cvt->long_end->has_arg =
|
||||
(real->arg
|
||||
? (real->flags & OPTION_ARG_OPTIONAL
|
||||
? optional_argument
|
||||
: required_argument)
|
||||
: no_argument);
|
||||
cvt->long_end->flag = 0;
|
||||
/* we add a disambiguating code to all the user's
|
||||
values (which is removed before we actually call
|
||||
the function to parse the value); this means that
|
||||
the user loses use of the high 8 bits in all his
|
||||
values (the sign of the lower bits is preserved
|
||||
however)... */
|
||||
cvt->long_end->val =
|
||||
((opt->key | real->key) & USER_MASK)
|
||||
+ (((group - cvt->parser->groups) + 1) << USER_BITS);
|
||||
|
||||
/* Keep the LONG_OPTS list terminated. */
|
||||
(++cvt->long_end)->name = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group->parser = argp->parser;
|
||||
group->argp = argp;
|
||||
group->short_end = cvt->short_end;
|
||||
group->args_processed = 0;
|
||||
group->parent = parent;
|
||||
group->parent_index = parent_index;
|
||||
group->input = 0;
|
||||
group->hook = 0;
|
||||
group->child_inputs = 0;
|
||||
|
||||
if (children)
|
||||
/* Assign GROUP's CHILD_INPUTS field some space from
|
||||
CVT->child_inputs_end.*/
|
||||
{
|
||||
unsigned num_children = 0;
|
||||
while (children[num_children].argp)
|
||||
num_children++;
|
||||
group->child_inputs = cvt->child_inputs_end;
|
||||
cvt->child_inputs_end += num_children;
|
||||
}
|
||||
|
||||
parent = group++;
|
||||
}
|
||||
else
|
||||
parent = 0;
|
||||
|
||||
if (children)
|
||||
{
|
||||
unsigned index = 0;
|
||||
while (children->argp)
|
||||
group =
|
||||
convert_options (children++->argp, parent, index++, group, cvt);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Find the merged set of getopt options, with keys appropiately prefixed. */
|
||||
static void
|
||||
parser_convert (struct parser *parser, const struct argp *argp, int flags)
|
||||
{
|
||||
struct parser_convert_state cvt;
|
||||
|
||||
cvt.parser = parser;
|
||||
cvt.short_end = parser->short_opts;
|
||||
cvt.long_end = parser->long_opts;
|
||||
cvt.child_inputs_end = parser->child_inputs;
|
||||
|
||||
if (flags & ARGP_IN_ORDER)
|
||||
*cvt.short_end++ = '-';
|
||||
else if (flags & ARGP_NO_ARGS)
|
||||
*cvt.short_end++ = '+';
|
||||
*cvt.short_end = '\0';
|
||||
|
||||
cvt.long_end->name = NULL;
|
||||
|
||||
parser->argp = argp;
|
||||
|
||||
if (argp)
|
||||
parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt);
|
||||
else
|
||||
parser->egroup = parser->groups; /* No parsers at all! */
|
||||
}
|
||||
|
||||
/* Lengths of various parser fields which we will allocated. */
|
||||
struct parser_sizes
|
||||
{
|
||||
size_t short_len; /* Getopt short options string. */
|
||||
size_t long_len; /* Getopt long options vector. */
|
||||
size_t num_groups; /* Group structures we allocate. */
|
||||
size_t num_child_inputs; /* Child input slots. */
|
||||
};
|
||||
|
||||
/* For ARGP, increments the NUM_GROUPS field in SZS by the total number of
|
||||
argp structures descended from it, and the SHORT_LEN & LONG_LEN fields by
|
||||
the maximum lengths of the resulting merged getopt short options string and
|
||||
long-options array, respectively. */
|
||||
static void
|
||||
calc_sizes (const struct argp *argp, struct parser_sizes *szs)
|
||||
{
|
||||
const struct argp_child *child = argp->children;
|
||||
const struct argp_option *opt = argp->options;
|
||||
|
||||
if (opt || argp->parser)
|
||||
{
|
||||
szs->num_groups++;
|
||||
if (opt)
|
||||
{
|
||||
int num_opts = 0;
|
||||
while (!__option_is_end (opt++))
|
||||
num_opts++;
|
||||
szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */
|
||||
szs->long_len += num_opts;
|
||||
}
|
||||
}
|
||||
|
||||
if (child)
|
||||
while (child->argp)
|
||||
{
|
||||
calc_sizes ((child++)->argp, szs);
|
||||
szs->num_child_inputs++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes PARSER to parse ARGP in a manner described by FLAGS. */
|
||||
static error_t
|
||||
parser_init (struct parser *parser, const struct argp *argp,
|
||||
int argc, char **argv, int flags, void *input)
|
||||
{
|
||||
error_t err = 0;
|
||||
struct group *group;
|
||||
struct parser_sizes szs;
|
||||
struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
|
||||
char *storage;
|
||||
size_t glen, gsum;
|
||||
size_t clen, csum;
|
||||
size_t llen, lsum;
|
||||
size_t slen, ssum;
|
||||
|
||||
szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
|
||||
szs.long_len = 0;
|
||||
szs.num_groups = 0;
|
||||
szs.num_child_inputs = 0;
|
||||
|
||||
if (argp)
|
||||
calc_sizes (argp, &szs);
|
||||
|
||||
/* Lengths of the various bits of storage used by PARSER. */
|
||||
glen = (szs.num_groups + 1) * sizeof (struct group);
|
||||
clen = szs.num_child_inputs * sizeof (void *);
|
||||
llen = (szs.long_len + 1) * sizeof (struct option);
|
||||
slen = szs.short_len + 1;
|
||||
|
||||
/* Sums of previous lengths, properly aligned. There's no need to
|
||||
align gsum, since struct group is aligned at least as strictly as
|
||||
void * (since it contains a void * member). And there's no need
|
||||
to align lsum, since struct option is aligned at least as
|
||||
strictly as char. */
|
||||
gsum = glen;
|
||||
csum = alignto (gsum + clen, alignof (struct option));
|
||||
lsum = csum + llen;
|
||||
ssum = lsum + slen;
|
||||
|
||||
parser->storage = malloc (ssum);
|
||||
if (! parser->storage)
|
||||
return ENOMEM;
|
||||
|
||||
storage = parser->storage;
|
||||
parser->groups = parser->storage;
|
||||
parser->child_inputs = (void **) (storage + gsum);
|
||||
parser->long_opts = (struct option *) (storage + csum);
|
||||
parser->short_opts = storage + lsum;
|
||||
parser->opt_data = opt_data;
|
||||
|
||||
memset (parser->child_inputs, 0, clen);
|
||||
parser_convert (parser, argp, flags);
|
||||
|
||||
memset (&parser->state, 0, sizeof (struct argp_state));
|
||||
parser->state.root_argp = parser->argp;
|
||||
parser->state.argc = argc;
|
||||
parser->state.argv = argv;
|
||||
parser->state.flags = flags;
|
||||
parser->state.err_stream = stderr;
|
||||
parser->state.out_stream = stdout;
|
||||
parser->state.next = 0; /* Tell getopt to initialize. */
|
||||
parser->state.pstate = parser;
|
||||
|
||||
parser->try_getopt = 1;
|
||||
|
||||
/* Call each parser for the first time, giving it a chance to propagate
|
||||
values to child parsers. */
|
||||
if (parser->groups < parser->egroup)
|
||||
parser->groups->input = input;
|
||||
for (group = parser->groups;
|
||||
group < parser->egroup && (!err || err == EBADKEY);
|
||||
group++)
|
||||
{
|
||||
if (group->parent)
|
||||
/* If a child parser, get the initial input value from the parent. */
|
||||
group->input = group->parent->child_inputs[group->parent_index];
|
||||
|
||||
if (!group->parser
|
||||
&& group->argp->children && group->argp->children->argp)
|
||||
/* For the special case where no parsing function is supplied for an
|
||||
argp, propagate its input to its first child, if any (this just
|
||||
makes very simple wrapper argps more convenient). */
|
||||
group->child_inputs[0] = group->input;
|
||||
|
||||
err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0);
|
||||
}
|
||||
if (err == EBADKEY)
|
||||
err = 0; /* Some parser didn't understand. */
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (parser->state.flags & ARGP_NO_ERRS)
|
||||
{
|
||||
parser->opt_data.opterr = 0;
|
||||
if (parser->state.flags & ARGP_PARSE_ARGV0)
|
||||
/* getopt always skips ARGV[0], so we have to fake it out. As long
|
||||
as OPTERR is 0, then it shouldn't actually try to access it. */
|
||||
parser->state.argv--, parser->state.argc++;
|
||||
}
|
||||
else
|
||||
parser->opt_data.opterr = 1; /* Print error messages. */
|
||||
|
||||
if (parser->state.argv == argv && argv[0])
|
||||
/* There's an argv[0]; use it for messages. */
|
||||
parser->state.name = __argp_base_name (argv[0]);
|
||||
else
|
||||
parser->state.name = __argp_short_program_name ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free any storage consumed by PARSER (but not PARSER itself). */
|
||||
static error_t
|
||||
parser_finalize (struct parser *parser,
|
||||
error_t err, int arg_ebadkey, int *end_index)
|
||||
{
|
||||
struct group *group;
|
||||
|
||||
if (err == EBADKEY && arg_ebadkey)
|
||||
/* Suppress errors generated by unparsed arguments. */
|
||||
err = 0;
|
||||
|
||||
if (! err)
|
||||
{
|
||||
if (parser->state.next == parser->state.argc)
|
||||
/* We successfully parsed all arguments! Call all the parsers again,
|
||||
just a few more times... */
|
||||
{
|
||||
for (group = parser->groups;
|
||||
group < parser->egroup && (!err || err==EBADKEY);
|
||||
group++)
|
||||
if (group->args_processed == 0)
|
||||
err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0);
|
||||
for (group = parser->egroup - 1;
|
||||
group >= parser->groups && (!err || err==EBADKEY);
|
||||
group--)
|
||||
err = group_parse (group, &parser->state, ARGP_KEY_END, 0);
|
||||
|
||||
if (err == EBADKEY)
|
||||
err = 0; /* Some parser didn't understand. */
|
||||
|
||||
/* Tell the user that all arguments are parsed. */
|
||||
if (end_index)
|
||||
*end_index = parser->state.next;
|
||||
}
|
||||
else if (end_index)
|
||||
/* Return any remaining arguments to the user. */
|
||||
*end_index = parser->state.next;
|
||||
else
|
||||
/* No way to return the remaining arguments, they must be bogus. */
|
||||
{
|
||||
if (!(parser->state.flags & ARGP_NO_ERRS)
|
||||
&& parser->state.err_stream)
|
||||
fprintf (parser->state.err_stream,
|
||||
dgettext (parser->argp->argp_domain,
|
||||
"%s: Too many arguments\n"),
|
||||
parser->state.name);
|
||||
err = EBADKEY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Okay, we're all done, with either an error or success; call the parsers
|
||||
to indicate which one. */
|
||||
|
||||
if (err)
|
||||
{
|
||||
/* Maybe print an error message. */
|
||||
if (err == EBADKEY)
|
||||
/* An appropriate message describing what the error was should have
|
||||
been printed earlier. */
|
||||
__argp_state_help (&parser->state, parser->state.err_stream,
|
||||
ARGP_HELP_STD_ERR);
|
||||
|
||||
/* Since we didn't exit, give each parser an error indication. */
|
||||
for (group = parser->groups; group < parser->egroup; group++)
|
||||
group_parse (group, &parser->state, ARGP_KEY_ERROR, 0);
|
||||
}
|
||||
else
|
||||
/* Notify parsers of success, and propagate back values from parsers. */
|
||||
{
|
||||
/* We pass over the groups in reverse order so that child groups are
|
||||
given a chance to do there processing before passing back a value to
|
||||
the parent. */
|
||||
for (group = parser->egroup - 1
|
||||
; group >= parser->groups && (!err || err == EBADKEY)
|
||||
; group--)
|
||||
err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0);
|
||||
if (err == EBADKEY)
|
||||
err = 0; /* Some parser didn't understand. */
|
||||
}
|
||||
|
||||
/* Call parsers once more, to do any final cleanup. Errors are ignored. */
|
||||
for (group = parser->egroup - 1; group >= parser->groups; group--)
|
||||
group_parse (group, &parser->state, ARGP_KEY_FINI, 0);
|
||||
|
||||
if (err == EBADKEY)
|
||||
err = EINVAL;
|
||||
|
||||
free (parser->storage);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Call the user parsers to parse the non-option argument VAL, at the current
|
||||
position, returning any error. The state NEXT pointer is assumed to have
|
||||
been adjusted (by getopt) to point after this argument; this function will
|
||||
adjust it correctly to reflect however many args actually end up being
|
||||
consumed. */
|
||||
static error_t
|
||||
parser_parse_arg (struct parser *parser, char *val)
|
||||
{
|
||||
/* Save the starting value of NEXT, first adjusting it so that the arg
|
||||
we're parsing is again the front of the arg vector. */
|
||||
int index = --parser->state.next;
|
||||
error_t err = EBADKEY;
|
||||
struct group *group;
|
||||
int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */
|
||||
|
||||
/* Try to parse the argument in each parser. */
|
||||
for (group = parser->groups
|
||||
; group < parser->egroup && err == EBADKEY
|
||||
; group++)
|
||||
{
|
||||
parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */
|
||||
key = ARGP_KEY_ARG;
|
||||
err = group_parse (group, &parser->state, key, val);
|
||||
|
||||
if (err == EBADKEY)
|
||||
/* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */
|
||||
{
|
||||
parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */
|
||||
key = ARGP_KEY_ARGS;
|
||||
err = group_parse (group, &parser->state, key, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (! err)
|
||||
{
|
||||
if (key == ARGP_KEY_ARGS)
|
||||
/* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't
|
||||
changed by the user, *all* arguments should be considered
|
||||
consumed. */
|
||||
parser->state.next = parser->state.argc;
|
||||
|
||||
if (parser->state.next > index)
|
||||
/* Remember that we successfully processed a non-option
|
||||
argument -- but only if the user hasn't gotten tricky and set
|
||||
the clock back. */
|
||||
(--group)->args_processed += (parser->state.next - index);
|
||||
else
|
||||
/* The user wants to reparse some args, give getopt another try. */
|
||||
parser->try_getopt = 1;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Call the user parsers to parse the option OPT, with argument VAL, at the
|
||||
current position, returning any error. */
|
||||
static error_t
|
||||
parser_parse_opt (struct parser *parser, int opt, char *val)
|
||||
{
|
||||
/* The group key encoded in the high bits; 0 for short opts or
|
||||
group_number + 1 for long opts. */
|
||||
int group_key = opt >> USER_BITS;
|
||||
error_t err = EBADKEY;
|
||||
|
||||
if (group_key == 0)
|
||||
/* A short option. By comparing OPT's position in SHORT_OPTS to the
|
||||
various starting positions in each group's SHORT_END field, we can
|
||||
determine which group OPT came from. */
|
||||
{
|
||||
struct group *group;
|
||||
char *short_index = strchr (parser->short_opts, opt);
|
||||
|
||||
if (short_index)
|
||||
for (group = parser->groups; group < parser->egroup; group++)
|
||||
if (group->short_end > short_index)
|
||||
{
|
||||
err = group_parse (group, &parser->state, opt,
|
||||
parser->opt_data.optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* A long option. We use shifts instead of masking for extracting
|
||||
the user value in order to preserve the sign. */
|
||||
err =
|
||||
group_parse (&parser->groups[group_key - 1], &parser->state,
|
||||
(opt << GROUP_BITS) >> GROUP_BITS,
|
||||
parser->opt_data.optarg);
|
||||
|
||||
if (err == EBADKEY)
|
||||
/* At least currently, an option not recognized is an error in the
|
||||
parser, because we pre-compute which parser is supposed to deal
|
||||
with each option. */
|
||||
{
|
||||
static const char bad_key_err[] =
|
||||
N_("(PROGRAM ERROR) Option should have been recognized!?");
|
||||
if (group_key == 0)
|
||||
__argp_error (&parser->state, "-%c: %s", opt,
|
||||
dgettext (parser->argp->argp_domain, bad_key_err));
|
||||
else
|
||||
{
|
||||
struct option *long_opt = parser->long_opts;
|
||||
while (long_opt->val != opt && long_opt->name)
|
||||
long_opt++;
|
||||
__argp_error (&parser->state, "--%s: %s",
|
||||
long_opt->name ? long_opt->name : "???",
|
||||
dgettext (parser->argp->argp_domain, bad_key_err));
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Parse the next argument in PARSER (as indicated by PARSER->state.next).
|
||||
Any error from the parsers is returned, and *ARGP_EBADKEY indicates
|
||||
whether a value of EBADKEY is due to an unrecognized argument (which is
|
||||
generally not fatal). */
|
||||
static error_t
|
||||
parser_parse_next (struct parser *parser, int *arg_ebadkey)
|
||||
{
|
||||
int opt;
|
||||
error_t err = 0;
|
||||
|
||||
if (parser->state.quoted && parser->state.next < parser->state.quoted)
|
||||
/* The next argument pointer has been moved to before the quoted
|
||||
region, so pretend we never saw the quoting `--', and give getopt
|
||||
another chance. If the user hasn't removed it, getopt will just
|
||||
process it again. */
|
||||
parser->state.quoted = 0;
|
||||
|
||||
if (parser->try_getopt && !parser->state.quoted)
|
||||
/* Give getopt a chance to parse this. */
|
||||
{
|
||||
/* Put it back in OPTIND for getopt. */
|
||||
parser->opt_data.optind = parser->state.next;
|
||||
/* Distinguish KEY_ERR from a real option. */
|
||||
parser->opt_data.optopt = KEY_END;
|
||||
if (parser->state.flags & ARGP_LONG_ONLY)
|
||||
opt = _getopt_long_only_r (parser->state.argc, parser->state.argv,
|
||||
parser->short_opts, parser->long_opts, 0,
|
||||
&parser->opt_data);
|
||||
else
|
||||
opt = _getopt_long_r (parser->state.argc, parser->state.argv,
|
||||
parser->short_opts, parser->long_opts, 0,
|
||||
&parser->opt_data);
|
||||
/* And see what getopt did. */
|
||||
parser->state.next = parser->opt_data.optind;
|
||||
|
||||
if (opt == KEY_END)
|
||||
/* Getopt says there are no more options, so stop using
|
||||
getopt; we'll continue if necessary on our own. */
|
||||
{
|
||||
parser->try_getopt = 0;
|
||||
if (parser->state.next > 1
|
||||
&& strcmp (parser->state.argv[parser->state.next - 1], QUOTE)
|
||||
== 0)
|
||||
/* Not only is this the end of the options, but it's a
|
||||
`quoted' region, which may have args that *look* like
|
||||
options, so we definitely shouldn't try to use getopt past
|
||||
here, whatever happens. */
|
||||
parser->state.quoted = parser->state.next;
|
||||
}
|
||||
else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END)
|
||||
/* KEY_ERR can have the same value as a valid user short
|
||||
option, but in the case of a real error, getopt sets OPTOPT
|
||||
to the offending character, which can never be KEY_END. */
|
||||
{
|
||||
*arg_ebadkey = 0;
|
||||
return EBADKEY;
|
||||
}
|
||||
}
|
||||
else
|
||||
opt = KEY_END;
|
||||
|
||||
if (opt == KEY_END)
|
||||
{
|
||||
/* We're past what getopt considers the options. */
|
||||
if (parser->state.next >= parser->state.argc
|
||||
|| (parser->state.flags & ARGP_NO_ARGS))
|
||||
/* Indicate that we're done. */
|
||||
{
|
||||
*arg_ebadkey = 1;
|
||||
return EBADKEY;
|
||||
}
|
||||
else
|
||||
/* A non-option arg; simulate what getopt might have done. */
|
||||
{
|
||||
opt = KEY_ARG;
|
||||
parser->opt_data.optarg = parser->state.argv[parser->state.next++];
|
||||
}
|
||||
}
|
||||
|
||||
if (opt == KEY_ARG)
|
||||
/* A non-option argument; try each parser in turn. */
|
||||
err = parser_parse_arg (parser, parser->opt_data.optarg);
|
||||
else
|
||||
err = parser_parse_opt (parser, opt, parser->opt_data.optarg);
|
||||
|
||||
if (err == EBADKEY)
|
||||
*arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Parse the options strings in ARGC & ARGV according to the argp in ARGP.
|
||||
FLAGS is one of the ARGP_ flags above. If END_INDEX is non-NULL, the
|
||||
index in ARGV of the first unparsed option is returned in it. If an
|
||||
unknown option is present, EINVAL is returned; if some parser routine
|
||||
returned a non-zero value, it is returned; otherwise 0 is returned. */
|
||||
error_t
|
||||
__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
|
||||
int *end_index, void *input)
|
||||
{
|
||||
error_t err;
|
||||
struct parser parser;
|
||||
|
||||
/* If true, then err == EBADKEY is a result of a non-option argument failing
|
||||
to be parsed (which in some cases isn't actually an error). */
|
||||
int arg_ebadkey = 0;
|
||||
|
||||
#ifndef _LIBC
|
||||
if (!(flags & ARGP_PARSE_ARGV0))
|
||||
{
|
||||
#ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME
|
||||
if (!program_invocation_name)
|
||||
program_invocation_name = argv[0];
|
||||
#endif
|
||||
#ifdef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
if (!program_invocation_short_name)
|
||||
program_invocation_short_name = __argp_base_name (argv[0]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! (flags & ARGP_NO_HELP))
|
||||
/* Add our own options. */
|
||||
{
|
||||
struct argp_child *child = alloca (4 * sizeof (struct argp_child));
|
||||
struct argp *top_argp = alloca (sizeof (struct argp));
|
||||
|
||||
/* TOP_ARGP has no options, it just serves to group the user & default
|
||||
argps. */
|
||||
memset (top_argp, 0, sizeof (*top_argp));
|
||||
top_argp->children = child;
|
||||
|
||||
memset (child, 0, 4 * sizeof (struct argp_child));
|
||||
|
||||
if (argp)
|
||||
(child++)->argp = argp;
|
||||
(child++)->argp = &argp_default_argp;
|
||||
if (argp_program_version || argp_program_version_hook)
|
||||
(child++)->argp = &argp_version_argp;
|
||||
child->argp = 0;
|
||||
|
||||
argp = top_argp;
|
||||
}
|
||||
|
||||
/* Construct a parser for these arguments. */
|
||||
err = parser_init (&parser, argp, argc, argv, flags, input);
|
||||
|
||||
if (! err)
|
||||
/* Parse! */
|
||||
{
|
||||
while (! err)
|
||||
err = parser_parse_next (&parser, &arg_ebadkey);
|
||||
err = parser_finalize (&parser, err, arg_ebadkey, end_index);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_parse, argp_parse)
|
||||
#endif
|
||||
|
||||
/* Return the input field for ARGP in the parser corresponding to STATE; used
|
||||
by the help routines. */
|
||||
void *
|
||||
__argp_input (const struct argp *argp, const struct argp_state *state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
struct group *group;
|
||||
struct parser *parser = state->pstate;
|
||||
|
||||
for (group = parser->groups; group < parser->egroup; group++)
|
||||
if (group->argp == argp)
|
||||
return group->input;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_input, _argp_input)
|
||||
#endif
|
@ -1,28 +0,0 @@
|
||||
/* Full and short program names for argp module
|
||||
Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
|
||||
char *program_invocation_short_name = 0;
|
||||
#endif
|
||||
#ifndef HAVE_PROGRAM_INVOCATION_NAME
|
||||
char *program_invocation_name = 0;
|
||||
#endif
|
||||
|
@ -1,24 +0,0 @@
|
||||
/* Default definition for ARGP_PROGRAM_VERSION.
|
||||
Copyright (C) 1996, 1997, 1999, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* If set by the user program to a non-zero value, then a default option
|
||||
--version is added (unless the ARGP_NO_HELP flag is used), which will
|
||||
print this string followed by a newline and exit (unless the
|
||||
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
|
||||
const char *argp_program_version;
|
@ -1,31 +0,0 @@
|
||||
/* Default definition for ARGP_PROGRAM_VERSION_HOOK.
|
||||
Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "argp.h"
|
||||
|
||||
/* If set by the user program to a non-zero value, then a default option
|
||||
--version is added (unless the ARGP_NO_HELP flag is used), which calls
|
||||
this function with a stream to print the version to and a pointer to the
|
||||
current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
|
||||
used). This variable takes precedent over ARGP_PROGRAM_VERSION. */
|
||||
void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL;
|
@ -1,43 +0,0 @@
|
||||
/* Real definitions for extern inline functions in argp.h
|
||||
Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined _LIBC || defined HAVE_FEATURES_H
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
#ifndef __USE_EXTERN_INLINES
|
||||
# define __USE_EXTERN_INLINES 1
|
||||
#endif
|
||||
#define ARGP_EI
|
||||
#undef __OPTIMIZE__
|
||||
#define __OPTIMIZE__ 1
|
||||
#include "argp.h"
|
||||
|
||||
/* Add weak aliases. */
|
||||
#if _LIBC - 0 && defined (weak_alias)
|
||||
|
||||
weak_alias (__argp_usage, argp_usage)
|
||||
weak_alias (__option_is_short, _option_is_short)
|
||||
weak_alias (__option_is_end, _option_is_end)
|
||||
|
||||
#endif
|
@ -1,624 +0,0 @@
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/* Hierarchial argument parsing, layered over getopt.
|
||||
Copyright (C) 1995-1999,2003-2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _ARGP_H
|
||||
#define _ARGP_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define __need_error_t
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __THROW
|
||||
# define __THROW
|
||||
#endif
|
||||
#ifndef __NTH
|
||||
# define __NTH(fct) fct __THROW
|
||||
#endif
|
||||
|
||||
#ifndef __attribute__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
/* The __-protected variants of `format' and `printf' attributes
|
||||
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__
|
||||
# define __format__ format
|
||||
# define __printf__ printf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* GCC 2.95 and later have "__restrict"; C99 compilers have
|
||||
"restrict", and "configure" may have defined "restrict".
|
||||
Other compilers use __restrict, __restrict__, and _Restrict, and
|
||||
'configure' might #define 'restrict' to those words. */
|
||||
#ifndef __restrict
|
||||
# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
|
||||
# if 199901L <= __STDC_VERSION__
|
||||
# define __restrict restrict
|
||||
# else
|
||||
# define __restrict
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __error_t_defined
|
||||
typedef int error_t;
|
||||
# define __error_t_defined
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* A description of a particular option. A pointer to an array of
|
||||
these is passed in the OPTIONS field of an argp structure. Each option
|
||||
entry can correspond to one long option and/or one short option; more
|
||||
names for the same option can be added by following an entry in an option
|
||||
array with options having the OPTION_ALIAS flag set. */
|
||||
struct argp_option
|
||||
{
|
||||
/* The long option name. For more than one name for the same option, you
|
||||
can use following options with the OPTION_ALIAS flag set. */
|
||||
const char *name;
|
||||
|
||||
/* What key is returned for this option. If > 0 and printable, then it's
|
||||
also accepted as a short option. */
|
||||
int key;
|
||||
|
||||
/* If non-NULL, this is the name of the argument associated with this
|
||||
option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */
|
||||
const char *arg;
|
||||
|
||||
/* OPTION_ flags. */
|
||||
int flags;
|
||||
|
||||
/* The doc string for this option. If both NAME and KEY are 0, This string
|
||||
will be printed outdented from the normal option column, making it
|
||||
useful as a group header (it will be the first thing printed in its
|
||||
group); in this usage, it's conventional to end the string with a `:'.
|
||||
|
||||
Write the initial value as N_("TEXT") if you want xgettext to collect
|
||||
it into a POT file. */
|
||||
const char *doc;
|
||||
|
||||
/* The group this option is in. In a long help message, options are sorted
|
||||
alphabetically within each group, and the groups presented in the order
|
||||
0, 1, 2, ..., n, -m, ..., -2, -1. Every entry in an options array with
|
||||
if this field 0 will inherit the group number of the previous entry, or
|
||||
zero if it's the first one, unless its a group header (NAME and KEY both
|
||||
0), in which case, the previous entry + 1 is the default. Automagic
|
||||
options such as --help are put into group -1. */
|
||||
int group;
|
||||
};
|
||||
|
||||
/* The argument associated with this option is optional. */
|
||||
#define OPTION_ARG_OPTIONAL 0x1
|
||||
|
||||
/* This option isn't displayed in any help messages. */
|
||||
#define OPTION_HIDDEN 0x2
|
||||
|
||||
/* This option is an alias for the closest previous non-alias option. This
|
||||
means that it will be displayed in the same help entry, and will inherit
|
||||
fields other than NAME and KEY from the aliased option. */
|
||||
#define OPTION_ALIAS 0x4
|
||||
|
||||
/* This option isn't actually an option (and so should be ignored by the
|
||||
actual option parser), but rather an arbitrary piece of documentation that
|
||||
should be displayed in much the same manner as the options. If this flag
|
||||
is set, then the option NAME field is displayed unmodified (e.g., no `--'
|
||||
prefix is added) at the left-margin (where a *short* option would normally
|
||||
be displayed), and the documentation string in the normal place. The NAME
|
||||
field will be translated using gettext, unless OPTION_NO_TRANS is set (see
|
||||
below). For purposes of sorting, any leading whitespace and punctuation is
|
||||
ignored, except that if the first non-whitespace character is not `-', this
|
||||
entry is displayed after all options (and OPTION_DOC entries with a leading
|
||||
`-') in the same group. */
|
||||
#define OPTION_DOC 0x8
|
||||
|
||||
/* This option shouldn't be included in `long' usage messages (but is still
|
||||
included in help messages). This is mainly intended for options that are
|
||||
completely documented in an argp's ARGS_DOC field, in which case including
|
||||
the option in the generic usage list would be redundant. For instance,
|
||||
if ARGS_DOC is "FOO BAR\n-x BLAH", and the `-x' option's purpose is to
|
||||
distinguish these two cases, -x should probably be marked
|
||||
OPTION_NO_USAGE. */
|
||||
#define OPTION_NO_USAGE 0x10
|
||||
|
||||
/* Valid only in conjunction with OPTION_DOC. This option disables translation
|
||||
of option name. */
|
||||
#define OPTION_NO_TRANS 0x20
|
||||
|
||||
|
||||
struct argp; /* fwd declare this type */
|
||||
struct argp_state; /* " */
|
||||
struct argp_child; /* " */
|
||||
|
||||
/* The type of a pointer to an argp parsing function. */
|
||||
typedef error_t (*argp_parser_t) (int key, char *arg,
|
||||
struct argp_state *state);
|
||||
|
||||
/* What to return for unrecognized keys. For special ARGP_KEY_ keys, such
|
||||
returns will simply be ignored. For user keys, this error will be turned
|
||||
into EINVAL (if the call to argp_parse is such that errors are propagated
|
||||
back to the user instead of exiting); returning EINVAL itself would result
|
||||
in an immediate stop to parsing in *all* cases. */
|
||||
#define ARGP_ERR_UNKNOWN E2BIG /* Hurd should never need E2BIG. XXX */
|
||||
|
||||
/* Special values for the KEY argument to an argument parsing function.
|
||||
ARGP_ERR_UNKNOWN should be returned if they aren't understood.
|
||||
|
||||
The sequence of keys to a parsing function is either (where each
|
||||
uppercased word should be prefixed by `ARGP_KEY_' and opt is a user key):
|
||||
|
||||
INIT opt... NO_ARGS END SUCCESS -- No non-option arguments at all
|
||||
or INIT (opt | ARG)... END SUCCESS -- All non-option args parsed
|
||||
or INIT (opt | ARG)... SUCCESS -- Some non-option arg unrecognized
|
||||
|
||||
The third case is where every parser returned ARGP_KEY_UNKNOWN for an
|
||||
argument, in which case parsing stops at that argument (returning the
|
||||
unparsed arguments to the caller of argp_parse if requested, or stopping
|
||||
with an error message if not).
|
||||
|
||||
If an error occurs (either detected by argp, or because the parsing
|
||||
function returned an error value), then the parser is called with
|
||||
ARGP_KEY_ERROR, and no further calls are made. */
|
||||
|
||||
/* This is not an option at all, but rather a command line argument. If a
|
||||
parser receiving this key returns success, the fact is recorded, and the
|
||||
ARGP_KEY_NO_ARGS case won't be used. HOWEVER, if while processing the
|
||||
argument, a parser function decrements the NEXT field of the state it's
|
||||
passed, the option won't be considered processed; this is to allow you to
|
||||
actually modify the argument (perhaps into an option), and have it
|
||||
processed again. */
|
||||
#define ARGP_KEY_ARG 0
|
||||
/* There are remaining arguments not parsed by any parser, which may be found
|
||||
starting at (STATE->argv + STATE->next). If success is returned, but
|
||||
STATE->next left untouched, it's assumed that all arguments were consume,
|
||||
otherwise, the parser should adjust STATE->next to reflect any arguments
|
||||
consumed. */
|
||||
#define ARGP_KEY_ARGS 0x1000006
|
||||
/* There are no more command line arguments at all. */
|
||||
#define ARGP_KEY_END 0x1000001
|
||||
/* Because it's common to want to do some special processing if there aren't
|
||||
any non-option args, user parsers are called with this key if they didn't
|
||||
successfully process any non-option arguments. Called just before
|
||||
ARGP_KEY_END (where more general validity checks on previously parsed
|
||||
arguments can take place). */
|
||||
#define ARGP_KEY_NO_ARGS 0x1000002
|
||||
/* Passed in before any parsing is done. Afterwards, the values of each
|
||||
element of the CHILD_INPUT field, if any, in the state structure is
|
||||
copied to each child's state to be the initial value of the INPUT field. */
|
||||
#define ARGP_KEY_INIT 0x1000003
|
||||
/* Use after all other keys, including SUCCESS & END. */
|
||||
#define ARGP_KEY_FINI 0x1000007
|
||||
/* Passed in when parsing has successfully been completed (even if there are
|
||||
still arguments remaining). */
|
||||
#define ARGP_KEY_SUCCESS 0x1000004
|
||||
/* Passed in if an error occurs. */
|
||||
#define ARGP_KEY_ERROR 0x1000005
|
||||
|
||||
/* An argp structure contains a set of options declarations, a function to
|
||||
deal with parsing one, documentation string, a possible vector of child
|
||||
argp's, and perhaps a function to filter help output. When actually
|
||||
parsing options, getopt is called with the union of all the argp
|
||||
structures chained together through their CHILD pointers, with conflicts
|
||||
being resolved in favor of the first occurrence in the chain. */
|
||||
struct argp
|
||||
{
|
||||
/* An array of argp_option structures, terminated by an entry with both
|
||||
NAME and KEY having a value of 0. */
|
||||
const struct argp_option *options;
|
||||
|
||||
/* What to do with an option from this structure. KEY is the key
|
||||
associated with the option, and ARG is any associated argument (NULL if
|
||||
none was supplied). If KEY isn't understood, ARGP_ERR_UNKNOWN should be
|
||||
returned. If a non-zero, non-ARGP_ERR_UNKNOWN value is returned, then
|
||||
parsing is stopped immediately, and that value is returned from
|
||||
argp_parse(). For special (non-user-supplied) values of KEY, see the
|
||||
ARGP_KEY_ definitions below. */
|
||||
argp_parser_t parser;
|
||||
|
||||
/* A string describing what other arguments are wanted by this program. It
|
||||
is only used by argp_usage to print the `Usage:' message. If it
|
||||
contains newlines, the strings separated by them are considered
|
||||
alternative usage patterns, and printed on separate lines (lines after
|
||||
the first are prefix by ` or: ' instead of `Usage:'). */
|
||||
const char *args_doc;
|
||||
|
||||
/* If non-NULL, a string containing extra text to be printed before and
|
||||
after the options in a long help message (separated by a vertical tab
|
||||
`\v' character).
|
||||
Write the initial value as N_("BEFORE-TEXT") "\v" N_("AFTER-TEXT") if
|
||||
you want xgettext to collect the two pieces of text into a POT file. */
|
||||
const char *doc;
|
||||
|
||||
/* A vector of argp_children structures, terminated by a member with a 0
|
||||
argp field, pointing to child argps should be parsed with this one. Any
|
||||
conflicts are resolved in favor of this argp, or early argps in the
|
||||
CHILDREN list. This field is useful if you use libraries that supply
|
||||
their own argp structure, which you want to use in conjunction with your
|
||||
own. */
|
||||
const struct argp_child *children;
|
||||
|
||||
/* If non-zero, this should be a function to filter the output of help
|
||||
messages. KEY is either a key from an option, in which case TEXT is
|
||||
that option's help text, or a special key from the ARGP_KEY_HELP_
|
||||
defines, below, describing which other help text TEXT is. The function
|
||||
should return either TEXT, if it should be used as-is, a replacement
|
||||
string, which should be malloced, and will be freed by argp, or NULL,
|
||||
meaning `print nothing'. The value for TEXT is *after* any translation
|
||||
has been done, so if any of the replacement text also needs translation,
|
||||
that should be done by the filter function. INPUT is either the input
|
||||
supplied to argp_parse, or NULL, if argp_help was called directly. */
|
||||
char *(*help_filter) (int __key, const char *__text, void *__input);
|
||||
|
||||
/* If non-zero the strings used in the argp library are translated using
|
||||
the domain described by this string. Otherwise the currently installed
|
||||
default domain is used. */
|
||||
const char *argp_domain;
|
||||
};
|
||||
|
||||
/* Possible KEY arguments to a help filter function. */
|
||||
#define ARGP_KEY_HELP_PRE_DOC 0x2000001 /* Help text preceeding options. */
|
||||
#define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */
|
||||
#define ARGP_KEY_HELP_HEADER 0x2000003 /* Option header string. */
|
||||
#define ARGP_KEY_HELP_EXTRA 0x2000004 /* After all other documentation;
|
||||
TEXT is NULL for this key. */
|
||||
/* Explanatory note emitted when duplicate option arguments have been
|
||||
suppressed. */
|
||||
#define ARGP_KEY_HELP_DUP_ARGS_NOTE 0x2000005
|
||||
#define ARGP_KEY_HELP_ARGS_DOC 0x2000006 /* Argument doc string. */
|
||||
|
||||
/* When an argp has a non-zero CHILDREN field, it should point to a vector of
|
||||
argp_child structures, each of which describes a subsidiary argp. */
|
||||
struct argp_child
|
||||
{
|
||||
/* The child parser. */
|
||||
const struct argp *argp;
|
||||
|
||||
/* Flags for this child. */
|
||||
int flags;
|
||||
|
||||
/* If non-zero, an optional header to be printed in help output before the
|
||||
child options. As a side-effect, a non-zero value forces the child
|
||||
options to be grouped together; to achieve this effect without actually
|
||||
printing a header string, use a value of "". */
|
||||
const char *header;
|
||||
|
||||
/* Where to group the child options relative to the other (`consolidated')
|
||||
options in the parent argp; the values are the same as the GROUP field
|
||||
in argp_option structs, but all child-groupings follow parent options at
|
||||
a particular group level. If both this field and HEADER are zero, then
|
||||
they aren't grouped at all, but rather merged with the parent options
|
||||
(merging the child's grouping levels with the parents). */
|
||||
int group;
|
||||
};
|
||||
|
||||
/* Parsing state. This is provided to parsing functions called by argp,
|
||||
which may examine and, as noted, modify fields. */
|
||||
struct argp_state
|
||||
{
|
||||
/* The top level ARGP being parsed. */
|
||||
const struct argp *root_argp;
|
||||
|
||||
/* The argument vector being parsed. May be modified. */
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
/* The index in ARGV of the next arg that to be parsed. May be modified. */
|
||||
int next;
|
||||
|
||||
/* The flags supplied to argp_parse. May be modified. */
|
||||
unsigned flags;
|
||||
|
||||
/* While calling a parsing function with a key of ARGP_KEY_ARG, this is the
|
||||
number of the current arg, starting at zero, and incremented after each
|
||||
such call returns. At all other times, this is the number of such
|
||||
arguments that have been processed. */
|
||||
unsigned arg_num;
|
||||
|
||||
/* If non-zero, the index in ARGV of the first argument following a special
|
||||
`--' argument (which prevents anything following being interpreted as an
|
||||
option). Only set once argument parsing has proceeded past this point. */
|
||||
int quoted;
|
||||
|
||||
/* An arbitrary pointer passed in from the user. */
|
||||
void *input;
|
||||
/* Values to pass to child parsers. This vector will be the same length as
|
||||
the number of children for the current parser. */
|
||||
void **child_inputs;
|
||||
|
||||
/* For the parser's use. Initialized to 0. */
|
||||
void *hook;
|
||||
|
||||
/* The name used when printing messages. This is initialized to ARGV[0],
|
||||
or PROGRAM_INVOCATION_NAME if that is unavailable. */
|
||||
char *name;
|
||||
|
||||
/* Streams used when argp prints something. */
|
||||
FILE *err_stream; /* For errors; initialized to stderr. */
|
||||
FILE *out_stream; /* For information; initialized to stdout. */
|
||||
|
||||
void *pstate; /* Private, for use by argp. */
|
||||
};
|
||||
|
||||
/* Flags for argp_parse (note that the defaults are those that are
|
||||
convenient for program command line parsing): */
|
||||
|
||||
/* Don't ignore the first element of ARGV. Normally (and always unless
|
||||
ARGP_NO_ERRS is set) the first element of the argument vector is
|
||||
skipped for option parsing purposes, as it corresponds to the program name
|
||||
in a command line. */
|
||||
#define ARGP_PARSE_ARGV0 0x01
|
||||
|
||||
/* Don't print error messages for unknown options to stderr; unless this flag
|
||||
is set, ARGP_PARSE_ARGV0 is ignored, as ARGV[0] is used as the program
|
||||
name in the error messages. This flag implies ARGP_NO_EXIT (on the
|
||||
assumption that silent exiting upon errors is bad behaviour). */
|
||||
#define ARGP_NO_ERRS 0x02
|
||||
|
||||
/* Don't parse any non-option args. Normally non-option args are parsed by
|
||||
calling the parse functions with a key of ARGP_KEY_ARG, and the actual arg
|
||||
as the value. Since it's impossible to know which parse function wants to
|
||||
handle it, each one is called in turn, until one returns 0 or an error
|
||||
other than ARGP_ERR_UNKNOWN; if an argument is handled by no one, the
|
||||
argp_parse returns prematurely (but with a return value of 0). If all
|
||||
args have been parsed without error, all parsing functions are called one
|
||||
last time with a key of ARGP_KEY_END. This flag needn't normally be set,
|
||||
as the normal behavior is to stop parsing as soon as some argument can't
|
||||
be handled. */
|
||||
#define ARGP_NO_ARGS 0x04
|
||||
|
||||
/* Parse options and arguments in the same order they occur on the command
|
||||
line -- normally they're rearranged so that all options come first. */
|
||||
#define ARGP_IN_ORDER 0x08
|
||||
|
||||
/* Don't provide the standard long option --help, which causes usage and
|
||||
option help information to be output to stdout, and exit (0) called. */
|
||||
#define ARGP_NO_HELP 0x10
|
||||
|
||||
/* Don't exit on errors (they may still result in error messages). */
|
||||
#define ARGP_NO_EXIT 0x20
|
||||
|
||||
/* Use the gnu getopt `long-only' rules for parsing arguments. */
|
||||
#define ARGP_LONG_ONLY 0x40
|
||||
|
||||
/* Turns off any message-printing/exiting options. */
|
||||
#define ARGP_SILENT (ARGP_NO_EXIT | ARGP_NO_ERRS | ARGP_NO_HELP)
|
||||
|
||||
/* Parse the options strings in ARGC & ARGV according to the options in ARGP.
|
||||
FLAGS is one of the ARGP_ flags above. If ARG_INDEX is non-NULL, the
|
||||
index in ARGV of the first unparsed option is returned in it. If an
|
||||
unknown option is present, ARGP_ERR_UNKNOWN is returned; if some parser
|
||||
routine returned a non-zero value, it is returned; otherwise 0 is
|
||||
returned. This function may also call exit unless the ARGP_NO_HELP flag
|
||||
is set. INPUT is a pointer to a value to be passed in to the parser. */
|
||||
extern error_t argp_parse (const struct argp *__restrict __argp,
|
||||
int /*argc*/, char **__restrict /*argv*/,
|
||||
unsigned __flags, int *__restrict __arg_index,
|
||||
void *__restrict __input);
|
||||
extern error_t __argp_parse (const struct argp *__restrict __argp,
|
||||
int /*argc*/, char **__restrict /*argv*/,
|
||||
unsigned __flags, int *__restrict __arg_index,
|
||||
void *__restrict __input);
|
||||
|
||||
/* Global variables. */
|
||||
|
||||
/* GNULIB makes sure both program_invocation_name and
|
||||
program_invocation_short_name are available */
|
||||
#ifdef GNULIB_PROGRAM_INVOCATION_NAME
|
||||
extern char *program_invocation_name;
|
||||
# undef HAVE_DECL_PROGRAM_INVOCATION_NAME
|
||||
# define HAVE_DECL_PROGRAM_INVOCATION_NAME 1
|
||||
#endif
|
||||
|
||||
#ifdef GNULIB_PROGRAM_INVOCATION_SHORT_NAME
|
||||
extern char *program_invocation_short_name;
|
||||
# undef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
# define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 1
|
||||
#endif
|
||||
|
||||
/* If defined or set by the user program to a non-zero value, then a default
|
||||
option --version is added (unless the ARGP_NO_HELP flag is used), which
|
||||
will print this string followed by a newline and exit (unless the
|
||||
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
|
||||
extern const char *argp_program_version;
|
||||
|
||||
/* If defined or set by the user program to a non-zero value, then a default
|
||||
option --version is added (unless the ARGP_NO_HELP flag is used), which
|
||||
calls this function with a stream to print the version to and a pointer to
|
||||
the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
|
||||
used). This variable takes precedent over ARGP_PROGRAM_VERSION. */
|
||||
extern void (*argp_program_version_hook) (FILE *__restrict __stream,
|
||||
struct argp_state *__restrict
|
||||
__state);
|
||||
|
||||
/* If defined or set by the user program, it should point to string that is
|
||||
the bug-reporting address for the program. It will be printed by
|
||||
argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various
|
||||
standard help messages), embedded in a sentence that says something like
|
||||
`Report bugs to ADDR.'. */
|
||||
extern const char *argp_program_bug_address;
|
||||
|
||||
/* The exit status that argp will use when exiting due to a parsing error.
|
||||
If not defined or set by the user program, this defaults to EX_USAGE from
|
||||
<sysexits.h>. */
|
||||
extern error_t argp_err_exit_status;
|
||||
|
||||
/* Flags for argp_help. */
|
||||
#define ARGP_HELP_USAGE 0x01 /* a Usage: message. */
|
||||
#define ARGP_HELP_SHORT_USAGE 0x02 /* " but don't actually print options. */
|
||||
#define ARGP_HELP_SEE 0x04 /* a `Try ... for more help' message. */
|
||||
#define ARGP_HELP_LONG 0x08 /* a long help message. */
|
||||
#define ARGP_HELP_PRE_DOC 0x10 /* doc string preceding long help. */
|
||||
#define ARGP_HELP_POST_DOC 0x20 /* doc string following long help. */
|
||||
#define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
|
||||
#define ARGP_HELP_BUG_ADDR 0x40 /* bug report address */
|
||||
#define ARGP_HELP_LONG_ONLY 0x80 /* modify output appropriately to
|
||||
reflect ARGP_LONG_ONLY mode. */
|
||||
|
||||
/* These ARGP_HELP flags are only understood by argp_state_help. */
|
||||
#define ARGP_HELP_EXIT_ERR 0x100 /* Call exit(1) instead of returning. */
|
||||
#define ARGP_HELP_EXIT_OK 0x200 /* Call exit(0) instead of returning. */
|
||||
|
||||
/* The standard thing to do after a program command line parsing error, if an
|
||||
error message has already been printed. */
|
||||
#define ARGP_HELP_STD_ERR \
|
||||
(ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
|
||||
/* The standard thing to do after a program command line parsing error, if no
|
||||
more specific error message has been printed. */
|
||||
#define ARGP_HELP_STD_USAGE \
|
||||
(ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
|
||||
/* The standard thing to do in response to a --help option. */
|
||||
#define ARGP_HELP_STD_HELP \
|
||||
(ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
|
||||
| ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
|
||||
|
||||
/* Output a usage message for ARGP to STREAM. FLAGS are from the set
|
||||
ARGP_HELP_*. */
|
||||
extern void argp_help (const struct argp *__restrict __argp,
|
||||
FILE *__restrict __stream,
|
||||
unsigned __flags, char *__restrict __name);
|
||||
extern void __argp_help (const struct argp *__restrict __argp,
|
||||
FILE *__restrict __stream, unsigned __flags,
|
||||
char *__name);
|
||||
|
||||
/* The following routines are intended to be called from within an argp
|
||||
parsing routine (thus taking an argp_state structure as the first
|
||||
argument). They may or may not print an error message and exit, depending
|
||||
on the flags in STATE -- in any case, the caller should be prepared for
|
||||
them *not* to exit, and should return an appropiate error after calling
|
||||
them. [argp_usage & argp_error should probably be called argp_state_...,
|
||||
but they're used often enough that they should be short] */
|
||||
|
||||
/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are
|
||||
from the set ARGP_HELP_*. */
|
||||
extern void argp_state_help (const struct argp_state *__restrict __state,
|
||||
FILE *__restrict __stream,
|
||||
unsigned int __flags);
|
||||
extern void __argp_state_help (const struct argp_state *__restrict __state,
|
||||
FILE *__restrict __stream,
|
||||
unsigned int __flags);
|
||||
|
||||
/* Possibly output the standard usage message for ARGP to stderr and exit. */
|
||||
extern void argp_usage (const struct argp_state *__state);
|
||||
extern void __argp_usage (const struct argp_state *__state);
|
||||
|
||||
/* If appropriate, print the printf string FMT and following args, preceded
|
||||
by the program name and `:', to stderr, and followed by a `Try ... --help'
|
||||
message, then exit (1). */
|
||||
extern void argp_error (const struct argp_state *__restrict __state,
|
||||
const char *__restrict __fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
extern void __argp_error (const struct argp_state *__restrict __state,
|
||||
const char *__restrict __fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
|
||||
/* Similar to the standard gnu error-reporting function error(), but will
|
||||
respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
|
||||
to STATE->err_stream. This is useful for argument parsing code that is
|
||||
shared between program startup (when exiting is desired) and runtime
|
||||
option parsing (when typically an error code is returned instead). The
|
||||
difference between this function and argp_error is that the latter is for
|
||||
*parsing errors*, and the former is for other problems that occur during
|
||||
parsing but don't reflect a (syntactic) problem with the input. */
|
||||
extern void argp_failure (const struct argp_state *__restrict __state,
|
||||
int __status, int __errnum,
|
||||
const char *__restrict __fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 4, 5)));
|
||||
extern void __argp_failure (const struct argp_state *__restrict __state,
|
||||
int __status, int __errnum,
|
||||
const char *__restrict __fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 4, 5)));
|
||||
|
||||
/* Returns true if the option OPT is a valid short option. */
|
||||
extern int _option_is_short (const struct argp_option *__opt) __THROW;
|
||||
extern int __option_is_short (const struct argp_option *__opt) __THROW;
|
||||
|
||||
/* Returns true if the option OPT is in fact the last (unused) entry in an
|
||||
options array. */
|
||||
extern int _option_is_end (const struct argp_option *__opt) __THROW;
|
||||
extern int __option_is_end (const struct argp_option *__opt) __THROW;
|
||||
|
||||
/* Return the input field for ARGP in the parser corresponding to STATE; used
|
||||
by the help routines. */
|
||||
extern void *_argp_input (const struct argp *__restrict __argp,
|
||||
const struct argp_state *__restrict __state)
|
||||
__THROW;
|
||||
extern void *__argp_input (const struct argp *__restrict __argp,
|
||||
const struct argp_state *__restrict __state)
|
||||
__THROW;
|
||||
|
||||
#ifdef __USE_EXTERN_INLINES
|
||||
|
||||
# if !_LIBC
|
||||
# define __argp_usage argp_usage
|
||||
# define __argp_state_help argp_state_help
|
||||
# define __option_is_short _option_is_short
|
||||
# define __option_is_end _option_is_end
|
||||
# endif
|
||||
|
||||
# ifndef ARGP_EI
|
||||
# define ARGP_EI extern __inline__
|
||||
# endif
|
||||
|
||||
ARGP_EI void
|
||||
__argp_usage (const struct argp_state *__state)
|
||||
{
|
||||
__argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE);
|
||||
}
|
||||
|
||||
ARGP_EI int
|
||||
__NTH (__option_is_short (const struct argp_option *__opt))
|
||||
{
|
||||
if (__opt->flags & OPTION_DOC)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
int __key = __opt->key;
|
||||
return __key > 0 && __key <= UCHAR_MAX && isprint (__key);
|
||||
}
|
||||
}
|
||||
|
||||
ARGP_EI int
|
||||
__NTH (__option_is_end (const struct argp_option *__opt))
|
||||
{
|
||||
return !__opt->key && !__opt->name && !__opt->doc && !__opt->group;
|
||||
}
|
||||
|
||||
# if !_LIBC
|
||||
# undef __argp_usage
|
||||
# undef __argp_state_help
|
||||
# undef __option_is_short
|
||||
# undef __option_is_end
|
||||
# endif
|
||||
#endif /* Use extern inlines. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* argp.h */
|
@ -1,129 +0,0 @@
|
||||
/* basename.c -- return the last element in a file name
|
||||
|
||||
Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "dirname.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "xalloc.h"
|
||||
#include "xstrndup.h"
|
||||
|
||||
/* Return the address of the last file name component of NAME. If
|
||||
NAME has no relative file name components because it is a file
|
||||
system root, return the empty string. */
|
||||
|
||||
char *
|
||||
last_component (char const *name)
|
||||
{
|
||||
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
|
||||
char const *p;
|
||||
bool saw_slash = false;
|
||||
|
||||
while (ISSLASH (*base))
|
||||
base++;
|
||||
|
||||
for (p = base; *p; p++)
|
||||
{
|
||||
if (ISSLASH (*p))
|
||||
saw_slash = true;
|
||||
else if (saw_slash)
|
||||
{
|
||||
base = p;
|
||||
saw_slash = false;
|
||||
}
|
||||
}
|
||||
|
||||
return (char *) base;
|
||||
}
|
||||
|
||||
|
||||
/* In general, we can't use the builtin `basename' function if available,
|
||||
since it has different meanings in different environments.
|
||||
In some environments the builtin `basename' modifies its argument.
|
||||
|
||||
Return the last file name component of NAME, allocated with
|
||||
xmalloc. On systems with drive letters, a leading "./"
|
||||
distinguishes relative names that would otherwise look like a drive
|
||||
letter. Unlike POSIX basename(), NAME cannot be NULL,
|
||||
base_name("") returns "", and the first trailing slash is not
|
||||
stripped.
|
||||
|
||||
If lstat (NAME) would succeed, then { chdir (dir_name (NAME));
|
||||
lstat (base_name (NAME)); } will access the same file. Likewise,
|
||||
if the sequence { chdir (dir_name (NAME));
|
||||
rename (base_name (NAME), "foo"); } succeeds, you have renamed NAME
|
||||
to "foo" in the same directory NAME was in. */
|
||||
|
||||
char *
|
||||
base_name (char const *name)
|
||||
{
|
||||
char const *base = last_component (name);
|
||||
size_t length;
|
||||
|
||||
/* If there is no last component, then name is a file system root or the
|
||||
empty string. */
|
||||
if (! *base)
|
||||
return xstrndup (name, base_len (name));
|
||||
|
||||
/* Collapse a sequence of trailing slashes into one. */
|
||||
length = base_len (base);
|
||||
if (ISSLASH (base[length]))
|
||||
length++;
|
||||
|
||||
/* On systems with drive letters, `a/b:c' must return `./b:c' rather
|
||||
than `b:c' to avoid confusion with a drive letter. On systems
|
||||
with pure POSIX semantics, this is not an issue. */
|
||||
if (FILE_SYSTEM_PREFIX_LEN (base))
|
||||
{
|
||||
char *p = xmalloc (length + 3);
|
||||
p[0] = '.';
|
||||
p[1] = '/';
|
||||
memcpy (p + 2, base, length);
|
||||
p[length + 2] = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Finally, copy the basename. */
|
||||
return xstrndup (base, length);
|
||||
}
|
||||
|
||||
/* Return the length of the basename NAME. Typically NAME is the
|
||||
value returned by base_name or last_component. Act like strlen
|
||||
(NAME), except omit all trailing slashes. */
|
||||
|
||||
size_t
|
||||
base_len (char const *name)
|
||||
{
|
||||
size_t len;
|
||||
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
|
||||
|
||||
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
|
||||
continue;
|
||||
|
||||
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
|
||||
&& ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
|
||||
return 2;
|
||||
|
||||
if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
|
||||
&& len == prefix_len && ISSLASH (name[prefix_len]))
|
||||
return prefix_len + 1;
|
||||
|
||||
return len;
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/* dirname.c -- return all but the last element in a file name
|
||||
|
||||
Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "dirname.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Return the length of the prefix of FILE that will be used by
|
||||
dir_name. If FILE is in the working directory, this returns zero
|
||||
even though `dir_name (FILE)' will return ".". Works properly even
|
||||
if there are trailing slashes (by effectively ignoring them). */
|
||||
|
||||
size_t
|
||||
dir_len (char const *file)
|
||||
{
|
||||
size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
|
||||
size_t length;
|
||||
|
||||
/* Advance prefix_length beyond important leading slashes. */
|
||||
prefix_length += (prefix_length != 0
|
||||
? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
&& ISSLASH (file[prefix_length]))
|
||||
: (ISSLASH (file[0])
|
||||
? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||
&& ISSLASH (file[1]) && ! ISSLASH (file[2])
|
||||
? 2 : 1))
|
||||
: 0));
|
||||
|
||||
/* Strip the basename and any redundant slashes before it. */
|
||||
for (length = last_component (file) - file;
|
||||
prefix_length < length; length--)
|
||||
if (! ISSLASH (file[length - 1]))
|
||||
break;
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/* In general, we can't use the builtin `dirname' function if available,
|
||||
since it has different meanings in different environments.
|
||||
In some environments the builtin `dirname' modifies its argument.
|
||||
|
||||
Return the leading directories part of FILE, allocated with xmalloc.
|
||||
Works properly even if there are trailing slashes (by effectively
|
||||
ignoring them). Unlike POSIX dirname(), FILE cannot be NULL.
|
||||
|
||||
If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
|
||||
lstat (base_name (FILE)); } will access the same file. Likewise,
|
||||
if the sequence { chdir (dir_name (FILE));
|
||||
rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
|
||||
to "foo" in the same directory FILE was in. */
|
||||
|
||||
char *
|
||||
dir_name (char const *file)
|
||||
{
|
||||
size_t length = dir_len (file);
|
||||
bool append_dot = (length == 0
|
||||
|| (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
&& length == FILE_SYSTEM_PREFIX_LEN (file)
|
||||
&& file[2] != '\0' && ! ISSLASH (file[2])));
|
||||
char *dir = xmalloc (length + append_dot + 1);
|
||||
memcpy (dir, file, length);
|
||||
if (append_dot)
|
||||
dir[length++] = '.';
|
||||
dir[length] = '\0';
|
||||
return dir;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/* Take file names apart into directory and base names.
|
||||
|
||||
Copyright (C) 1998, 2001, 2003-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef DIRNAME_H_
|
||||
# define DIRNAME_H_ 1
|
||||
|
||||
# include <stdbool.h>
|
||||
# include <stddef.h>
|
||||
|
||||
# ifndef DIRECTORY_SEPARATOR
|
||||
# define DIRECTORY_SEPARATOR '/'
|
||||
# endif
|
||||
|
||||
# ifndef ISSLASH
|
||||
# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
|
||||
# endif
|
||||
|
||||
# ifndef FILE_SYSTEM_PREFIX_LEN
|
||||
# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
|
||||
/* This internal macro assumes ASCII, but all hosts that support drive
|
||||
letters use ASCII. */
|
||||
# define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \
|
||||
<= 'z' - 'a')
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) \
|
||||
(_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
|
||||
# else
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
|
||||
# endif
|
||||
|
||||
# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
|
||||
# endif
|
||||
|
||||
# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
|
||||
# else
|
||||
# define IS_ABSOLUTE_FILE_NAME(F) \
|
||||
(ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F))
|
||||
# endif
|
||||
# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
|
||||
|
||||
char *base_name (char const *file);
|
||||
char *dir_name (char const *file);
|
||||
size_t base_len (char const *file);
|
||||
size_t dir_len (char const *file);
|
||||
char *last_component (char const *file);
|
||||
|
||||
bool strip_trailing_slashes (char *file);
|
||||
|
||||
#endif /* not DIRNAME_H_ */
|
@ -1,338 +0,0 @@
|
||||
/* Error handler for noninteractive utilities
|
||||
Copyright (C) 1990-1998, 2000-2005, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#if !_LIBC
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !_LIBC && ENABLE_NLS
|
||||
# include "gettext.h"
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <libintl.h>
|
||||
# include <stdbool.h>
|
||||
# include <stdint.h>
|
||||
# include <wchar.h>
|
||||
# define mbsrtowcs __mbsrtowcs
|
||||
#endif
|
||||
|
||||
#if USE_UNLOCKED_IO
|
||||
# include "unlocked-io.h"
|
||||
#endif
|
||||
|
||||
#ifndef _
|
||||
# define _(String) String
|
||||
#endif
|
||||
|
||||
/* If NULL, error will flush stdout, then print on stderr the program
|
||||
name, a colon and a space. Otherwise, error will call this
|
||||
function without parameters instead. */
|
||||
void (*error_print_progname) (void);
|
||||
|
||||
/* This variable is incremented each time `error' is called. */
|
||||
unsigned int error_message_count;
|
||||
|
||||
#ifdef _LIBC
|
||||
/* In the GNU C library, there is a predefined variable for this. */
|
||||
|
||||
# define program_name program_invocation_name
|
||||
# include <errno.h>
|
||||
# include <limits.h>
|
||||
# include <libio/libioP.h>
|
||||
|
||||
/* In GNU libc we want do not want to use the common name `error' directly.
|
||||
Instead make it a weak alias. */
|
||||
extern void __error (int status, int errnum, const char *message, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
extern void __error_at_line (int status, int errnum, const char *file_name,
|
||||
unsigned int line_number, const char *message,
|
||||
...)
|
||||
__attribute__ ((__format__ (__printf__, 5, 6)));;
|
||||
# define error __error
|
||||
# define error_at_line __error_at_line
|
||||
|
||||
# include <libio/iolibio.h>
|
||||
# define fflush(s) INTUSE(_IO_fflush) (s)
|
||||
# undef putc
|
||||
# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
|
||||
|
||||
# include <bits/libc-lock.h>
|
||||
|
||||
#else /* not _LIBC */
|
||||
|
||||
# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
|
||||
# ifndef HAVE_DECL_STRERROR_R
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
char *strerror_r ();
|
||||
# endif
|
||||
|
||||
/* The calling program should define program_name and set it to the
|
||||
name of the executing program. */
|
||||
extern char *program_name;
|
||||
|
||||
# if HAVE_STRERROR_R || defined strerror_r
|
||||
# define __strerror_r strerror_r
|
||||
# endif /* HAVE_STRERROR_R || defined strerror_r */
|
||||
#endif /* not _LIBC */
|
||||
|
||||
static void
|
||||
print_errno_message (int errnum)
|
||||
{
|
||||
char const *s;
|
||||
|
||||
#if defined HAVE_STRERROR_R || _LIBC
|
||||
char errbuf[1024];
|
||||
# if STRERROR_R_CHAR_P || _LIBC
|
||||
s = __strerror_r (errnum, errbuf, sizeof errbuf);
|
||||
# else
|
||||
if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
|
||||
s = errbuf;
|
||||
else
|
||||
s = 0;
|
||||
# endif
|
||||
#else
|
||||
s = strerror (errnum);
|
||||
#endif
|
||||
|
||||
#if !_LIBC
|
||||
if (! s)
|
||||
s = _("Unknown system error");
|
||||
#endif
|
||||
|
||||
#if _LIBC
|
||||
__fxprintf (NULL, ": %s", s);
|
||||
#else
|
||||
fprintf (stderr, ": %s", s);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
error_tail (int status, int errnum, const char *message, va_list args)
|
||||
{
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
{
|
||||
# define ALLOCA_LIMIT 2000
|
||||
size_t len = strlen (message) + 1;
|
||||
wchar_t *wmessage = NULL;
|
||||
mbstate_t st;
|
||||
size_t res;
|
||||
const char *tmp;
|
||||
bool use_malloc = false;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (__libc_use_alloca (len * sizeof (wchar_t)))
|
||||
wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
|
||||
else
|
||||
{
|
||||
if (!use_malloc)
|
||||
wmessage = NULL;
|
||||
|
||||
wchar_t *p = (wchar_t *) realloc (wmessage,
|
||||
len * sizeof (wchar_t));
|
||||
if (p == NULL)
|
||||
{
|
||||
free (wmessage);
|
||||
fputws_unlocked (L"out of memory\n", stderr);
|
||||
return;
|
||||
}
|
||||
wmessage = p;
|
||||
use_malloc = true;
|
||||
}
|
||||
|
||||
memset (&st, '\0', sizeof (st));
|
||||
tmp = message;
|
||||
|
||||
res = mbsrtowcs (wmessage, &tmp, len, &st);
|
||||
if (res != len)
|
||||
break;
|
||||
|
||||
if (__builtin_expect (len >= SIZE_MAX / 2, 0))
|
||||
{
|
||||
/* This really should not happen if everything is fine. */
|
||||
res = (size_t) -1;
|
||||
break;
|
||||
}
|
||||
|
||||
len *= 2;
|
||||
}
|
||||
|
||||
if (res == (size_t) -1)
|
||||
{
|
||||
/* The string cannot be converted. */
|
||||
if (use_malloc)
|
||||
{
|
||||
free (wmessage);
|
||||
use_malloc = false;
|
||||
}
|
||||
wmessage = (wchar_t *) L"???";
|
||||
}
|
||||
|
||||
__vfwprintf (stderr, wmessage, args);
|
||||
|
||||
if (use_malloc)
|
||||
free (wmessage);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
vfprintf (stderr, message, args);
|
||||
va_end (args);
|
||||
|
||||
++error_message_count;
|
||||
if (errnum)
|
||||
print_errno_message (errnum);
|
||||
#if _LIBC
|
||||
__fxprintf (NULL, "\n");
|
||||
#else
|
||||
putc ('\n', stderr);
|
||||
#endif
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
exit (status);
|
||||
}
|
||||
|
||||
|
||||
/* 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. */
|
||||
void
|
||||
error (int status, int errnum, const char *message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
#if defined _LIBC && defined __libc_ptf_call
|
||||
/* We do not want this call to be cut short by a thread
|
||||
cancellation. Therefore disable cancellation for now. */
|
||||
int state = PTHREAD_CANCEL_ENABLE;
|
||||
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
|
||||
0);
|
||||
#endif
|
||||
|
||||
fflush (stdout);
|
||||
#ifdef _LIBC
|
||||
_IO_flockfile (stderr);
|
||||
#endif
|
||||
if (error_print_progname)
|
||||
(*error_print_progname) ();
|
||||
else
|
||||
{
|
||||
#if _LIBC
|
||||
__fxprintf (NULL, "%s: ", program_name);
|
||||
#else
|
||||
fprintf (stderr, "%s: ", program_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
va_start (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
|
||||
#ifdef _LIBC
|
||||
_IO_funlockfile (stderr);
|
||||
# ifdef __libc_ptf_call
|
||||
__libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Sometimes we want to have at most one error per line. This
|
||||
variable controls whether this mode is selected or not. */
|
||||
int error_one_per_line;
|
||||
|
||||
void
|
||||
error_at_line (int status, int errnum, const char *file_name,
|
||||
unsigned int line_number, const char *message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (error_one_per_line)
|
||||
{
|
||||
static const char *old_file_name;
|
||||
static unsigned int old_line_number;
|
||||
|
||||
if (old_line_number == line_number
|
||||
&& (file_name == old_file_name
|
||||
|| strcmp (old_file_name, file_name) == 0))
|
||||
/* Simply return and print nothing. */
|
||||
return;
|
||||
|
||||
old_file_name = file_name;
|
||||
old_line_number = line_number;
|
||||
}
|
||||
|
||||
#if defined _LIBC && defined __libc_ptf_call
|
||||
/* We do not want this call to be cut short by a thread
|
||||
cancellation. Therefore disable cancellation for now. */
|
||||
int state = PTHREAD_CANCEL_ENABLE;
|
||||
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
|
||||
0);
|
||||
#endif
|
||||
|
||||
fflush (stdout);
|
||||
#ifdef _LIBC
|
||||
_IO_flockfile (stderr);
|
||||
#endif
|
||||
if (error_print_progname)
|
||||
(*error_print_progname) ();
|
||||
else
|
||||
{
|
||||
#if _LIBC
|
||||
__fxprintf (NULL, "%s:", program_name);
|
||||
#else
|
||||
fprintf (stderr, "%s:", program_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if _LIBC
|
||||
__fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
|
||||
file_name, line_number);
|
||||
#else
|
||||
fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
|
||||
file_name, line_number);
|
||||
#endif
|
||||
|
||||
va_start (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
|
||||
#ifdef _LIBC
|
||||
_IO_funlockfile (stderr);
|
||||
# ifdef __libc_ptf_call
|
||||
__libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _LIBC
|
||||
/* Make the weak alias. */
|
||||
# undef error
|
||||
# undef error_at_line
|
||||
weak_alias (__error, error)
|
||||
weak_alias (__error_at_line, error_at_line)
|
||||
#endif
|
@ -1,66 +0,0 @@
|
||||
/* Declaration for error-reporting function
|
||||
Copyright (C) 1995, 1996, 1997, 2003, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _ERROR_H
|
||||
#define _ERROR_H 1
|
||||
|
||||
#ifndef __attribute__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
/* The __-protected variants of `format' and `printf' attributes
|
||||
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
|
||||
# define __format__ format
|
||||
# define __printf__ printf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Print a message with `fprintf (stderr, FORMAT, ...)';
|
||||
if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
|
||||
If STATUS is nonzero, terminate the program with `exit (STATUS)'. */
|
||||
|
||||
extern void error (int __status, int __errnum, const char *__format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
|
||||
extern void error_at_line (int __status, int __errnum, const char *__fname,
|
||||
unsigned int __lineno, const char *__format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 5, 6)));
|
||||
|
||||
/* If NULL, error will flush stdout, then print on stderr the program
|
||||
name, a colon and a space. Otherwise, error will call this
|
||||
function without parameters instead. */
|
||||
extern void (*error_print_progname) (void);
|
||||
|
||||
/* This variable is incremented each time `error' is called. */
|
||||
extern unsigned int error_message_count;
|
||||
|
||||
/* Sometimes we want to have at most one error per line. This
|
||||
variable controls whether this mode is selected or not. */
|
||||
extern int error_one_per_line;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* error.h */
|
@ -1,26 +0,0 @@
|
||||
/* Failure exit status
|
||||
|
||||
Copyright (C) 2002, 2003, 2005, 2006, 2007 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; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "exitfail.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int volatile exit_failure = EXIT_FAILURE;
|
@ -1,20 +0,0 @@
|
||||
/* Failure exit status
|
||||
|
||||
Copyright (C) 2002 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; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
extern int volatile exit_failure;
|
@ -1,27 +0,0 @@
|
||||
/* This file is part of GNU cpio.
|
||||
Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <paxlib.h>
|
||||
|
||||
void
|
||||
fatal_exit ()
|
||||
{
|
||||
exit (PAXEXIT_FAILURE);
|
||||
}
|
||||
|
@ -1,81 +0,0 @@
|
||||
/* An interface to read and write that retries (if necessary) until complete.
|
||||
|
||||
Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
||||
2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#ifdef FULL_READ
|
||||
# include "full-read.h"
|
||||
#else
|
||||
# include "full-write.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef FULL_READ
|
||||
# include "safe-read.h"
|
||||
# define safe_rw safe_read
|
||||
# define full_rw full_read
|
||||
# undef const
|
||||
# define const /* empty */
|
||||
#else
|
||||
# include "safe-write.h"
|
||||
# define safe_rw safe_write
|
||||
# define full_rw full_write
|
||||
#endif
|
||||
|
||||
#ifdef FULL_READ
|
||||
/* Set errno to zero upon EOF. */
|
||||
# define ZERO_BYTE_TRANSFER_ERRNO 0
|
||||
#else
|
||||
/* Some buggy drivers return 0 when one tries to write beyond
|
||||
a device's end. (Example: Linux 1.2.13 on /dev/fd0.)
|
||||
Set errno to ENOSPC so they get a sensible diagnostic. */
|
||||
# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC
|
||||
#endif
|
||||
|
||||
/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if
|
||||
interrupted or if a partial write(read) occurs. Return the number
|
||||
of bytes transferred.
|
||||
When writing, set errno if fewer than COUNT bytes are written.
|
||||
When reading, if fewer than COUNT bytes are read, you must examine
|
||||
errno to distinguish failure from EOF (errno == 0). */
|
||||
size_t
|
||||
full_rw (int fd, const void *buf, size_t count)
|
||||
{
|
||||
size_t total = 0;
|
||||
const char *ptr = (const char *) buf;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
size_t n_rw = safe_rw (fd, ptr, count);
|
||||
if (n_rw == (size_t) -1)
|
||||
break;
|
||||
if (n_rw == 0)
|
||||
{
|
||||
errno = ZERO_BYTE_TRANSFER_ERRNO;
|
||||
break;
|
||||
}
|
||||
total += n_rw;
|
||||
ptr += n_rw;
|
||||
count -= n_rw;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/* An interface to write() that writes all it is asked to write.
|
||||
|
||||
Copyright (C) 2002-2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted
|
||||
or if partial writes occur. Return the number of bytes successfully
|
||||
written, setting errno if that is less than COUNT. */
|
||||
extern size_t full_write (int fd, const void *buf, size_t count);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,171 +0,0 @@
|
||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004,2006
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <getopt.h>
|
||||
#else
|
||||
# include <config.h>
|
||||
# include "getopt.h"
|
||||
#endif
|
||||
#include "getopt_int.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
int
|
||||
getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
|
||||
const struct option *long_options, int *opt_index)
|
||||
{
|
||||
return _getopt_internal (argc, (char **) argv, options, long_options,
|
||||
opt_index, 0, 0);
|
||||
}
|
||||
|
||||
int
|
||||
_getopt_long_r (int argc, char **argv, const char *options,
|
||||
const struct option *long_options, int *opt_index,
|
||||
struct _getopt_data *d)
|
||||
{
|
||||
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
|
||||
0, 0, d);
|
||||
}
|
||||
|
||||
/* 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 (int argc, char *__getopt_argv_const *argv,
|
||||
const char *options,
|
||||
const struct option *long_options, int *opt_index)
|
||||
{
|
||||
return _getopt_internal (argc, (char **) argv, options, long_options,
|
||||
opt_index, 1, 0);
|
||||
}
|
||||
|
||||
int
|
||||
_getopt_long_only_r (int argc, char **argv, const char *options,
|
||||
const struct option *long_options, int *opt_index,
|
||||
struct _getopt_data *d)
|
||||
{
|
||||
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
|
||||
1, 0, d);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (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 == -1)
|
||||
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 */
|
@ -1,226 +0,0 @@
|
||||
/* Declarations for getopt.
|
||||
Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005,2006,2007
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
|
||||
#ifndef __need_getopt
|
||||
# define _GETOPT_H 1
|
||||
#endif
|
||||
|
||||
/* Standalone applications should #define __GETOPT_PREFIX to an
|
||||
identifier that prefixes the external functions and variables
|
||||
defined in this header. When this happens, include the
|
||||
headers that might declare getopt so that they will not cause
|
||||
confusion if included after this file. Then systematically rename
|
||||
identifiers so that they do not collide with the system functions
|
||||
and variables. Renaming avoids problems with some compilers and
|
||||
linkers. */
|
||||
#if defined __GETOPT_PREFIX && !defined __need_getopt
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <unistd.h>
|
||||
# undef __need_getopt
|
||||
# undef getopt
|
||||
# undef getopt_long
|
||||
# undef getopt_long_only
|
||||
# undef optarg
|
||||
# undef opterr
|
||||
# undef optind
|
||||
# undef optopt
|
||||
# define __GETOPT_CONCAT(x, y) x ## y
|
||||
# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y)
|
||||
# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y)
|
||||
# define getopt __GETOPT_ID (getopt)
|
||||
# define getopt_long __GETOPT_ID (getopt_long)
|
||||
# define getopt_long_only __GETOPT_ID (getopt_long_only)
|
||||
# define optarg __GETOPT_ID (optarg)
|
||||
# define opterr __GETOPT_ID (opterr)
|
||||
# define optind __GETOPT_ID (optind)
|
||||
# define optopt __GETOPT_ID (optopt)
|
||||
#endif
|
||||
|
||||
/* Standalone applications get correct prototypes for getopt_long and
|
||||
getopt_long_only; they declare "char **argv". libc uses prototypes
|
||||
with "char *const *argv" that are incorrect because getopt_long and
|
||||
getopt_long_only can permute argv; this is required for backward
|
||||
compatibility (e.g., for LSB 2.0.1).
|
||||
|
||||
This used to be `#if defined __GETOPT_PREFIX && !defined __need_getopt',
|
||||
but it caused redefinition warnings if both unistd.h and getopt.h were
|
||||
included, since unistd.h includes getopt.h having previously defined
|
||||
__need_getopt.
|
||||
|
||||
The only place where __getopt_argv_const is used is in definitions
|
||||
of getopt_long and getopt_long_only below, but these are visible
|
||||
only if __need_getopt is not defined, so it is quite safe to rewrite
|
||||
the conditional as follows:
|
||||
*/
|
||||
#if !defined __need_getopt
|
||||
# if defined __GETOPT_PREFIX
|
||||
# define __getopt_argv_const /* empty */
|
||||
# else
|
||||
# define __getopt_argv_const const
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* If __GNU_LIBRARY__ is not already defined, either we are being used
|
||||
standalone, or this is the first header included in the source file.
|
||||
If we are being used with glibc, we need to include <features.h>, but
|
||||
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
|
||||
not defined, include <ctype.h>, which will pull in <features.h> for us
|
||||
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
|
||||
doesn't flood the namespace with stuff the way some other headers do.) */
|
||||
#if !defined __GNU_LIBRARY__
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
#ifndef __THROW
|
||||
# ifndef __GNUC_PREREQ
|
||||
# define __GNUC_PREREQ(maj, min) (0)
|
||||
# endif
|
||||
# if defined __cplusplus && __GNUC_PREREQ (2,8)
|
||||
# define __THROW throw ()
|
||||
# else
|
||||
# define __THROW
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#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 -1, 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;
|
||||
|
||||
#ifndef __need_getopt
|
||||
/* 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
|
||||
{
|
||||
const char *name;
|
||||
/* 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
|
||||
#endif /* need getopt */
|
||||
|
||||
|
||||
/* Get definitions and prototypes for functions to process the
|
||||
arguments in ARGV (ARGC of them, minus the program name) for
|
||||
options given in OPTS.
|
||||
|
||||
Return the option character from OPTS just read. Return -1 when
|
||||
there are no more options. For unrecognized options, or options
|
||||
missing arguments, `optopt' is set to the option letter, and '?' is
|
||||
returned.
|
||||
|
||||
The OPTS string is a list of characters which are recognized option
|
||||
letters, optionally followed by colons, specifying that that letter
|
||||
takes an argument, to be placed in `optarg'.
|
||||
|
||||
If a letter in OPTS is followed by two colons, its argument is
|
||||
optional. This behavior is specific to the GNU `getopt'.
|
||||
|
||||
The argument `--' causes premature termination of argument
|
||||
scanning, explicitly telling `getopt' that there are no more
|
||||
options.
|
||||
|
||||
If OPTS begins with `-', then non-option arguments are treated as
|
||||
arguments to the option '\1'. This behavior is specific to the GNU
|
||||
`getopt'. If OPTS begins with `+', or POSIXLY_CORRECT is set in
|
||||
the environment, then do not permute arguments. */
|
||||
|
||||
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
|
||||
__THROW;
|
||||
|
||||
#ifndef __need_getopt
|
||||
extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind)
|
||||
__THROW;
|
||||
extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind)
|
||||
__THROW;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make sure we later can get all the definitions and declarations. */
|
||||
#undef __need_getopt
|
||||
|
||||
#endif /* getopt.h */
|
@ -1,131 +0,0 @@
|
||||
/* Internal declarations for getopt.
|
||||
Copyright (C) 1989-1994,1996-1999,2001,2003,2004
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _GETOPT_INT_H
|
||||
#define _GETOPT_INT_H 1
|
||||
|
||||
extern int _getopt_internal (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
int __long_only, int __posixly_correct);
|
||||
|
||||
|
||||
/* Reentrant versions which can handle parsing multiple argument
|
||||
vectors at the same time. */
|
||||
|
||||
/* Data type for reentrant functions. */
|
||||
struct _getopt_data
|
||||
{
|
||||
/* These have exactly the same meaning as the corresponding global
|
||||
variables, except that they are used for the reentrant
|
||||
versions of getopt. */
|
||||
int optind;
|
||||
int opterr;
|
||||
int optopt;
|
||||
char *optarg;
|
||||
|
||||
/* Internal members. */
|
||||
|
||||
/* True if the internal members have been initialized. */
|
||||
int __initialized;
|
||||
|
||||
/* 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. */
|
||||
char *__nextchar;
|
||||
|
||||
/* 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, or by calling getopt.
|
||||
|
||||
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 -1 with `optind' != ARGC. */
|
||||
|
||||
enum
|
||||
{
|
||||
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
||||
} __ordering;
|
||||
|
||||
/* If the POSIXLY_CORRECT environment variable is set
|
||||
or getopt was called. */
|
||||
int __posixly_correct;
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
int __first_nonopt;
|
||||
int __last_nonopt;
|
||||
|
||||
#if defined _LIBC && defined USE_NONOPTION_FLAGS
|
||||
int __nonoption_flags_max_len;
|
||||
int __nonoption_flags_len;
|
||||
# endif
|
||||
};
|
||||
|
||||
/* The initializer is necessary to set OPTIND and OPTERR to their
|
||||
default values and to clear the initialization flag. */
|
||||
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
|
||||
|
||||
extern int _getopt_internal_r (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
int __long_only, int __posixly_correct,
|
||||
struct _getopt_data *__data);
|
||||
|
||||
extern int _getopt_long_r (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts, int *__longind,
|
||||
struct _getopt_data *__data);
|
||||
|
||||
extern int _getopt_long_only_r (int ___argc, char **___argv,
|
||||
const char *__shortopts,
|
||||
const struct option *__longopts,
|
||||
int *__longind,
|
||||
struct _getopt_data *__data);
|
||||
|
||||
#endif /* getopt_int.h */
|
@ -1,270 +0,0 @@
|
||||
/* Convenience header for conditional use of GNU <libintl.h>.
|
||||
Copyright (C) 1995-1998, 2000-2002, 2004-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _LIBGETTEXT_H
|
||||
#define _LIBGETTEXT_H 1
|
||||
|
||||
/* NLS can be disabled through the configure --disable-nls option. */
|
||||
#if ENABLE_NLS
|
||||
|
||||
/* Get declarations of GNU message catalog functions. */
|
||||
# include <libintl.h>
|
||||
|
||||
/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
|
||||
the gettext() and ngettext() macros. This is an alternative to calling
|
||||
textdomain(), and is useful for libraries. */
|
||||
# ifdef DEFAULT_TEXT_DOMAIN
|
||||
# undef gettext
|
||||
# define gettext(Msgid) \
|
||||
dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
|
||||
# undef ngettext
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
|
||||
chokes if dcgettext is defined as a macro. So include it now, to make
|
||||
later inclusions of <locale.h> a NOP. We don't include <libintl.h>
|
||||
as well because people using "gettext.h" will not include <libintl.h>,
|
||||
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
|
||||
is OK. */
|
||||
#if defined(__sun)
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
|
||||
<libintl.h>, which chokes if dcgettext is defined as a macro. So include
|
||||
it now, to make later inclusions of <libintl.h> a NOP. */
|
||||
#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
|
||||
# include <cstdlib>
|
||||
# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
|
||||
# include <libintl.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Disabled NLS.
|
||||
The casts to 'const char *' serve the purpose of producing warnings
|
||||
for invalid uses of the value returned from these functions.
|
||||
On pre-ANSI systems without 'const', the config.h file is supposed to
|
||||
contain "#define const". */
|
||||
# define gettext(Msgid) ((const char *) (Msgid))
|
||||
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
|
||||
# define dcgettext(Domainname, Msgid, Category) \
|
||||
((void) (Category), dgettext (Domainname, Msgid))
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
((N) == 1 \
|
||||
? ((void) (Msgid2), (const char *) (Msgid1)) \
|
||||
: ((void) (Msgid1), (const char *) (Msgid2)))
|
||||
# define dngettext(Domainname, Msgid1, Msgid2, N) \
|
||||
((void) (Domainname), ngettext (Msgid1, Msgid2, N))
|
||||
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
|
||||
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
|
||||
# define textdomain(Domainname) ((const char *) (Domainname))
|
||||
# define bindtextdomain(Domainname, Dirname) \
|
||||
((void) (Domainname), (const char *) (Dirname))
|
||||
# define bind_textdomain_codeset(Domainname, Codeset) \
|
||||
((void) (Domainname), (const char *) (Codeset))
|
||||
|
||||
#endif
|
||||
|
||||
/* A pseudo function call that serves as a marker for the automated
|
||||
extraction of messages, but does not call gettext(). The run-time
|
||||
translation is done at a different place in the code.
|
||||
The argument, String, should be a literal string. Concatenated strings
|
||||
and other string expressions won't work.
|
||||
The macro's expansion is not parenthesized, so that it is suitable as
|
||||
initializer for static 'char[]' or 'const char[]' variables. */
|
||||
#define gettext_noop(String) String
|
||||
|
||||
/* The separator between msgctxt and msgid in a .mo file. */
|
||||
#define GETTEXT_CONTEXT_GLUE "\004"
|
||||
|
||||
/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
|
||||
MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
|
||||
short and rarely need to change.
|
||||
The letter 'p' stands for 'particular' or 'special'. */
|
||||
#ifdef DEFAULT_TEXT_DOMAIN
|
||||
# define pgettext(Msgctxt, Msgid) \
|
||||
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#else
|
||||
# define pgettext(Msgctxt, Msgid) \
|
||||
pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#endif
|
||||
#define dpgettext(Domainname, Msgctxt, Msgid) \
|
||||
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
|
||||
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
|
||||
#ifdef DEFAULT_TEXT_DOMAIN
|
||||
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#else
|
||||
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#endif
|
||||
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
|
||||
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
pgettext_aux (const char *domain,
|
||||
const char *msg_ctxt_id, const char *msgid,
|
||||
int category)
|
||||
{
|
||||
const char *translation = dcgettext (domain, msg_ctxt_id, category);
|
||||
if (translation == msg_ctxt_id)
|
||||
return msgid;
|
||||
else
|
||||
return translation;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
npgettext_aux (const char *domain,
|
||||
const char *msg_ctxt_id, const char *msgid,
|
||||
const char *msgid_plural, unsigned long int n,
|
||||
int category)
|
||||
{
|
||||
const char *translation =
|
||||
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
|
||||
if (translation == msg_ctxt_id || translation == msgid_plural)
|
||||
return (n == 1 ? msgid : msgid_plural);
|
||||
else
|
||||
return translation;
|
||||
}
|
||||
|
||||
/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
|
||||
can be arbitrary expressions. But for string literals these macros are
|
||||
less efficient than those above. */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
|
||||
(((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
|
||||
/* || __STDC_VERSION__ >= 199901L */ )
|
||||
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define pgettext_expr(Msgctxt, Msgid) \
|
||||
dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
|
||||
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
|
||||
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
dcpgettext_expr (const char *domain,
|
||||
const char *msgctxt, const char *msgid,
|
||||
int category)
|
||||
{
|
||||
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||
size_t msgid_len = strlen (msgid) + 1;
|
||||
const char *translation;
|
||||
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
char msg_ctxt_id[msgctxt_len + msgid_len];
|
||||
#else
|
||||
char buf[1024];
|
||||
char *msg_ctxt_id =
|
||||
(msgctxt_len + msgid_len <= sizeof (buf)
|
||||
? buf
|
||||
: (char *) malloc (msgctxt_len + msgid_len));
|
||||
if (msg_ctxt_id != NULL)
|
||||
#endif
|
||||
{
|
||||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||
translation = dcgettext (domain, msg_ctxt_id, category);
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
if (msg_ctxt_id != buf)
|
||||
free (msg_ctxt_id);
|
||||
#endif
|
||||
if (translation != msg_ctxt_id)
|
||||
return translation;
|
||||
}
|
||||
return msgid;
|
||||
}
|
||||
|
||||
#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
|
||||
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
dcnpgettext_expr (const char *domain,
|
||||
const char *msgctxt, const char *msgid,
|
||||
const char *msgid_plural, unsigned long int n,
|
||||
int category)
|
||||
{
|
||||
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||
size_t msgid_len = strlen (msgid) + 1;
|
||||
const char *translation;
|
||||
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
char msg_ctxt_id[msgctxt_len + msgid_len];
|
||||
#else
|
||||
char buf[1024];
|
||||
char *msg_ctxt_id =
|
||||
(msgctxt_len + msgid_len <= sizeof (buf)
|
||||
? buf
|
||||
: (char *) malloc (msgctxt_len + msgid_len));
|
||||
if (msg_ctxt_id != NULL)
|
||||
#endif
|
||||
{
|
||||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
if (msg_ctxt_id != buf)
|
||||
free (msg_ctxt_id);
|
||||
#endif
|
||||
if (!(translation == msg_ctxt_id || translation == msgid_plural))
|
||||
return translation;
|
||||
}
|
||||
return (n == 1 ? msgid : msgid_plural);
|
||||
}
|
||||
|
||||
#endif /* _LIBGETTEXT_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,88 +0,0 @@
|
||||
/* hash - hashing table processing.
|
||||
Copyright (C) 1998, 1999, 2001, 2003 Free Software Foundation, Inc.
|
||||
Written by Jim Meyering <meyering@ascend.com>, 1998.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* A generic hash table package. */
|
||||
|
||||
/* Make sure USE_OBSTACK is defined to 1 if you want the allocator to use
|
||||
obstacks instead of malloc, and recompile `hash.c' with same setting. */
|
||||
|
||||
#ifndef HASH_H_
|
||||
# define HASH_H_
|
||||
|
||||
# include <stdio.h>
|
||||
# include <stdbool.h>
|
||||
|
||||
typedef size_t (*Hash_hasher) (const void *, size_t);
|
||||
typedef bool (*Hash_comparator) (const void *, const void *);
|
||||
typedef void (*Hash_data_freer) (void *);
|
||||
typedef bool (*Hash_processor) (void *, void *);
|
||||
|
||||
struct hash_entry
|
||||
{
|
||||
void *data;
|
||||
struct hash_entry *next;
|
||||
};
|
||||
|
||||
struct hash_tuning
|
||||
{
|
||||
/* This structure is mainly used for `hash_initialize', see the block
|
||||
documentation of `hash_reset_tuning' for more complete comments. */
|
||||
|
||||
float shrink_threshold; /* ratio of used buckets to trigger a shrink */
|
||||
float shrink_factor; /* ratio of new smaller size to original size */
|
||||
float growth_threshold; /* ratio of used buckets to trigger a growth */
|
||||
float growth_factor; /* ratio of new bigger size to original size */
|
||||
bool is_n_buckets; /* if CANDIDATE really means table size */
|
||||
};
|
||||
|
||||
typedef struct hash_tuning Hash_tuning;
|
||||
|
||||
struct hash_table;
|
||||
|
||||
typedef struct hash_table Hash_table;
|
||||
|
||||
/* Information and lookup. */
|
||||
size_t hash_get_n_buckets (const Hash_table *);
|
||||
size_t hash_get_n_buckets_used (const Hash_table *);
|
||||
size_t hash_get_n_entries (const Hash_table *);
|
||||
size_t hash_get_max_bucket_length (const Hash_table *);
|
||||
bool hash_table_ok (const Hash_table *);
|
||||
void hash_print_statistics (const Hash_table *, FILE *);
|
||||
void *hash_lookup (const Hash_table *, const void *);
|
||||
|
||||
/* Walking. */
|
||||
void *hash_get_first (const Hash_table *);
|
||||
void *hash_get_next (const Hash_table *, const void *);
|
||||
size_t hash_get_entries (const Hash_table *, void **, size_t);
|
||||
size_t hash_do_for_each (const Hash_table *, Hash_processor, void *);
|
||||
|
||||
/* Allocation and clean-up. */
|
||||
size_t hash_string (const char *, size_t);
|
||||
void hash_reset_tuning (Hash_tuning *);
|
||||
Hash_table *hash_initialize (size_t, const Hash_tuning *,
|
||||
Hash_hasher, Hash_comparator,
|
||||
Hash_data_freer);
|
||||
void hash_clear (Hash_table *);
|
||||
void hash_free (Hash_table *);
|
||||
|
||||
/* Insertion and deletion. */
|
||||
bool hash_rehash (Hash_table *, size_t);
|
||||
void *hash_insert (Hash_table *, const void *);
|
||||
void *hash_delete (Hash_table *, const void *);
|
||||
|
||||
#endif
|
@ -1,78 +0,0 @@
|
||||
/* intprops.h -- properties of integer types
|
||||
|
||||
Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* The extra casts in the following macros work around compiler bugs,
|
||||
e.g., in Cray C 5.0.3.0. */
|
||||
|
||||
/* True if the arithmetic type T is an integer type. bool counts as
|
||||
an integer. */
|
||||
#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
|
||||
|
||||
/* True if negative values of the signed integer type T use two's
|
||||
complement, ones' complement, or signed magnitude representation,
|
||||
respectively. Much GNU code assumes two's complement, but some
|
||||
people like to be portable to all possible C hosts. */
|
||||
#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
|
||||
#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
|
||||
#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
|
||||
|
||||
/* True if the arithmetic type T is signed. */
|
||||
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
|
||||
/* The maximum and minimum values for the integer type T. These
|
||||
macros have undefined behavior if T is signed and has padding bits.
|
||||
If this is a problem for you, please let us know how to fix it for
|
||||
your host. */
|
||||
#define TYPE_MINIMUM(t) \
|
||||
((t) (! TYPE_SIGNED (t) \
|
||||
? (t) 0 \
|
||||
: TYPE_SIGNED_MAGNITUDE (t) \
|
||||
? ~ (t) 0 \
|
||||
: ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
|
||||
#define TYPE_MAXIMUM(t) \
|
||||
((t) (! TYPE_SIGNED (t) \
|
||||
? (t) -1 \
|
||||
: ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
|
||||
|
||||
/* Return zero if T can be determined to be an unsigned type.
|
||||
Otherwise, return 1.
|
||||
When compiling with GCC, INT_STRLEN_BOUND uses this macro to obtain a
|
||||
tighter bound. Otherwise, it overestimates the true bound by one byte
|
||||
when applied to unsigned types of size 2, 4, 16, ... bytes.
|
||||
The symbol signed_type_or_expr__ is private to this header file. */
|
||||
#if __GNUC__ >= 2
|
||||
# define signed_type_or_expr__(t) TYPE_SIGNED (__typeof__ (t))
|
||||
#else
|
||||
# define signed_type_or_expr__(t) 1
|
||||
#endif
|
||||
|
||||
/* Bound on length of the string representing an integer type or expression T.
|
||||
Subtract 1 for the sign bit if T is signed; log10 (2.0) < 146/485;
|
||||
add 1 for integer division truncation; add 1 more for a minus sign
|
||||
if needed. */
|
||||
#define INT_STRLEN_BOUND(t) \
|
||||
((sizeof (t) * CHAR_BIT - signed_type_or_expr__ (t)) * 146 / 485 \
|
||||
+ signed_type_or_expr__ (t) + 1)
|
||||
|
||||
/* Bound on buffer size needed to represent an integer type or expression T,
|
||||
including the terminating null. */
|
||||
#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
|
@ -1,51 +0,0 @@
|
||||
/* inttostr.c -- convert integers to printable strings
|
||||
|
||||
Copyright (C) 2001, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Paul Eggert */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "inttostr.h"
|
||||
|
||||
/* Convert I to a printable string in BUF, which must be at least
|
||||
INT_BUFSIZE_BOUND (INTTYPE) bytes long. Return the address of the
|
||||
printable string, which need not start at BUF. */
|
||||
|
||||
char *
|
||||
inttostr (inttype i, char *buf)
|
||||
{
|
||||
char *p = buf + INT_STRLEN_BOUND (inttype);
|
||||
*p = 0;
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
do
|
||||
*--p = '0' - i % 10;
|
||||
while ((i /= 10) != 0);
|
||||
|
||||
*--p = '-';
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
*--p = '0' + i % 10;
|
||||
while ((i /= 10) != 0);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/* inttostr.h -- convert integers to printable strings
|
||||
|
||||
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Paul Eggert */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "intprops.h"
|
||||
|
||||
char *offtostr (off_t, char *);
|
||||
char *imaxtostr (intmax_t, char *);
|
||||
char *umaxtostr (uintmax_t, char *);
|
||||
char *uinttostr (unsigned int, char *);
|
@ -1,29 +0,0 @@
|
||||
/* Copy memory area and return pointer after last written byte.
|
||||
Copyright (C) 2003, 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <string.h>
|
||||
|
||||
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
|
||||
last written byte. */
|
||||
void *
|
||||
mempcpy (void *dest, const void *src, size_t n)
|
||||
{
|
||||
return (char *) memcpy (dest, src, n) + n;
|
||||
}
|
@ -1,365 +0,0 @@
|
||||
/* Miscellaneous error functions
|
||||
|
||||
Copyright (C) 2005 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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <paxlib.h>
|
||||
#include <quote.h>
|
||||
#include <quotearg.h>
|
||||
|
||||
/* Decode MODE from its binary form in a stat structure, and encode it
|
||||
into a 9-byte string STRING, terminated with a NUL. */
|
||||
|
||||
void
|
||||
pax_decode_mode (mode_t mode, char *string)
|
||||
{
|
||||
*string++ = mode & S_IRUSR ? 'r' : '-';
|
||||
*string++ = mode & S_IWUSR ? 'w' : '-';
|
||||
*string++ = (mode & S_ISUID
|
||||
? (mode & S_IXUSR ? 's' : 'S')
|
||||
: (mode & S_IXUSR ? 'x' : '-'));
|
||||
*string++ = mode & S_IRGRP ? 'r' : '-';
|
||||
*string++ = mode & S_IWGRP ? 'w' : '-';
|
||||
*string++ = (mode & S_ISGID
|
||||
? (mode & S_IXGRP ? 's' : 'S')
|
||||
: (mode & S_IXGRP ? 'x' : '-'));
|
||||
*string++ = mode & S_IROTH ? 'r' : '-';
|
||||
*string++ = mode & S_IWOTH ? 'w' : '-';
|
||||
*string++ = (mode & S_ISVTX
|
||||
? (mode & S_IXOTH ? 't' : 'T')
|
||||
: (mode & S_IXOTH ? 'x' : '-'));
|
||||
*string = '\0';
|
||||
}
|
||||
|
||||
/* Report an error associated with the system call CALL and the
|
||||
optional name NAME. */
|
||||
void
|
||||
call_arg_error (char const *call, char const *name)
|
||||
{
|
||||
int e = errno;
|
||||
/* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
|
||||
Directly translating this to another language will not work, first because
|
||||
%s itself is not translated.
|
||||
Translate it as `%s: Function %s failed'. */
|
||||
ERROR ((0, e, _("%s: Cannot %s"), quotearg_colon (name), call));
|
||||
}
|
||||
|
||||
/* Report a fatal error associated with the system call CALL and
|
||||
the optional file name NAME. */
|
||||
void
|
||||
call_arg_fatal (char const *call, char const *name)
|
||||
{
|
||||
int e = errno;
|
||||
/* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
|
||||
Directly translating this to another language will not work, first because
|
||||
%s itself is not translated.
|
||||
Translate it as `%s: Function %s failed'. */
|
||||
FATAL_ERROR ((0, e, _("%s: Cannot %s"), quotearg_colon (name), call));
|
||||
}
|
||||
|
||||
/* Report a warning associated with the system call CALL and
|
||||
the optional file name NAME. */
|
||||
void
|
||||
call_arg_warn (char const *call, char const *name)
|
||||
{
|
||||
int e = errno;
|
||||
/* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
|
||||
Directly translating this to another language will not work, first because
|
||||
%s itself is not translated.
|
||||
Translate it as `%s: Function %s failed'. */
|
||||
WARN ((0, e, _("%s: Warning: Cannot %s"), quotearg_colon (name), call));
|
||||
}
|
||||
|
||||
void
|
||||
chmod_error_details (char const *name, mode_t mode)
|
||||
{
|
||||
int e = errno;
|
||||
char buf[10];
|
||||
pax_decode_mode (mode, buf);
|
||||
ERROR ((0, e, _("%s: Cannot change mode to %s"),
|
||||
quotearg_colon (name), buf));
|
||||
}
|
||||
|
||||
void
|
||||
chown_error_details (char const *name, uid_t uid, gid_t gid)
|
||||
{
|
||||
int e = errno;
|
||||
ERROR ((0, e, _("%s: Cannot change ownership to uid %lu, gid %lu"),
|
||||
quotearg_colon (name), (unsigned long) uid, (unsigned long) gid));
|
||||
}
|
||||
|
||||
void
|
||||
close_error (char const *name)
|
||||
{
|
||||
call_arg_error ("close", name);
|
||||
}
|
||||
|
||||
void
|
||||
close_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("close", name);
|
||||
}
|
||||
|
||||
void
|
||||
exec_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("exec", name);
|
||||
}
|
||||
|
||||
void
|
||||
link_error (char const *target, char const *source)
|
||||
{
|
||||
int e = errno;
|
||||
ERROR ((0, e, _("%s: Cannot hard link to %s"),
|
||||
quotearg_colon (source), quote_n (1, target)));
|
||||
}
|
||||
|
||||
void
|
||||
mkdir_error (char const *name)
|
||||
{
|
||||
call_arg_error ("mkdir", name);
|
||||
}
|
||||
|
||||
void
|
||||
mkfifo_error (char const *name)
|
||||
{
|
||||
call_arg_error ("mkfifo", name);
|
||||
}
|
||||
|
||||
void
|
||||
mknod_error (char const *name)
|
||||
{
|
||||
call_arg_error ("mknod", name);
|
||||
}
|
||||
|
||||
void
|
||||
open_error (char const *name)
|
||||
{
|
||||
call_arg_error ("open", name);
|
||||
}
|
||||
|
||||
void
|
||||
open_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("open", name);
|
||||
}
|
||||
|
||||
void
|
||||
open_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("open", name);
|
||||
}
|
||||
|
||||
void
|
||||
read_error (char const *name)
|
||||
{
|
||||
call_arg_error ("read", name);
|
||||
}
|
||||
|
||||
void
|
||||
read_error_details (char const *name, off_t offset, size_t size)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
int e = errno;
|
||||
ERROR ((0, e,
|
||||
ngettext ("%s: Read error at byte %s, while reading %lu byte",
|
||||
"%s: Read error at byte %s, while reading %lu bytes",
|
||||
size),
|
||||
quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
|
||||
(unsigned long) size));
|
||||
}
|
||||
|
||||
void
|
||||
read_warn_details (char const *name, off_t offset, size_t size)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
int e = errno;
|
||||
WARN ((0, e,
|
||||
ngettext ("%s: Warning: Read error at byte %s, while reading %lu byte",
|
||||
"%s: Warning: Read error at byte %s, while reading %lu bytes",
|
||||
size),
|
||||
quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
|
||||
(unsigned long) size));
|
||||
}
|
||||
|
||||
void
|
||||
read_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("read", name);
|
||||
}
|
||||
|
||||
void
|
||||
read_fatal_details (char const *name, off_t offset, size_t size)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
int e = errno;
|
||||
FATAL_ERROR ((0, e,
|
||||
ngettext ("%s: Read error at byte %s, while reading %lu byte",
|
||||
"%s: Read error at byte %s, while reading %lu bytes",
|
||||
size),
|
||||
quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
|
||||
(unsigned long) size));
|
||||
}
|
||||
|
||||
void
|
||||
readlink_error (char const *name)
|
||||
{
|
||||
call_arg_error ("readlink", name);
|
||||
}
|
||||
|
||||
void
|
||||
readlink_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("readlink", name);
|
||||
}
|
||||
|
||||
void
|
||||
rmdir_error (char const *name)
|
||||
{
|
||||
call_arg_error ("rmdir", name);
|
||||
}
|
||||
|
||||
void
|
||||
savedir_error (char const *name)
|
||||
{
|
||||
call_arg_error ("savedir", name);
|
||||
}
|
||||
|
||||
void
|
||||
savedir_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("savedir", name);
|
||||
}
|
||||
|
||||
void
|
||||
seek_error (char const *name)
|
||||
{
|
||||
call_arg_error ("seek", name);
|
||||
}
|
||||
|
||||
void
|
||||
seek_error_details (char const *name, off_t offset)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
int e = errno;
|
||||
ERROR ((0, e, _("%s: Cannot seek to %s"),
|
||||
quotearg_colon (name),
|
||||
STRINGIFY_BIGINT (offset, buf)));
|
||||
}
|
||||
|
||||
void
|
||||
seek_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("seek", name);
|
||||
}
|
||||
|
||||
void
|
||||
seek_warn_details (char const *name, off_t offset)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
int e = errno;
|
||||
WARN ((0, e, _("%s: Warning: Cannot seek to %s"),
|
||||
quotearg_colon (name),
|
||||
STRINGIFY_BIGINT (offset, buf)));
|
||||
}
|
||||
|
||||
void
|
||||
symlink_error (char const *contents, char const *name)
|
||||
{
|
||||
int e = errno;
|
||||
ERROR ((0, e, _("%s: Cannot create symlink to %s"),
|
||||
quotearg_colon (name), quote_n (1, contents)));
|
||||
}
|
||||
|
||||
void
|
||||
stat_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("stat", name);
|
||||
}
|
||||
|
||||
void
|
||||
stat_error (char const *name)
|
||||
{
|
||||
call_arg_error ("stat", name);
|
||||
}
|
||||
|
||||
void
|
||||
stat_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("stat", name);
|
||||
}
|
||||
|
||||
void
|
||||
truncate_error (char const *name)
|
||||
{
|
||||
call_arg_error ("truncate", name);
|
||||
}
|
||||
|
||||
void
|
||||
truncate_warn (char const *name)
|
||||
{
|
||||
call_arg_warn ("truncate", name);
|
||||
}
|
||||
|
||||
void
|
||||
unlink_error (char const *name)
|
||||
{
|
||||
call_arg_error ("unlink", name);
|
||||
}
|
||||
|
||||
void
|
||||
utime_error (char const *name)
|
||||
{
|
||||
call_arg_error ("utime", name);
|
||||
}
|
||||
|
||||
void
|
||||
waitpid_error (char const *name)
|
||||
{
|
||||
call_arg_error ("waitpid", name);
|
||||
}
|
||||
|
||||
void
|
||||
write_error (char const *name)
|
||||
{
|
||||
call_arg_error ("write", name);
|
||||
}
|
||||
|
||||
void
|
||||
write_error_details (char const *name, size_t status, size_t size)
|
||||
{
|
||||
if (status == 0)
|
||||
write_error (name);
|
||||
else
|
||||
ERROR ((0, 0,
|
||||
ngettext ("%s: Wrote only %lu of %lu byte",
|
||||
"%s: Wrote only %lu of %lu bytes",
|
||||
size),
|
||||
name, (unsigned long int) status, (unsigned long int) size));
|
||||
}
|
||||
|
||||
void
|
||||
write_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("write", name);
|
||||
}
|
||||
|
||||
void
|
||||
chdir_fatal (char const *name)
|
||||
{
|
||||
call_arg_fatal ("chdir", name);
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/* Miscellaneous error functions
|
||||
|
||||
Copyright (C) 2005, 2006 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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <paxlib.h>
|
||||
|
||||
int exit_status = PAXEXIT_SUCCESS;
|
||||
|
||||
void
|
||||
pax_exit ()
|
||||
{
|
||||
exit (exit_status);
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/* This file is part of GNU paxutils
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _paxlib_h_
|
||||
#define _paxlib_h_
|
||||
|
||||
#include <hash.h>
|
||||
#include <inttostr.h>
|
||||
|
||||
/* Error reporting functions and definitions */
|
||||
|
||||
/* Exit status for paxutils app. Let's try to keep this list as simple as
|
||||
possible. tar -d option strongly invites a status different for unequal
|
||||
comparison and other errors. */
|
||||
#define PAXEXIT_SUCCESS 0
|
||||
#define PAXEXIT_DIFFERS 1
|
||||
#define PAXEXIT_FAILURE 2
|
||||
|
||||
/* Both WARN and ERROR write a message on stderr and continue processing,
|
||||
however ERROR manages so tar will exit unsuccessfully. FATAL_ERROR
|
||||
writes a message on stderr and aborts immediately, with another message
|
||||
line telling so. USAGE_ERROR works like FATAL_ERROR except that the
|
||||
other message line suggests trying --help. All four macros accept a
|
||||
single argument of the form ((0, errno, _("FORMAT"), Args...)). errno
|
||||
is zero when the error is not being detected by the system. */
|
||||
|
||||
#define WARN(Args) \
|
||||
error Args
|
||||
#define ERROR(Args) \
|
||||
(error Args, exit_status = PAXEXIT_FAILURE)
|
||||
#define FATAL_ERROR(Args) \
|
||||
(error Args, fatal_exit ())
|
||||
#define USAGE_ERROR(Args) \
|
||||
(error Args, usage (PAXEXIT_FAILURE))
|
||||
|
||||
extern int exit_status;
|
||||
|
||||
void pax_decode_mode (mode_t mode, char *string);
|
||||
void call_arg_error (char const *call, char const *name);
|
||||
void call_arg_fatal (char const *call, char const *name) __attribute__ ((noreturn));
|
||||
void call_arg_warn (char const *call, char const *name);
|
||||
void chmod_error_details (char const *name, mode_t mode);
|
||||
void chown_error_details (char const *name, uid_t uid, gid_t gid);
|
||||
|
||||
void decode_mode (mode_t, char *);
|
||||
|
||||
void chdir_fatal (char const *) __attribute__ ((noreturn));
|
||||
void chmod_error_details (char const *, mode_t);
|
||||
void chown_error_details (char const *, uid_t, gid_t);
|
||||
void close_error (char const *);
|
||||
void close_warn (char const *);
|
||||
void exec_fatal (char const *) __attribute__ ((noreturn));
|
||||
void link_error (char const *, char const *);
|
||||
void mkdir_error (char const *);
|
||||
void mkfifo_error (char const *);
|
||||
void mknod_error (char const *);
|
||||
void open_error (char const *);
|
||||
void open_fatal (char const *) __attribute__ ((noreturn));
|
||||
void open_warn (char const *);
|
||||
void read_error (char const *);
|
||||
void read_error_details (char const *, off_t, size_t);
|
||||
void read_fatal (char const *) __attribute__ ((noreturn));
|
||||
void read_fatal_details (char const *, off_t, size_t) __attribute__ ((noreturn));
|
||||
void read_warn_details (char const *, off_t, size_t);
|
||||
void readlink_error (char const *);
|
||||
void readlink_warn (char const *);
|
||||
void rmdir_error (char const *);
|
||||
void savedir_error (char const *);
|
||||
void savedir_warn (char const *);
|
||||
void seek_error (char const *);
|
||||
void seek_error_details (char const *, off_t);
|
||||
void seek_warn (char const *);
|
||||
void seek_warn_details (char const *, off_t);
|
||||
void stat_fatal (char const *);
|
||||
void stat_error (char const *);
|
||||
void stat_warn (char const *);
|
||||
void symlink_error (char const *, char const *);
|
||||
void truncate_error (char const *);
|
||||
void truncate_warn (char const *);
|
||||
void unlink_error (char const *);
|
||||
void utime_error (char const *);
|
||||
void waitpid_error (char const *);
|
||||
void write_error (char const *);
|
||||
|
||||
void pax_exit (void);
|
||||
void fatal_exit (void) __attribute__ ((noreturn));
|
||||
|
||||
#define STRINGIFY_BIGINT(i, b) umaxtostr (i, b)
|
||||
|
||||
|
||||
/* Name-related functions */
|
||||
bool hash_string_insert (Hash_table **table, char const *string);
|
||||
bool hash_string_lookup (Hash_table const *table, char const *string);
|
||||
|
||||
bool removed_prefixes_p (void);
|
||||
char *safer_name_suffix (char const *file_name, bool link_target, bool absolute_names);
|
||||
|
||||
#endif
|
@ -1,156 +0,0 @@
|
||||
/* This file is part of GNU paxutils
|
||||
Copyright (C) 2005 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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <system.h>
|
||||
#include <hash.h>
|
||||
#include <paxlib.h>
|
||||
|
||||
|
||||
/* Hash tables of strings. */
|
||||
|
||||
/* Calculate the hash of a string. */
|
||||
static size_t
|
||||
hash_string_hasher (void const *name, size_t n_buckets)
|
||||
{
|
||||
return hash_string (name, n_buckets);
|
||||
}
|
||||
|
||||
/* Compare two strings for equality. */
|
||||
static bool
|
||||
hash_string_compare (void const *name1, void const *name2)
|
||||
{
|
||||
return strcmp (name1, name2) == 0;
|
||||
}
|
||||
|
||||
/* Return zero if TABLE contains a copy of STRING; otherwise, insert a
|
||||
copy of STRING to TABLE and return 1. */
|
||||
bool
|
||||
hash_string_insert (Hash_table **table, char const *string)
|
||||
{
|
||||
Hash_table *t = *table;
|
||||
char *s = xstrdup (string);
|
||||
char *e;
|
||||
|
||||
if (! ((t
|
||||
|| (*table = t = hash_initialize (0, 0, hash_string_hasher,
|
||||
hash_string_compare, 0)))
|
||||
&& (e = hash_insert (t, s))))
|
||||
xalloc_die ();
|
||||
|
||||
if (e == s)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
free (s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if TABLE contains STRING. */
|
||||
bool
|
||||
hash_string_lookup (Hash_table const *table, char const *string)
|
||||
{
|
||||
return table && hash_lookup (table, string);
|
||||
}
|
||||
|
||||
|
||||
static Hash_table *prefix_table[2];
|
||||
|
||||
/* Return true if file names of some members in the archive were stripped off
|
||||
their leading components. We could have used
|
||||
return prefix_table[0] || prefix_table[1]
|
||||
but the following seems to be safer: */
|
||||
bool
|
||||
removed_prefixes_p (void)
|
||||
{
|
||||
return (prefix_table[0] && hash_get_n_entries (prefix_table[0]) != 0)
|
||||
|| (prefix_table[1] && hash_get_n_entries (prefix_table[1]) != 0);
|
||||
}
|
||||
|
||||
/* Return a safer suffix of FILE_NAME, or "." if it has no safer
|
||||
suffix. Check for fully specified file names and other atrocities.
|
||||
Warn the user if we do not return NAME. If LINK_TARGET is 1,
|
||||
FILE_NAME is the target of a hard link, not a member name.
|
||||
If ABSOLUTE_NAMES is 0, strip filesystem prefix from the file name. */
|
||||
|
||||
char *
|
||||
safer_name_suffix (char const *file_name, bool link_target, bool absolute_names)
|
||||
{
|
||||
char const *p;
|
||||
|
||||
if (absolute_names)
|
||||
p = file_name;
|
||||
else
|
||||
{
|
||||
/* Skip file system prefixes, leading file name components that contain
|
||||
"..", and leading slashes. */
|
||||
|
||||
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (file_name);
|
||||
|
||||
for (p = file_name + prefix_len; *p; )
|
||||
{
|
||||
if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
|
||||
prefix_len = p + 2 - file_name;
|
||||
|
||||
do
|
||||
{
|
||||
char c = *p++;
|
||||
if (ISSLASH (c))
|
||||
break;
|
||||
}
|
||||
while (*p);
|
||||
}
|
||||
|
||||
for (p = file_name + prefix_len; ISSLASH (*p); p++)
|
||||
continue;
|
||||
prefix_len = p - file_name;
|
||||
|
||||
if (prefix_len)
|
||||
{
|
||||
char *prefix = alloca (prefix_len + 1);
|
||||
memcpy (prefix, file_name, prefix_len);
|
||||
prefix[prefix_len] = '\0';
|
||||
|
||||
if (hash_string_insert (&prefix_table[link_target], prefix))
|
||||
{
|
||||
static char const *const diagnostic[] =
|
||||
{
|
||||
N_("Removing leading `%s' from member names"),
|
||||
N_("Removing leading `%s' from hard link targets")
|
||||
};
|
||||
WARN ((0, 0, _(diagnostic[link_target]), prefix));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! *p)
|
||||
{
|
||||
if (p == file_name)
|
||||
{
|
||||
static char const *const diagnostic[] =
|
||||
{
|
||||
N_("Substituting `.' for empty member name"),
|
||||
N_("Substituting `.' for empty hard link target")
|
||||
};
|
||||
WARN ((0, 0, "%s", _(diagnostic[link_target])));
|
||||
}
|
||||
|
||||
p = ".";
|
||||
}
|
||||
|
||||
return (char *) p;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/* quote.c - quote arguments for output
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com> */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "quotearg.h"
|
||||
#include "quote.h"
|
||||
|
||||
/* Return an unambiguous printable representation of NAME,
|
||||
allocated in slot N, suitable for diagnostics. */
|
||||
char const *
|
||||
quote_n (int n, char const *name)
|
||||
{
|
||||
return quotearg_n_style (n, locale_quoting_style, name);
|
||||
}
|
||||
|
||||
/* Return an unambiguous printable representation of NAME,
|
||||
suitable for diagnostics. */
|
||||
char const *
|
||||
quote (char const *name)
|
||||
{
|
||||
return quote_n (0, name);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
/* quote.h - prototypes for quote.c
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
char const *quote_n (int n, char const *name);
|
||||
char const *quote (char const *name);
|
@ -1,697 +0,0 @@
|
||||
/* quotearg.c - quote arguments for output
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com> */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "quotearg.h"
|
||||
|
||||
#include "xalloc.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include "gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
#define N_(msgid) msgid
|
||||
|
||||
#if !HAVE_MBRTOWC
|
||||
/* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the
|
||||
other macros are defined only for documentation and to satisfy C
|
||||
syntax. */
|
||||
# undef MB_CUR_MAX
|
||||
# define MB_CUR_MAX 1
|
||||
# undef mbstate_t
|
||||
# define mbstate_t int
|
||||
# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
|
||||
# define iswprint(wc) isprint ((unsigned char) (wc))
|
||||
# undef HAVE_MBSINIT
|
||||
#endif
|
||||
|
||||
#if !defined mbsinit && !HAVE_MBSINIT
|
||||
# define mbsinit(ps) 1
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
|
||||
#define INT_BITS (sizeof (int) * CHAR_BIT)
|
||||
|
||||
struct quoting_options
|
||||
{
|
||||
/* Basic quoting style. */
|
||||
enum quoting_style style;
|
||||
|
||||
/* Quote the characters indicated by this bit vector even if the
|
||||
quoting style would not normally require them to be quoted. */
|
||||
unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
|
||||
};
|
||||
|
||||
/* Names of quoting styles. */
|
||||
char const *const quoting_style_args[] =
|
||||
{
|
||||
"literal",
|
||||
"shell",
|
||||
"shell-always",
|
||||
"c",
|
||||
"escape",
|
||||
"locale",
|
||||
"clocale",
|
||||
0
|
||||
};
|
||||
|
||||
/* Correspondences to quoting style names. */
|
||||
enum quoting_style const quoting_style_vals[] =
|
||||
{
|
||||
literal_quoting_style,
|
||||
shell_quoting_style,
|
||||
shell_always_quoting_style,
|
||||
c_quoting_style,
|
||||
escape_quoting_style,
|
||||
locale_quoting_style,
|
||||
clocale_quoting_style
|
||||
};
|
||||
|
||||
/* The default quoting options. */
|
||||
static struct quoting_options default_quoting_options;
|
||||
|
||||
/* Allocate a new set of quoting options, with contents initially identical
|
||||
to O if O is not null, or to the default if O is null.
|
||||
It is the caller's responsibility to free the result. */
|
||||
struct quoting_options *
|
||||
clone_quoting_options (struct quoting_options *o)
|
||||
{
|
||||
int e = errno;
|
||||
struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
|
||||
sizeof *o);
|
||||
errno = e;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Get the value of O's quoting style. If O is null, use the default. */
|
||||
enum quoting_style
|
||||
get_quoting_style (struct quoting_options *o)
|
||||
{
|
||||
return (o ? o : &default_quoting_options)->style;
|
||||
}
|
||||
|
||||
/* In O (or in the default if O is null),
|
||||
set the value of the quoting style to S. */
|
||||
void
|
||||
set_quoting_style (struct quoting_options *o, enum quoting_style s)
|
||||
{
|
||||
(o ? o : &default_quoting_options)->style = s;
|
||||
}
|
||||
|
||||
/* In O (or in the default if O is null),
|
||||
set the value of the quoting options for character C to I.
|
||||
Return the old value. Currently, the only values defined for I are
|
||||
0 (the default) and 1 (which means to quote the character even if
|
||||
it would not otherwise be quoted). */
|
||||
int
|
||||
set_char_quoting (struct quoting_options *o, char c, int i)
|
||||
{
|
||||
unsigned char uc = c;
|
||||
unsigned int *p =
|
||||
(o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
|
||||
int shift = uc % INT_BITS;
|
||||
int r = (*p >> shift) & 1;
|
||||
*p ^= ((i & 1) ^ r) << shift;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* MSGID approximates a quotation mark. Return its translation if it
|
||||
has one; otherwise, return either it or "\"", depending on S. */
|
||||
static char const *
|
||||
gettext_quote (char const *msgid, enum quoting_style s)
|
||||
{
|
||||
char const *translation = _(msgid);
|
||||
if (translation == msgid && s == clocale_quoting_style)
|
||||
translation = "\"";
|
||||
return translation;
|
||||
}
|
||||
|
||||
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
|
||||
argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
|
||||
non-quoting-style part of O to control quoting.
|
||||
Terminate the output with a null character, and return the written
|
||||
size of the output, not counting the terminating null.
|
||||
If BUFFERSIZE is too small to store the output string, return the
|
||||
value that would have been returned had BUFFERSIZE been large enough.
|
||||
If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
|
||||
|
||||
This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
|
||||
ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
|
||||
style specified by O, and O may not be null. */
|
||||
|
||||
static size_t
|
||||
quotearg_buffer_restyled (char *buffer, size_t buffersize,
|
||||
char const *arg, size_t argsize,
|
||||
enum quoting_style quoting_style,
|
||||
struct quoting_options const *o)
|
||||
{
|
||||
size_t i;
|
||||
size_t len = 0;
|
||||
char const *quote_string = 0;
|
||||
size_t quote_string_len = 0;
|
||||
bool backslash_escapes = false;
|
||||
bool unibyte_locale = MB_CUR_MAX == 1;
|
||||
|
||||
#define STORE(c) \
|
||||
do \
|
||||
{ \
|
||||
if (len < buffersize) \
|
||||
buffer[len] = (c); \
|
||||
len++; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
switch (quoting_style)
|
||||
{
|
||||
case c_quoting_style:
|
||||
STORE ('"');
|
||||
backslash_escapes = true;
|
||||
quote_string = "\"";
|
||||
quote_string_len = 1;
|
||||
break;
|
||||
|
||||
case escape_quoting_style:
|
||||
backslash_escapes = true;
|
||||
break;
|
||||
|
||||
case locale_quoting_style:
|
||||
case clocale_quoting_style:
|
||||
{
|
||||
/* TRANSLATORS:
|
||||
Get translations for open and closing quotation marks.
|
||||
|
||||
The message catalog should translate "`" to a left
|
||||
quotation mark suitable for the locale, and similarly for
|
||||
"'". If the catalog has no translation,
|
||||
locale_quoting_style quotes `like this', and
|
||||
clocale_quoting_style quotes "like this".
|
||||
|
||||
For example, an American English Unicode locale should
|
||||
translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
|
||||
should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
|
||||
MARK). A British English Unicode locale should instead
|
||||
translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
|
||||
U+2019 (RIGHT SINGLE QUOTATION MARK), respectively.
|
||||
|
||||
If you don't know what to put here, please see
|
||||
<http://en.wikipedia.org/wiki/Quotation_mark#Glyphs>
|
||||
and use glyphs suitable for your language. */
|
||||
|
||||
char const *left = gettext_quote (N_("`"), quoting_style);
|
||||
char const *right = gettext_quote (N_("'"), quoting_style);
|
||||
for (quote_string = left; *quote_string; quote_string++)
|
||||
STORE (*quote_string);
|
||||
backslash_escapes = true;
|
||||
quote_string = right;
|
||||
quote_string_len = strlen (quote_string);
|
||||
}
|
||||
break;
|
||||
|
||||
case shell_always_quoting_style:
|
||||
STORE ('\'');
|
||||
quote_string = "'";
|
||||
quote_string_len = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++)
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned char esc;
|
||||
|
||||
if (backslash_escapes
|
||||
&& quote_string_len
|
||||
&& i + quote_string_len <= argsize
|
||||
&& memcmp (arg + i, quote_string, quote_string_len) == 0)
|
||||
STORE ('\\');
|
||||
|
||||
c = arg[i];
|
||||
switch (c)
|
||||
{
|
||||
case '\0':
|
||||
if (backslash_escapes)
|
||||
{
|
||||
STORE ('\\');
|
||||
STORE ('0');
|
||||
STORE ('0');
|
||||
c = '0';
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
switch (quoting_style)
|
||||
{
|
||||
case shell_quoting_style:
|
||||
goto use_shell_always_quoting_style;
|
||||
|
||||
case c_quoting_style:
|
||||
if (i + 2 < argsize && arg[i + 1] == '?')
|
||||
switch (arg[i + 2])
|
||||
{
|
||||
case '!': case '\'':
|
||||
case '(': case ')': case '-': case '/':
|
||||
case '<': case '=': case '>':
|
||||
/* Escape the second '?' in what would otherwise be
|
||||
a trigraph. */
|
||||
c = arg[i + 2];
|
||||
i += 2;
|
||||
STORE ('?');
|
||||
STORE ('\\');
|
||||
STORE ('?');
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\a': esc = 'a'; goto c_escape;
|
||||
case '\b': esc = 'b'; goto c_escape;
|
||||
case '\f': esc = 'f'; goto c_escape;
|
||||
case '\n': esc = 'n'; goto c_and_shell_escape;
|
||||
case '\r': esc = 'r'; goto c_and_shell_escape;
|
||||
case '\t': esc = 't'; goto c_and_shell_escape;
|
||||
case '\v': esc = 'v'; goto c_escape;
|
||||
case '\\': esc = c; goto c_and_shell_escape;
|
||||
|
||||
c_and_shell_escape:
|
||||
if (quoting_style == shell_quoting_style)
|
||||
goto use_shell_always_quoting_style;
|
||||
c_escape:
|
||||
if (backslash_escapes)
|
||||
{
|
||||
c = esc;
|
||||
goto store_escape;
|
||||
}
|
||||
break;
|
||||
|
||||
case '{': case '}': /* sometimes special if isolated */
|
||||
if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
|
||||
break;
|
||||
/* Fall through. */
|
||||
case '#': case '~':
|
||||
if (i != 0)
|
||||
break;
|
||||
/* Fall through. */
|
||||
case ' ':
|
||||
case '!': /* special in bash */
|
||||
case '"': case '$': case '&':
|
||||
case '(': case ')': case '*': case ';':
|
||||
case '<':
|
||||
case '=': /* sometimes special in 0th or (with "set -k") later args */
|
||||
case '>': case '[':
|
||||
case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
|
||||
case '`': case '|':
|
||||
/* A shell special character. In theory, '$' and '`' could
|
||||
be the first bytes of multibyte characters, which means
|
||||
we should check them with mbrtowc, but in practice this
|
||||
doesn't happen so it's not worth worrying about. */
|
||||
if (quoting_style == shell_quoting_style)
|
||||
goto use_shell_always_quoting_style;
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
switch (quoting_style)
|
||||
{
|
||||
case shell_quoting_style:
|
||||
goto use_shell_always_quoting_style;
|
||||
|
||||
case shell_always_quoting_style:
|
||||
STORE ('\'');
|
||||
STORE ('\\');
|
||||
STORE ('\'');
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '%': case '+': case ',': case '-': case '.': case '/':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5':
|
||||
case '6': case '7': case '8': case '9': case ':':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
||||
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
|
||||
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
|
||||
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
|
||||
case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
|
||||
case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
|
||||
case 'o': case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
|
||||
/* These characters don't cause problems, no matter what the
|
||||
quoting style is. They cannot start multibyte sequences. */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* If we have a multibyte sequence, copy it until we reach
|
||||
its end, find an error, or come back to the initial shift
|
||||
state. For C-like styles, if the sequence has
|
||||
unprintable characters, escape the whole sequence, since
|
||||
we can't easily escape single characters within it. */
|
||||
{
|
||||
/* Length of multibyte sequence found so far. */
|
||||
size_t m;
|
||||
|
||||
bool printable;
|
||||
|
||||
if (unibyte_locale)
|
||||
{
|
||||
m = 1;
|
||||
printable = isprint (c) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mbstate_t mbstate;
|
||||
memset (&mbstate, 0, sizeof mbstate);
|
||||
|
||||
m = 0;
|
||||
printable = true;
|
||||
if (argsize == SIZE_MAX)
|
||||
argsize = strlen (arg);
|
||||
|
||||
do
|
||||
{
|
||||
wchar_t w;
|
||||
size_t bytes = mbrtowc (&w, &arg[i + m],
|
||||
argsize - (i + m), &mbstate);
|
||||
if (bytes == 0)
|
||||
break;
|
||||
else if (bytes == (size_t) -1)
|
||||
{
|
||||
printable = false;
|
||||
break;
|
||||
}
|
||||
else if (bytes == (size_t) -2)
|
||||
{
|
||||
printable = false;
|
||||
while (i + m < argsize && arg[i + m])
|
||||
m++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Work around a bug with older shells that "see" a '\'
|
||||
that is really the 2nd byte of a multibyte character.
|
||||
In practice the problem is limited to ASCII
|
||||
chars >= '@' that are shell special chars. */
|
||||
if ('[' == 0x5b && quoting_style == shell_quoting_style)
|
||||
{
|
||||
size_t j;
|
||||
for (j = 1; j < bytes; j++)
|
||||
switch (arg[i + m + j])
|
||||
{
|
||||
case '[': case '\\': case '^':
|
||||
case '`': case '|':
|
||||
goto use_shell_always_quoting_style;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! iswprint (w))
|
||||
printable = false;
|
||||
m += bytes;
|
||||
}
|
||||
}
|
||||
while (! mbsinit (&mbstate));
|
||||
}
|
||||
|
||||
if (1 < m || (backslash_escapes && ! printable))
|
||||
{
|
||||
/* Output a multibyte sequence, or an escaped
|
||||
unprintable unibyte character. */
|
||||
size_t ilim = i + m;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (backslash_escapes && ! printable)
|
||||
{
|
||||
STORE ('\\');
|
||||
STORE ('0' + (c >> 6));
|
||||
STORE ('0' + ((c >> 3) & 7));
|
||||
c = '0' + (c & 7);
|
||||
}
|
||||
if (ilim <= i + 1)
|
||||
break;
|
||||
STORE (c);
|
||||
c = arg[++i];
|
||||
}
|
||||
|
||||
goto store_c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! (backslash_escapes
|
||||
&& o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
|
||||
goto store_c;
|
||||
|
||||
store_escape:
|
||||
STORE ('\\');
|
||||
|
||||
store_c:
|
||||
STORE (c);
|
||||
}
|
||||
|
||||
if (i == 0 && quoting_style == shell_quoting_style)
|
||||
goto use_shell_always_quoting_style;
|
||||
|
||||
if (quote_string)
|
||||
for (; *quote_string; quote_string++)
|
||||
STORE (*quote_string);
|
||||
|
||||
if (len < buffersize)
|
||||
buffer[len] = '\0';
|
||||
return len;
|
||||
|
||||
use_shell_always_quoting_style:
|
||||
return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
|
||||
shell_always_quoting_style, o);
|
||||
}
|
||||
|
||||
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
|
||||
argument ARG (of size ARGSIZE), using O to control quoting.
|
||||
If O is null, use the default.
|
||||
Terminate the output with a null character, and return the written
|
||||
size of the output, not counting the terminating null.
|
||||
If BUFFERSIZE is too small to store the output string, return the
|
||||
value that would have been returned had BUFFERSIZE been large enough.
|
||||
If ARGSIZE is SIZE_MAX, use the string length of the argument for
|
||||
ARGSIZE. */
|
||||
size_t
|
||||
quotearg_buffer (char *buffer, size_t buffersize,
|
||||
char const *arg, size_t argsize,
|
||||
struct quoting_options const *o)
|
||||
{
|
||||
struct quoting_options const *p = o ? o : &default_quoting_options;
|
||||
int e = errno;
|
||||
size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
|
||||
p->style, p);
|
||||
errno = e;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
|
||||
allocated storage containing the quoted string. */
|
||||
char *
|
||||
quotearg_alloc (char const *arg, size_t argsize,
|
||||
struct quoting_options const *o)
|
||||
{
|
||||
int e = errno;
|
||||
size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1;
|
||||
char *buf = xcharalloc (bufsize);
|
||||
quotearg_buffer (buf, bufsize, arg, argsize, o);
|
||||
errno = e;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* A storage slot with size and pointer to a value. */
|
||||
struct slotvec
|
||||
{
|
||||
size_t size;
|
||||
char *val;
|
||||
};
|
||||
|
||||
/* Preallocate a slot 0 buffer, so that the caller can always quote
|
||||
one small component of a "memory exhausted" message in slot 0. */
|
||||
static char slot0[256];
|
||||
static unsigned int nslots = 1;
|
||||
static struct slotvec slotvec0 = {sizeof slot0, slot0};
|
||||
static struct slotvec *slotvec = &slotvec0;
|
||||
|
||||
void
|
||||
quotearg_free (void)
|
||||
{
|
||||
struct slotvec *sv = slotvec;
|
||||
unsigned int i;
|
||||
for (i = 1; i < nslots; i++)
|
||||
free (sv[i].val);
|
||||
if (sv[0].val != slot0)
|
||||
{
|
||||
free (sv[0].val);
|
||||
slotvec0.size = sizeof slot0;
|
||||
slotvec0.val = slot0;
|
||||
}
|
||||
if (sv != &slotvec0)
|
||||
{
|
||||
free (sv);
|
||||
slotvec = &slotvec0;
|
||||
}
|
||||
nslots = 1;
|
||||
}
|
||||
|
||||
/* Use storage slot N to return a quoted version of argument ARG.
|
||||
ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
|
||||
null-terminated string.
|
||||
OPTIONS specifies the quoting options.
|
||||
The returned value points to static storage that can be
|
||||
reused by the next call to this function with the same value of N.
|
||||
N must be nonnegative. N is deliberately declared with type "int"
|
||||
to allow for future extensions (using negative values). */
|
||||
static char *
|
||||
quotearg_n_options (int n, char const *arg, size_t argsize,
|
||||
struct quoting_options const *options)
|
||||
{
|
||||
int e = errno;
|
||||
|
||||
unsigned int n0 = n;
|
||||
struct slotvec *sv = slotvec;
|
||||
|
||||
if (n < 0)
|
||||
abort ();
|
||||
|
||||
if (nslots <= n0)
|
||||
{
|
||||
/* FIXME: technically, the type of n1 should be `unsigned int',
|
||||
but that evokes an unsuppressible warning from gcc-4.0.1 and
|
||||
older. If gcc ever provides an option to suppress that warning,
|
||||
revert to the original type, so that the test in xalloc_oversized
|
||||
is once again performed only at compile time. */
|
||||
size_t n1 = n0 + 1;
|
||||
bool preallocated = (sv == &slotvec0);
|
||||
|
||||
if (xalloc_oversized (n1, sizeof *sv))
|
||||
xalloc_die ();
|
||||
|
||||
slotvec = sv = xrealloc (preallocated ? NULL : sv, n1 * sizeof *sv);
|
||||
if (preallocated)
|
||||
*sv = slotvec0;
|
||||
memset (sv + nslots, 0, (n1 - nslots) * sizeof *sv);
|
||||
nslots = n1;
|
||||
}
|
||||
|
||||
{
|
||||
size_t size = sv[n].size;
|
||||
char *val = sv[n].val;
|
||||
size_t qsize = quotearg_buffer (val, size, arg, argsize, options);
|
||||
|
||||
if (size <= qsize)
|
||||
{
|
||||
sv[n].size = size = qsize + 1;
|
||||
if (val != slot0)
|
||||
free (val);
|
||||
sv[n].val = val = xcharalloc (size);
|
||||
quotearg_buffer (val, size, arg, argsize, options);
|
||||
}
|
||||
|
||||
errno = e;
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_n (int n, char const *arg)
|
||||
{
|
||||
return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg (char const *arg)
|
||||
{
|
||||
return quotearg_n (0, arg);
|
||||
}
|
||||
|
||||
/* Return quoting options for STYLE, with no extra quoting. */
|
||||
static struct quoting_options
|
||||
quoting_options_from_style (enum quoting_style style)
|
||||
{
|
||||
struct quoting_options o;
|
||||
o.style = style;
|
||||
memset (o.quote_these_too, 0, sizeof o.quote_these_too);
|
||||
return o;
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_n_style (int n, enum quoting_style s, char const *arg)
|
||||
{
|
||||
struct quoting_options const o = quoting_options_from_style (s);
|
||||
return quotearg_n_options (n, arg, SIZE_MAX, &o);
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_n_style_mem (int n, enum quoting_style s,
|
||||
char const *arg, size_t argsize)
|
||||
{
|
||||
struct quoting_options const o = quoting_options_from_style (s);
|
||||
return quotearg_n_options (n, arg, argsize, &o);
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_style (enum quoting_style s, char const *arg)
|
||||
{
|
||||
return quotearg_n_style (0, s, arg);
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_char (char const *arg, char ch)
|
||||
{
|
||||
struct quoting_options options;
|
||||
options = default_quoting_options;
|
||||
set_char_quoting (&options, ch, 1);
|
||||
return quotearg_n_options (0, arg, SIZE_MAX, &options);
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_colon (char const *arg)
|
||||
{
|
||||
return quotearg_char (arg, ':');
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
/* quotearg.h - quote arguments for output
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com> */
|
||||
|
||||
#ifndef QUOTEARG_H_
|
||||
# define QUOTEARG_H_ 1
|
||||
|
||||
# include <stddef.h>
|
||||
|
||||
/* Basic quoting styles. */
|
||||
enum quoting_style
|
||||
{
|
||||
/* Output names as-is (ls --quoting-style=literal). */
|
||||
literal_quoting_style,
|
||||
|
||||
/* Quote names for the shell if they contain shell metacharacters
|
||||
or would cause ambiguous output (ls --quoting-style=shell). */
|
||||
shell_quoting_style,
|
||||
|
||||
/* Quote names for the shell, even if they would normally not
|
||||
require quoting (ls --quoting-style=shell-always). */
|
||||
shell_always_quoting_style,
|
||||
|
||||
/* Quote names as for a C language string (ls --quoting-style=c). */
|
||||
c_quoting_style,
|
||||
|
||||
/* Like c_quoting_style except omit the surrounding double-quote
|
||||
characters (ls --quoting-style=escape). */
|
||||
escape_quoting_style,
|
||||
|
||||
/* Like clocale_quoting_style, but quote `like this' instead of
|
||||
"like this" in the default C locale (ls --quoting-style=locale). */
|
||||
locale_quoting_style,
|
||||
|
||||
/* Like c_quoting_style except use quotation marks appropriate for
|
||||
the locale (ls --quoting-style=clocale). */
|
||||
clocale_quoting_style
|
||||
};
|
||||
|
||||
/* For now, --quoting-style=literal is the default, but this may change. */
|
||||
# ifndef DEFAULT_QUOTING_STYLE
|
||||
# define DEFAULT_QUOTING_STYLE literal_quoting_style
|
||||
# endif
|
||||
|
||||
/* Names of quoting styles and their corresponding values. */
|
||||
extern char const *const quoting_style_args[];
|
||||
extern enum quoting_style const quoting_style_vals[];
|
||||
|
||||
struct quoting_options;
|
||||
|
||||
/* The functions listed below set and use a hidden variable
|
||||
that contains the default quoting style options. */
|
||||
|
||||
/* Allocate a new set of quoting options, with contents initially identical
|
||||
to O if O is not null, or to the default if O is null.
|
||||
It is the caller's responsibility to free the result. */
|
||||
struct quoting_options *clone_quoting_options (struct quoting_options *o);
|
||||
|
||||
/* Get the value of O's quoting style. If O is null, use the default. */
|
||||
enum quoting_style get_quoting_style (struct quoting_options *o);
|
||||
|
||||
/* In O (or in the default if O is null),
|
||||
set the value of the quoting style to S. */
|
||||
void set_quoting_style (struct quoting_options *o, enum quoting_style s);
|
||||
|
||||
/* In O (or in the default if O is null),
|
||||
set the value of the quoting options for character C to I.
|
||||
Return the old value. Currently, the only values defined for I are
|
||||
0 (the default) and 1 (which means to quote the character even if
|
||||
it would not otherwise be quoted). */
|
||||
int set_char_quoting (struct quoting_options *o, char c, int i);
|
||||
|
||||
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
|
||||
argument ARG (of size ARGSIZE), using O to control quoting.
|
||||
If O is null, use the default.
|
||||
Terminate the output with a null character, and return the written
|
||||
size of the output, not counting the terminating null.
|
||||
If BUFFERSIZE is too small to store the output string, return the
|
||||
value that would have been returned had BUFFERSIZE been large enough.
|
||||
If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */
|
||||
size_t quotearg_buffer (char *buffer, size_t buffersize,
|
||||
char const *arg, size_t argsize,
|
||||
struct quoting_options const *o);
|
||||
|
||||
/* Like quotearg_buffer, except return the result in a newly allocated
|
||||
buffer. It is the caller's responsibility to free the result. */
|
||||
char *quotearg_alloc (char const *arg, size_t argsize,
|
||||
struct quoting_options const *o);
|
||||
|
||||
/* Use storage slot N to return a quoted version of the string ARG.
|
||||
Use the default quoting options.
|
||||
The returned value points to static storage that can be
|
||||
reused by the next call to this function with the same value of N.
|
||||
N must be nonnegative. */
|
||||
char *quotearg_n (int n, char const *arg);
|
||||
|
||||
/* Equivalent to quotearg_n (0, ARG). */
|
||||
char *quotearg (char const *arg);
|
||||
|
||||
/* Use style S and storage slot N to return a quoted version of the string ARG.
|
||||
This is like quotearg_n (N, ARG), except that it uses S with no other
|
||||
options to specify the quoting method. */
|
||||
char *quotearg_n_style (int n, enum quoting_style s, char const *arg);
|
||||
|
||||
/* Use style S and storage slot N to return a quoted version of the
|
||||
argument ARG of size ARGSIZE. This is like quotearg_n_style
|
||||
(N, S, ARG), except it can quote null bytes. */
|
||||
char *quotearg_n_style_mem (int n, enum quoting_style s,
|
||||
char const *arg, size_t argsize);
|
||||
|
||||
/* Equivalent to quotearg_n_style (0, S, ARG). */
|
||||
char *quotearg_style (enum quoting_style s, char const *arg);
|
||||
|
||||
/* Like quotearg (ARG), except also quote any instances of CH. */
|
||||
char *quotearg_char (char const *arg, char ch);
|
||||
|
||||
/* Equivalent to quotearg_char (ARG, ':'). */
|
||||
char *quotearg_colon (char const *arg);
|
||||
|
||||
/* Free any dynamically allocated memory. */
|
||||
void quotearg_free (void);
|
||||
|
||||
#endif /* !QUOTEARG_H_ */
|
@ -1,4 +0,0 @@
|
||||
#define LOCALEDIR "/usr/local/share/locale"
|
||||
#ifndef DEFAULT_RMT_COMMAND
|
||||
# define DEFAULT_RMT_COMMAND "/usr/local/libexec/rmt"
|
||||
#endif
|
@ -1,99 +0,0 @@
|
||||
/* Definitions for communicating with a remote tape drive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1996, 1997, 2001, 2003, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
extern char *rmt_command;
|
||||
extern char *rmt_dev_name__;
|
||||
|
||||
int rmt_open__ (const char *, int, int, const char *);
|
||||
int rmt_close__ (int);
|
||||
size_t rmt_read__ (int, char *, size_t);
|
||||
size_t rmt_write__ (int, char *, size_t);
|
||||
off_t rmt_lseek__ (int, off_t, int);
|
||||
int rmt_ioctl__ (int, int, char *);
|
||||
|
||||
extern bool force_local_option;
|
||||
|
||||
/* A filename is remote if it contains a colon not preceded by a slash,
|
||||
to take care of `/:/' which is a shorthand for `/.../<CELL-NAME>/fs'
|
||||
on machines running OSF's Distributing Computing Environment (DCE) and
|
||||
Distributed File System (DFS). However, when --force-local, a
|
||||
filename is never remote. */
|
||||
|
||||
#define _remdev(dev_name) \
|
||||
(!force_local_option && (rmt_dev_name__ = strchr (dev_name, ':')) \
|
||||
&& rmt_dev_name__ > (dev_name) \
|
||||
&& ! memchr (dev_name, '/', rmt_dev_name__ - (dev_name)))
|
||||
|
||||
#define _isrmt(fd) \
|
||||
((fd) >= __REM_BIAS)
|
||||
|
||||
#define __REM_BIAS (1 << 30)
|
||||
|
||||
#ifndef O_CREAT
|
||||
# define O_CREAT 01000
|
||||
#endif
|
||||
|
||||
#define rmtopen(dev_name, oflag, mode, command) \
|
||||
(_remdev (dev_name) ? rmt_open__ (dev_name, oflag, __REM_BIAS, command) \
|
||||
: open (dev_name, oflag, mode))
|
||||
|
||||
#define rmtaccess(dev_name, amode) \
|
||||
(_remdev (dev_name) ? 0 : access (dev_name, amode))
|
||||
|
||||
#define rmtstat(dev_name, buffer) \
|
||||
(_remdev (dev_name) ? (errno = EOPNOTSUPP), -1 : stat (dev_name, buffer))
|
||||
|
||||
#define rmtcreat(dev_name, mode, command) \
|
||||
(_remdev (dev_name) \
|
||||
? rmt_open__ (dev_name, 1 | O_CREAT, __REM_BIAS, command) \
|
||||
: creat (dev_name, mode))
|
||||
|
||||
#define rmtlstat(dev_name, muffer) \
|
||||
(_remdev (dev_name) ? (errno = EOPNOTSUPP), -1 : lstat (dev_name, buffer))
|
||||
|
||||
#define rmtread(fd, buffer, length) \
|
||||
(_isrmt (fd) ? rmt_read__ (fd - __REM_BIAS, buffer, length) \
|
||||
: safe_read (fd, buffer, length))
|
||||
|
||||
#define rmtwrite(fd, buffer, length) \
|
||||
(_isrmt (fd) ? rmt_write__ (fd - __REM_BIAS, buffer, length) \
|
||||
: full_write (fd, buffer, length))
|
||||
|
||||
#define rmtlseek(fd, offset, where) \
|
||||
(_isrmt (fd) ? rmt_lseek__ (fd - __REM_BIAS, offset, where) \
|
||||
: lseek (fd, offset, where))
|
||||
|
||||
#define rmtclose(fd) \
|
||||
(_isrmt (fd) ? rmt_close__ (fd - __REM_BIAS) : close (fd))
|
||||
|
||||
#define rmtioctl(fd, request, argument) \
|
||||
(_isrmt (fd) ? rmt_ioctl__ (fd - __REM_BIAS, request, argument) \
|
||||
: ioctl (fd, request, argument))
|
||||
|
||||
#define rmtdup(fd) \
|
||||
(_isrmt (fd) ? (errno = EOPNOTSUPP), -1 : dup (fd))
|
||||
|
||||
#define rmtfstat(fd, buffer) \
|
||||
(_isrmt (fd) ? (errno = EOPNOTSUPP), -1 : fstat (fd, buffer))
|
||||
|
||||
#define rmtfcntl(cd, command, argument) \
|
||||
(_isrmt (fd) ? (errno = EOPNOTSUPP), -1 : fcntl (fd, command, argument))
|
||||
|
||||
#define rmtisatty(fd) \
|
||||
(_isrmt (fd) ? 0 : isatty (fd))
|
@ -1,741 +0,0 @@
|
||||
/* Functions for communicating with a remote tape drive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004,
|
||||
2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 rmt* calls
|
||||
into macros for speed by Jay Fenlason. Use -DWITH_REXEC for rexec
|
||||
code, courtesy of Dan Kegel. */
|
||||
|
||||
#include "system.h"
|
||||
#include "system-ioctl.h"
|
||||
|
||||
#include <safe-read.h>
|
||||
#include <full-write.h>
|
||||
|
||||
/* Try hard to get EOPNOTSUPP defined. 486/ISC has it in net/errno.h,
|
||||
3B2/SVR3 has it in sys/inet.h. Otherwise, like on MSDOS, use EINVAL. */
|
||||
|
||||
#ifndef EOPNOTSUPP
|
||||
# if HAVE_NET_ERRNO_H
|
||||
# include <net/errno.h>
|
||||
# endif
|
||||
# if HAVE_SYS_INET_H
|
||||
# include <sys/inet.h>
|
||||
# endif
|
||||
# ifndef EOPNOTSUPP
|
||||
# define EOPNOTSUPP EINVAL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#if HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <rmt.h>
|
||||
#include <rmt-command.h>
|
||||
|
||||
/* Exit status if exec errors. */
|
||||
#define EXIT_ON_EXEC_ERROR 128
|
||||
|
||||
/* FIXME: Size of buffers for reading and writing commands to rmt. */
|
||||
#define COMMAND_BUFFER_SIZE 64
|
||||
|
||||
#ifndef RETSIGTYPE
|
||||
# define RETSIGTYPE void
|
||||
#endif
|
||||
|
||||
/* FIXME: Maximum number of simultaneous remote tape connections. */
|
||||
#define MAXUNIT 4
|
||||
|
||||
#define PREAD 0 /* read file descriptor from pipe() */
|
||||
#define PWRITE 1 /* write file descriptor from pipe() */
|
||||
|
||||
/* Return the parent's read side of remote tape connection Fd. */
|
||||
#define READ_SIDE(Fd) (from_remote[Fd][PREAD])
|
||||
|
||||
/* Return the parent's write side of remote tape connection Fd. */
|
||||
#define WRITE_SIDE(Fd) (to_remote[Fd][PWRITE])
|
||||
|
||||
/* The pipes for receiving data from remote tape drives. */
|
||||
static int from_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
|
||||
|
||||
/* The pipes for sending data to remote tape drives. */
|
||||
static int to_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
|
||||
|
||||
char *rmt_command = DEFAULT_RMT_COMMAND;
|
||||
|
||||
/* Temporary variable used by macros in rmt.h. */
|
||||
char *rmt_dev_name__;
|
||||
|
||||
/* If true, always consider file names to be local, even if they contain
|
||||
colons */
|
||||
bool force_local_option;
|
||||
|
||||
|
||||
|
||||
/* Close remote tape connection HANDLE, and reset errno to ERRNO_VALUE. */
|
||||
static void
|
||||
_rmt_shutdown (int handle, int errno_value)
|
||||
{
|
||||
close (READ_SIDE (handle));
|
||||
close (WRITE_SIDE (handle));
|
||||
READ_SIDE (handle) = -1;
|
||||
WRITE_SIDE (handle) = -1;
|
||||
errno = errno_value;
|
||||
}
|
||||
|
||||
/* Attempt to perform the remote tape command specified in BUFFER on
|
||||
remote tape connection HANDLE. Return 0 if successful, -1 on
|
||||
error. */
|
||||
static int
|
||||
do_command (int handle, const char *buffer)
|
||||
{
|
||||
/* Save the current pipe handler and try to make the request. */
|
||||
|
||||
size_t length = strlen (buffer);
|
||||
RETSIGTYPE (*pipe_handler) () = signal (SIGPIPE, SIG_IGN);
|
||||
ssize_t written = full_write (WRITE_SIDE (handle), buffer, length);
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
|
||||
if (written == length)
|
||||
return 0;
|
||||
|
||||
/* Something went wrong. Close down and go home. */
|
||||
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_status_string (int handle, char *command_buffer)
|
||||
{
|
||||
char *cursor;
|
||||
int counter;
|
||||
|
||||
/* Read the reply command line. */
|
||||
|
||||
for (counter = 0, cursor = command_buffer;
|
||||
counter < COMMAND_BUFFER_SIZE;
|
||||
counter++, cursor++)
|
||||
{
|
||||
if (safe_read (READ_SIDE (handle), cursor, 1) != 1)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
if (*cursor == '\n')
|
||||
{
|
||||
*cursor = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter == COMMAND_BUFFER_SIZE)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check the return status. */
|
||||
|
||||
for (cursor = command_buffer; *cursor; cursor++)
|
||||
if (*cursor != ' ')
|
||||
break;
|
||||
|
||||
if (*cursor == 'E' || *cursor == 'F')
|
||||
{
|
||||
/* Skip the error message line. */
|
||||
|
||||
/* FIXME: there is better to do than merely ignoring error messages
|
||||
coming from the remote end. Translate them, too... */
|
||||
|
||||
{
|
||||
char character;
|
||||
|
||||
while (safe_read (READ_SIDE (handle), &character, 1) == 1)
|
||||
if (character == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
errno = atoi (cursor + 1);
|
||||
|
||||
if (*cursor == 'F')
|
||||
_rmt_shutdown (handle, errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for mis-synced pipes. */
|
||||
|
||||
if (*cursor != 'A')
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Got an `A' (success) response. */
|
||||
|
||||
return cursor + 1;
|
||||
}
|
||||
|
||||
/* Read and return the status from remote tape connection HANDLE. If
|
||||
an error occurred, return -1 and set errno. */
|
||||
static long int
|
||||
get_status (int handle)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
const char *status = get_status_string (handle, command_buffer);
|
||||
if (status)
|
||||
{
|
||||
long int result = atol (status);
|
||||
if (0 <= result)
|
||||
return result;
|
||||
errno = EIO;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static off_t
|
||||
get_status_off (int handle)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
const char *status = get_status_string (handle, command_buffer);
|
||||
|
||||
if (! status)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
/* Parse status, taking care to check for overflow.
|
||||
We can't use standard functions,
|
||||
since off_t might be longer than long. */
|
||||
|
||||
off_t count = 0;
|
||||
int negative;
|
||||
|
||||
for (; *status == ' ' || *status == '\t'; status++)
|
||||
continue;
|
||||
|
||||
negative = *status == '-';
|
||||
status += negative || *status == '+';
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int digit = *status++ - '0';
|
||||
if (9 < (unsigned) digit)
|
||||
break;
|
||||
else
|
||||
{
|
||||
off_t c10 = 10 * count;
|
||||
off_t nc = negative ? c10 - digit : c10 + digit;
|
||||
if (c10 / 10 != count || (negative ? c10 < nc : nc < c10))
|
||||
return -1;
|
||||
count = nc;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_REXEC
|
||||
|
||||
/* 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 zero, 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 (char *host, char *user)
|
||||
{
|
||||
int saved_stdin = dup (STDIN_FILENO);
|
||||
int saved_stdout = dup (STDOUT_FILENO);
|
||||
struct servent *rexecserv;
|
||||
int result;
|
||||
|
||||
/* 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))
|
||||
freopen ("/dev/null", "r", stdin);
|
||||
if (! freopen ("/dev/tty", "w", stdout))
|
||||
freopen ("/dev/null", "w", stdout);
|
||||
|
||||
if (rexecserv = getservbyname ("exec", "tcp"), !rexecserv)
|
||||
error (EXIT_ON_EXEC_ERROR, 0, _("exec/tcp: Service not available"));
|
||||
|
||||
result = rexec (&host, rexecserv->s_port, user, 0, rmt_command, 0);
|
||||
if (fclose (stdin) == EOF)
|
||||
error (0, errno, _("stdin"));
|
||||
fdopen (saved_stdin, "r");
|
||||
if (fclose (stdout) == EOF)
|
||||
error (0, errno, _("stdout"));
|
||||
fdopen (saved_stdout, "w");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* WITH_REXEC */
|
||||
|
||||
/* Place into BUF a string representing OFLAG, which must be suitable
|
||||
as argument 2 of `open'. BUF must be large enough to hold the
|
||||
result. This function should generate a string that decode_oflag
|
||||
can parse. */
|
||||
static void
|
||||
encode_oflag (char *buf, int oflag)
|
||||
{
|
||||
sprintf (buf, "%d ", oflag);
|
||||
|
||||
switch (oflag & O_ACCMODE)
|
||||
{
|
||||
case O_RDONLY: strcat (buf, "O_RDONLY"); break;
|
||||
case O_RDWR: strcat (buf, "O_RDWR"); break;
|
||||
case O_WRONLY: strcat (buf, "O_WRONLY"); break;
|
||||
default: abort ();
|
||||
}
|
||||
|
||||
#ifdef O_APPEND
|
||||
if (oflag & O_APPEND) strcat (buf, "|O_APPEND");
|
||||
#endif
|
||||
if (oflag & O_CREAT) strcat (buf, "|O_CREAT");
|
||||
#ifdef O_DSYNC
|
||||
if (oflag & O_DSYNC) strcat (buf, "|O_DSYNC");
|
||||
#endif
|
||||
if (oflag & O_EXCL) strcat (buf, "|O_EXCL");
|
||||
#ifdef O_LARGEFILE
|
||||
if (oflag & O_LARGEFILE) strcat (buf, "|O_LARGEFILE");
|
||||
#endif
|
||||
#ifdef O_NOCTTY
|
||||
if (oflag & O_NOCTTY) strcat (buf, "|O_NOCTTY");
|
||||
#endif
|
||||
if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK");
|
||||
#ifdef O_RSYNC
|
||||
if (oflag & O_RSYNC) strcat (buf, "|O_RSYNC");
|
||||
#endif
|
||||
#ifdef O_SYNC
|
||||
if (oflag & O_SYNC) strcat (buf, "|O_SYNC");
|
||||
#endif
|
||||
if (oflag & O_TRUNC) strcat (buf, "|O_TRUNC");
|
||||
}
|
||||
|
||||
/* Open a file (a magnetic tape device?) on the system specified in
|
||||
FILE_NAME, as the given user. FILE_NAME has the form `[USER@]HOST:FILE'.
|
||||
OPEN_MODE is O_RDONLY, O_WRONLY, etc. If successful, return the
|
||||
remote pipe number plus BIAS. REMOTE_SHELL may be overridden. On
|
||||
error, return -1. */
|
||||
int
|
||||
rmt_open__ (const char *file_name, int open_mode, int bias,
|
||||
const char *remote_shell)
|
||||
{
|
||||
int remote_pipe_number; /* pseudo, biased file descriptor */
|
||||
char *file_name_copy; /* copy of file_name string */
|
||||
char *remote_host; /* remote host name */
|
||||
char *remote_file; /* remote file name (often a device) */
|
||||
char *remote_user; /* remote user name */
|
||||
|
||||
/* Find an unused pair of file descriptors. */
|
||||
|
||||
for (remote_pipe_number = 0;
|
||||
remote_pipe_number < MAXUNIT;
|
||||
remote_pipe_number++)
|
||||
if (READ_SIDE (remote_pipe_number) == -1
|
||||
&& WRITE_SIDE (remote_pipe_number) == -1)
|
||||
break;
|
||||
|
||||
if (remote_pipe_number == MAXUNIT)
|
||||
{
|
||||
errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pull apart the system and device, and optional user. */
|
||||
|
||||
{
|
||||
char *cursor;
|
||||
|
||||
file_name_copy = xstrdup (file_name);
|
||||
remote_host = file_name_copy;
|
||||
remote_user = 0;
|
||||
remote_file = 0;
|
||||
|
||||
for (cursor = file_name_copy; *cursor; cursor++)
|
||||
switch (*cursor)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
/* Do not allow newlines in the file_name, since the protocol
|
||||
uses newline delimiters. */
|
||||
free (file_name_copy);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
|
||||
case '@':
|
||||
if (!remote_user)
|
||||
{
|
||||
remote_user = remote_host;
|
||||
*cursor = '\0';
|
||||
remote_host = cursor + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ':':
|
||||
if (!remote_file)
|
||||
{
|
||||
*cursor = '\0';
|
||||
remote_file = cursor + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Should somewhat validate the decoding, here. */
|
||||
|
||||
if (remote_user && *remote_user == '\0')
|
||||
remote_user = 0;
|
||||
|
||||
#if WITH_REXEC
|
||||
|
||||
/* Execute the remote command using rexec. */
|
||||
|
||||
READ_SIDE (remote_pipe_number) = _rmt_rexec (remote_host, remote_user);
|
||||
if (READ_SIDE (remote_pipe_number) < 0)
|
||||
{
|
||||
int e = errno;
|
||||
free (file_name_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WRITE_SIDE (remote_pipe_number) = READ_SIDE (remote_pipe_number);
|
||||
|
||||
#else /* not WITH_REXEC */
|
||||
{
|
||||
const char *remote_shell_basename;
|
||||
pid_t status;
|
||||
|
||||
/* Identify the remote command to be executed. */
|
||||
|
||||
if (!remote_shell)
|
||||
{
|
||||
#ifdef REMOTE_SHELL
|
||||
remote_shell = REMOTE_SHELL;
|
||||
#else
|
||||
free (file_name_copy);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
remote_shell_basename = base_name (remote_shell);
|
||||
|
||||
/* Set up the pipes for the `rsh' command, and fork. */
|
||||
|
||||
if (pipe (to_remote[remote_pipe_number]) == -1
|
||||
|| pipe (from_remote[remote_pipe_number]) == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (file_name_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = fork ();
|
||||
if (status == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (file_name_copy);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
/* Child. */
|
||||
|
||||
close (STDIN_FILENO);
|
||||
dup (to_remote[remote_pipe_number][PREAD]);
|
||||
close (to_remote[remote_pipe_number][PREAD]);
|
||||
close (to_remote[remote_pipe_number][PWRITE]);
|
||||
|
||||
close (STDOUT_FILENO);
|
||||
dup (from_remote[remote_pipe_number][PWRITE]);
|
||||
close (from_remote[remote_pipe_number][PREAD]);
|
||||
close (from_remote[remote_pipe_number][PWRITE]);
|
||||
|
||||
sys_reset_uid_gid ();
|
||||
|
||||
if (remote_user)
|
||||
execl (remote_shell, remote_shell_basename, remote_host,
|
||||
"-l", remote_user, rmt_command, (char *) 0);
|
||||
else
|
||||
execl (remote_shell, remote_shell_basename, remote_host,
|
||||
rmt_command, (char *) 0);
|
||||
|
||||
/* Bad problems if we get here. */
|
||||
|
||||
/* In a previous version, _exit was used here instead of exit. */
|
||||
error (EXIT_ON_EXEC_ERROR, errno, _("Cannot execute remote shell"));
|
||||
}
|
||||
|
||||
/* Parent. */
|
||||
|
||||
close (from_remote[remote_pipe_number][PWRITE]);
|
||||
close (to_remote[remote_pipe_number][PREAD]);
|
||||
}
|
||||
#endif /* not WITH_REXEC */
|
||||
|
||||
/* Attempt to open the tape device. */
|
||||
|
||||
{
|
||||
size_t remote_file_len = strlen (remote_file);
|
||||
char *command_buffer = xmalloc (remote_file_len + 1000);
|
||||
sprintf (command_buffer, "O%s\n", remote_file);
|
||||
encode_oflag (command_buffer + remote_file_len + 2, open_mode);
|
||||
strcat (command_buffer, "\n");
|
||||
if (do_command (remote_pipe_number, command_buffer) == -1
|
||||
|| get_status (remote_pipe_number) == -1)
|
||||
{
|
||||
int e = errno;
|
||||
free (command_buffer);
|
||||
free (file_name_copy);
|
||||
_rmt_shutdown (remote_pipe_number, e);
|
||||
return -1;
|
||||
}
|
||||
free (command_buffer);
|
||||
}
|
||||
|
||||
free (file_name_copy);
|
||||
return remote_pipe_number + bias;
|
||||
}
|
||||
|
||||
/* Close remote tape connection HANDLE and shut down. Return 0 if
|
||||
successful, -1 on error. */
|
||||
int
|
||||
rmt_close__ (int handle)
|
||||
{
|
||||
long int status;
|
||||
|
||||
if (do_command (handle, "C\n") == -1)
|
||||
return -1;
|
||||
|
||||
status = get_status (handle);
|
||||
_rmt_shutdown (handle, errno);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Read up to LENGTH bytes into BUFFER from remote tape connection HANDLE.
|
||||
Return the number of bytes read on success, SAFE_READ_ERROR on error. */
|
||||
size_t
|
||||
rmt_read__ (int handle, char *buffer, size_t length)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
size_t status;
|
||||
size_t rlen;
|
||||
size_t counter;
|
||||
|
||||
sprintf (command_buffer, "R%lu\n", (unsigned long) length);
|
||||
if (do_command (handle, command_buffer) == -1
|
||||
|| (status = get_status (handle)) == SAFE_READ_ERROR
|
||||
|| status > length)
|
||||
return SAFE_READ_ERROR;
|
||||
|
||||
for (counter = 0; counter < status; counter += rlen, buffer += rlen)
|
||||
{
|
||||
rlen = safe_read (READ_SIDE (handle), buffer, status - counter);
|
||||
if (rlen == SAFE_READ_ERROR || rlen == 0)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return SAFE_READ_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Write LENGTH bytes from BUFFER to remote tape connection HANDLE.
|
||||
Return the number of bytes written. */
|
||||
size_t
|
||||
rmt_write__ (int handle, char *buffer, size_t length)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
RETSIGTYPE (*pipe_handler) ();
|
||||
size_t written;
|
||||
|
||||
sprintf (command_buffer, "W%lu\n", (unsigned long) length);
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return 0;
|
||||
|
||||
pipe_handler = signal (SIGPIPE, SIG_IGN);
|
||||
written = full_write (WRITE_SIDE (handle), buffer, length);
|
||||
signal (SIGPIPE, pipe_handler);
|
||||
if (written == length)
|
||||
{
|
||||
long int r = get_status (handle);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
if (r == length)
|
||||
return length;
|
||||
written = r;
|
||||
}
|
||||
|
||||
/* Write error. */
|
||||
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return written;
|
||||
}
|
||||
|
||||
/* Perform an imitation lseek operation on remote tape connection
|
||||
HANDLE. Return the new file offset if successful, -1 if on error. */
|
||||
off_t
|
||||
rmt_lseek__ (int handle, off_t offset, int whence)
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
char operand_buffer[UINTMAX_STRSIZE_BOUND];
|
||||
uintmax_t u = offset < 0 ? - (uintmax_t) offset : (uintmax_t) offset;
|
||||
char *p = operand_buffer + sizeof operand_buffer;
|
||||
|
||||
*--p = 0;
|
||||
do
|
||||
*--p = '0' + (int) (u % 10);
|
||||
while ((u /= 10) != 0);
|
||||
if (offset < 0)
|
||||
*--p = '-';
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET: whence = 0; break;
|
||||
case SEEK_CUR: whence = 1; break;
|
||||
case SEEK_END: whence = 2; break;
|
||||
default: abort ();
|
||||
}
|
||||
|
||||
sprintf (command_buffer, "L%s\n%d\n", p, whence);
|
||||
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return -1;
|
||||
|
||||
return get_status_off (handle);
|
||||
}
|
||||
|
||||
/* Perform a raw tape operation on remote tape connection HANDLE.
|
||||
Return the results of the ioctl, or -1 on error. */
|
||||
int
|
||||
rmt_ioctl__ (int handle, int operation, char *argument)
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
default:
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
|
||||
#ifdef MTIOCTOP
|
||||
case MTIOCTOP:
|
||||
{
|
||||
char command_buffer[COMMAND_BUFFER_SIZE];
|
||||
char operand_buffer[UINTMAX_STRSIZE_BOUND];
|
||||
uintmax_t u = (((struct mtop *) argument)->mt_count < 0
|
||||
? - (uintmax_t) ((struct mtop *) argument)->mt_count
|
||||
: (uintmax_t) ((struct mtop *) argument)->mt_count);
|
||||
char *p = operand_buffer + sizeof operand_buffer;
|
||||
|
||||
*--p = 0;
|
||||
do
|
||||
*--p = '0' + (int) (u % 10);
|
||||
while ((u /= 10) != 0);
|
||||
if (((struct mtop *) argument)->mt_count < 0)
|
||||
*--p = '-';
|
||||
|
||||
/* MTIOCTOP is the easy one. Nothing is transferred in binary. */
|
||||
|
||||
sprintf (command_buffer, "I%d\n%s\n",
|
||||
((struct mtop *) argument)->mt_op, p);
|
||||
if (do_command (handle, command_buffer) == -1)
|
||||
return -1;
|
||||
|
||||
return get_status (handle);
|
||||
}
|
||||
#endif /* MTIOCTOP */
|
||||
|
||||
#ifdef MTIOCGET
|
||||
case MTIOCGET:
|
||||
{
|
||||
ssize_t status;
|
||||
size_t counter;
|
||||
|
||||
/* 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 (do_command (handle, "S") == -1
|
||||
|| (status = get_status (handle), status == -1))
|
||||
return -1;
|
||||
|
||||
for (; status > 0; status -= counter, argument += counter)
|
||||
{
|
||||
counter = safe_read (READ_SIDE (handle), argument, status);
|
||||
if (counter == SAFE_READ_ERROR || counter == 0)
|
||||
{
|
||||
_rmt_shutdown (handle, EIO);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for byte position. mt_type (or mt_model) 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 *) argument)->MTIO_CHECK_FIELD < 256)
|
||||
return 0;
|
||||
|
||||
for (counter = 0; counter < status; counter += 2)
|
||||
{
|
||||
char copy = argument[counter];
|
||||
|
||||
argument[counter] = argument[counter + 1];
|
||||
argument[counter + 1] = copy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MTIOCGET */
|
||||
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/* An interface to read and write that retries after interrupts.
|
||||
|
||||
Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#ifdef SAFE_WRITE
|
||||
# include "safe-write.h"
|
||||
#else
|
||||
# include "safe-read.h"
|
||||
#endif
|
||||
|
||||
/* Get ssize_t. */
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef EINTR
|
||||
# define IS_EINTR(x) ((x) == EINTR)
|
||||
#else
|
||||
# define IS_EINTR(x) 0
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef SAFE_WRITE
|
||||
# define safe_rw safe_write
|
||||
# define rw write
|
||||
#else
|
||||
# define safe_rw safe_read
|
||||
# define rw read
|
||||
# undef const
|
||||
# define const /* empty */
|
||||
#endif
|
||||
|
||||
/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if
|
||||
interrupted. Return the actual number of bytes read(written), zero for EOF,
|
||||
or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */
|
||||
size_t
|
||||
safe_rw (int fd, void const *buf, size_t count)
|
||||
{
|
||||
/* Work around a bug in Tru64 5.1. Attempting to read more than
|
||||
INT_MAX bytes fails with errno == EINVAL. See
|
||||
<http://lists.gnu.org/archive/html/bug-gnu-utils/2002-04/msg00010.html>.
|
||||
When decreasing COUNT, keep it block-aligned. */
|
||||
enum { BUGGY_READ_MAXIMUM = INT_MAX & ~8191 };
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ssize_t result = rw (fd, buf, count);
|
||||
|
||||
if (0 <= result)
|
||||
return result;
|
||||
else if (IS_EINTR (errno))
|
||||
continue;
|
||||
else if (errno == EINVAL && BUGGY_READ_MAXIMUM < count)
|
||||
count = BUGGY_READ_MAXIMUM;
|
||||
else
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/* An interface to read() that retries after interrupts.
|
||||
Copyright (C) 2002, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define SAFE_READ_ERROR ((size_t) -1)
|
||||
|
||||
/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted.
|
||||
Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR
|
||||
upon error. */
|
||||
extern size_t safe_read (int fd, void *buf, size_t count);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,19 +0,0 @@
|
||||
/* An interface to write that retries after interrupts.
|
||||
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define SAFE_WRITE
|
||||
#include "safe-read.c"
|
@ -1,25 +0,0 @@
|
||||
/* An interface to write() that retries after interrupts.
|
||||
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define SAFE_WRITE_ERROR ((size_t) -1)
|
||||
|
||||
/* Write up to COUNT bytes at BUF to descriptor FD, retrying if interrupted.
|
||||
Return the actual number of bytes written, zero for EOF, or SAFE_WRITE_ERROR
|
||||
upon error. */
|
||||
extern size_t safe_write (int fd, const void *buf, size_t count);
|
@ -1,137 +0,0 @@
|
||||
/* savedir.c -- save the list of files in a directory in a string
|
||||
|
||||
Copyright (C) 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
|
||||
2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "savedir.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#ifndef _D_EXACT_NAMLEN
|
||||
# define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "openat.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#ifndef NAME_SIZE_DEFAULT
|
||||
# define NAME_SIZE_DEFAULT 512
|
||||
#endif
|
||||
|
||||
/* The results of opendir() in this file are not used with dirfd and fchdir,
|
||||
therefore save some unnecessary work in fchdir.c. */
|
||||
#undef opendir
|
||||
#undef closedir
|
||||
|
||||
/* Return a freshly allocated string containing the file names
|
||||
in directory DIRP, separated by '\0' characters;
|
||||
the end is marked by two '\0' characters in a row.
|
||||
Return NULL (setting errno) if DIRP cannot be read or closed.
|
||||
If DIRP is NULL, return NULL without affecting errno. */
|
||||
|
||||
static char *
|
||||
savedirstream (DIR *dirp)
|
||||
{
|
||||
char *name_space;
|
||||
size_t allocated = NAME_SIZE_DEFAULT;
|
||||
size_t used = 0;
|
||||
int save_errno;
|
||||
|
||||
if (dirp == NULL)
|
||||
return NULL;
|
||||
|
||||
name_space = xmalloc (allocated);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
struct dirent const *dp;
|
||||
char const *entry;
|
||||
|
||||
errno = 0;
|
||||
dp = readdir (dirp);
|
||||
if (! dp)
|
||||
break;
|
||||
|
||||
/* Skip "", ".", and "..". "" is returned by at least one buggy
|
||||
implementation: Solaris 2.4 readdir on NFS file systems. */
|
||||
entry = dp->d_name;
|
||||
if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
|
||||
{
|
||||
size_t entry_size = _D_EXACT_NAMLEN (dp) + 1;
|
||||
if (used + entry_size < used)
|
||||
xalloc_die ();
|
||||
if (allocated <= used + entry_size)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (2 * allocated < allocated)
|
||||
xalloc_die ();
|
||||
allocated *= 2;
|
||||
}
|
||||
while (allocated <= used + entry_size);
|
||||
|
||||
name_space = xrealloc (name_space, allocated);
|
||||
}
|
||||
memcpy (name_space + used, entry, entry_size);
|
||||
used += entry_size;
|
||||
}
|
||||
}
|
||||
name_space[used] = '\0';
|
||||
save_errno = errno;
|
||||
if (closedir (dirp) != 0)
|
||||
save_errno = errno;
|
||||
if (save_errno != 0)
|
||||
{
|
||||
free (name_space);
|
||||
errno = save_errno;
|
||||
return NULL;
|
||||
}
|
||||
return name_space;
|
||||
}
|
||||
|
||||
/* Return a freshly allocated string containing the file names
|
||||
in directory DIR, separated by '\0' characters;
|
||||
the end is marked by two '\0' characters in a row.
|
||||
Return NULL (setting errno) if DIR cannot be opened, read, or closed. */
|
||||
|
||||
char *
|
||||
savedir (char const *dir)
|
||||
{
|
||||
return savedirstream (opendir (dir));
|
||||
}
|
||||
|
||||
/* Return a freshly allocated string containing the file names
|
||||
in directory FD, separated by '\0' characters;
|
||||
the end is marked by two '\0' characters in a row.
|
||||
Return NULL (setting errno) if FD cannot be read or closed. */
|
||||
|
||||
char *
|
||||
fdsavedir (int fd)
|
||||
{
|
||||
return savedirstream (fdopendir (fd));
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/* Save the list of files in a directory in a string.
|
||||
|
||||
Copyright (C) 1997, 1999, 2001, 2003, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#if !defined SAVEDIR_H_
|
||||
# define SAVEDIR_H_
|
||||
|
||||
char *savedir (char const *dir);
|
||||
char *fdsavedir (int fd);
|
||||
|
||||
#endif
|
@ -1,32 +0,0 @@
|
||||
/* Searching in a string.
|
||||
Copyright (C) 2003, 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <string.h>
|
||||
|
||||
/* Find the first occurrence of C in S or the final NUL byte. */
|
||||
char *
|
||||
strchrnul (const char *s, int c_in)
|
||||
{
|
||||
char c = c_in;
|
||||
while (*s && (*s != c))
|
||||
s++;
|
||||
|
||||
return (char *) s;
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/* stripslash.c -- remove redundant trailing slashes from a file name
|
||||
|
||||
Copyright (C) 1990, 2001, 2003-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "dirname.h"
|
||||
|
||||
/* Remove trailing slashes from FILE. Return true if a trailing slash
|
||||
was removed. This is useful when using file name completion from a
|
||||
shell that adds a "/" after directory names (such as tcsh and
|
||||
bash), because on symlinks to directories, several system calls
|
||||
have different semantics according to whether a trailing slash is
|
||||
present. */
|
||||
|
||||
bool
|
||||
strip_trailing_slashes (char *file)
|
||||
{
|
||||
char *base = last_component (file);
|
||||
char *base_lim;
|
||||
bool had_slash;
|
||||
|
||||
/* last_component returns "" for file system roots, but we need to turn
|
||||
`///' into `/'. */
|
||||
if (! *base)
|
||||
base = file;
|
||||
base_lim = base + base_len (base);
|
||||
had_slash = (*base_lim != '\0');
|
||||
*base_lim = '\0';
|
||||
return had_slash;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/* A replacement function, for systems that lack strndup.
|
||||
|
||||
Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2005, 2006, 2007
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
char *
|
||||
strndup (char const *s, size_t n)
|
||||
{
|
||||
size_t len = strnlen (s, n);
|
||||
char *new = malloc (len + 1);
|
||||
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
|
||||
new[len] = '\0';
|
||||
return memcpy (new, s, len);
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/* Find the length of STRING, but scan at most MAXLEN characters.
|
||||
Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
Written by Simon Josefsson.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Find the length of STRING, but scan at most MAXLEN characters.
|
||||
If no '\0' terminator is found in that many characters, return MAXLEN. */
|
||||
|
||||
size_t
|
||||
strnlen (const char *string, size_t maxlen)
|
||||
{
|
||||
const char *end = memchr (string, '\0', maxlen);
|
||||
return end ? (size_t) (end - string) : maxlen;
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/* System dependent definitions for GNU tar's use of ioctl macros.
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* This is a real challenge to properly get MTIO* symbols :-(. ISC uses
|
||||
<sys/gentape.h>. SCO and BSDi uses <sys/tape.h>; BSDi also requires
|
||||
<sys/tprintf.h> and <sys/device.h> for defining tp_dev and tpr_t. It
|
||||
seems that the rest use <sys/mtio.h>, which itself requires other files,
|
||||
depending on systems. Pyramid defines _IOW in <sgtty.h>, for example. */
|
||||
|
||||
#if HAVE_SYS_GENTAPE_H
|
||||
# include <sys/gentape.h>
|
||||
#else
|
||||
# if HAVE_SYS_TAPE_H
|
||||
# if HAVE_SYS_DEVICE_H
|
||||
# include <sys/device.h>
|
||||
# endif
|
||||
# if HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# if HAVE_SYS_BUF_H
|
||||
# include <sys/buf.h>
|
||||
# endif
|
||||
# if HAVE_SYS_TPRINTF_H
|
||||
# include <sys/tprintf.h>
|
||||
# endif
|
||||
# include <sys/tape.h>
|
||||
# else
|
||||
# if HAVE_SYS_MTIO_H
|
||||
# include <sys/ioctl.h>
|
||||
# if HAVE_SGTTY_H
|
||||
# include <sgtty.h>
|
||||
# endif
|
||||
# if HAVE_SYS_IO_TRIOCTL_H
|
||||
# include <sys/io/trioctl.h>
|
||||
# endif
|
||||
# include <sys/mtio.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
@ -1,475 +0,0 @@
|
||||
/* System dependent definitions for GNU tar.
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
#ifndef __attribute__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
|
||||
# define __attribute__(spec) /* empty */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* IN_CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
|
||||
as an argument to <ctype.h> macros like `isspace'. */
|
||||
#if STDC_HEADERS
|
||||
# define IN_CTYPE_DOMAIN(c) 1
|
||||
#else
|
||||
# define IN_CTYPE_DOMAIN(c) ((unsigned) (c) <= 0177)
|
||||
#endif
|
||||
|
||||
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
|
||||
#define ISODIGIT(c) ((unsigned) (c) - '0' <= 7)
|
||||
#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
|
||||
#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
|
||||
|
||||
/* Declare string and memory handling routines. Take care that an ANSI
|
||||
string.h and pre-ANSI memory.h might conflict, and that memory.h and
|
||||
strings.h conflict on some systems. */
|
||||
|
||||
#if STDC_HEADERS || HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# if !STDC_HEADERS && HAVE_MEMORY_H
|
||||
# include <memory.h>
|
||||
# endif
|
||||
#else
|
||||
# include <strings.h>
|
||||
# ifndef strchr
|
||||
# define strchr index
|
||||
# endif
|
||||
# ifndef strrchr
|
||||
# define strrchr rindex
|
||||
# endif
|
||||
# ifndef memcpy
|
||||
# define memcpy(d, s, n) bcopy ((char const *) (s), (char *) (d), n)
|
||||
# endif
|
||||
# ifndef memcmp
|
||||
# define memcmp(a, b, n) bcmp ((char const *) (a), (char const *) (b), n)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Declare errno. */
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
/* Declare open parameters. */
|
||||
|
||||
#if HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
/* Pick only one of the next three: */
|
||||
#ifndef O_RDONLY
|
||||
# define O_RDONLY 0 /* only allow read */
|
||||
#endif
|
||||
#ifndef O_WRONLY
|
||||
# define O_WRONLY 1 /* only allow write */
|
||||
#endif
|
||||
#ifndef O_RDWR
|
||||
# define O_RDWR 2 /* both are allowed */
|
||||
#endif
|
||||
#ifndef O_ACCMODE
|
||||
# define O_ACCMODE (O_RDONLY | O_RDWR | O_WRONLY)
|
||||
#endif
|
||||
/* The rest can be OR-ed in to the above: */
|
||||
#ifndef O_CREAT
|
||||
# define O_CREAT 8 /* create file if needed */
|
||||
#endif
|
||||
#ifndef O_EXCL
|
||||
# define O_EXCL 16 /* file cannot already exist */
|
||||
#endif
|
||||
#ifndef O_TRUNC
|
||||
# define O_TRUNC 32 /* truncate file on open */
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
#ifndef O_DIRECTORY
|
||||
# define O_DIRECTORY 0
|
||||
#endif
|
||||
#ifndef O_NOATIME
|
||||
# define O_NOATIME 0
|
||||
#endif
|
||||
#ifndef O_NONBLOCK
|
||||
# define O_NONBLOCK 0
|
||||
#endif
|
||||
|
||||
/* Declare file status routines and bits. */
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !HAVE_LSTAT && !defined lstat
|
||||
# define lstat stat
|
||||
#endif
|
||||
|
||||
#if STX_HIDDEN && !_LARGE_FILES /* AIX */
|
||||
# ifdef stat
|
||||
# undef stat
|
||||
# endif
|
||||
# define stat(file_name, buf) statx (file_name, buf, STATSIZE, STX_HIDDEN)
|
||||
# ifdef lstat
|
||||
# undef lstat
|
||||
# endif
|
||||
# define lstat(file_name, buf) statx (file_name, buf, STATSIZE, STX_HIDDEN | STX_LINK)
|
||||
#endif
|
||||
|
||||
#if STAT_MACROS_BROKEN
|
||||
# undef S_ISBLK
|
||||
# undef S_ISCHR
|
||||
# undef S_ISCTG
|
||||
# undef S_ISDIR
|
||||
# undef S_ISFIFO
|
||||
# undef S_ISLNK
|
||||
# undef S_ISREG
|
||||
# undef S_ISSOCK
|
||||
#endif
|
||||
|
||||
/* On MSDOS, there are missing things from <sys/stat.h>. */
|
||||
#if MSDOS
|
||||
# define S_ISUID 0
|
||||
# define S_ISGID 0
|
||||
# define S_ISVTX 0
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#ifndef S_ISREG
|
||||
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISBLK
|
||||
# ifdef S_IFBLK
|
||||
# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
|
||||
# else
|
||||
# define S_ISBLK(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISCHR
|
||||
# ifdef S_IFCHR
|
||||
# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
||||
# else
|
||||
# define S_ISCHR(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISCTG
|
||||
# ifdef S_IFCTG
|
||||
# define S_ISCTG(mode) (((mode) & S_IFMT) == S_IFCTG)
|
||||
# else
|
||||
# define S_ISCTG(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISDOOR
|
||||
# define S_ISDOOR(mode) 0
|
||||
#endif
|
||||
#ifndef S_ISFIFO
|
||||
# ifdef S_IFIFO
|
||||
# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
|
||||
# else
|
||||
# define S_ISFIFO(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISLNK
|
||||
# ifdef S_IFLNK
|
||||
# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
|
||||
# else
|
||||
# define S_ISLNK(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISSOCK
|
||||
# ifdef S_IFSOCK
|
||||
# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
|
||||
# else
|
||||
# define S_ISSOCK(mode) 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !HAVE_MKFIFO && !defined mkfifo && defined S_IFIFO
|
||||
# define mkfifo(file_name, mode) (mknod (file_name, (mode) | S_IFIFO, 0))
|
||||
#endif
|
||||
|
||||
#ifndef S_ISUID
|
||||
# define S_ISUID 0004000
|
||||
#endif
|
||||
#ifndef S_ISGID
|
||||
# define S_ISGID 0002000
|
||||
#endif
|
||||
#ifndef S_ISVTX
|
||||
# define S_ISVTX 0001000
|
||||
#endif
|
||||
#ifndef S_IRUSR
|
||||
# define S_IRUSR 0000400
|
||||
#endif
|
||||
#ifndef S_IWUSR
|
||||
# define S_IWUSR 0000200
|
||||
#endif
|
||||
#ifndef S_IXUSR
|
||||
# define S_IXUSR 0000100
|
||||
#endif
|
||||
#ifndef S_IRGRP
|
||||
# define S_IRGRP 0000040
|
||||
#endif
|
||||
#ifndef S_IWGRP
|
||||
# define S_IWGRP 0000020
|
||||
#endif
|
||||
#ifndef S_IXGRP
|
||||
# define S_IXGRP 0000010
|
||||
#endif
|
||||
#ifndef S_IROTH
|
||||
# define S_IROTH 0000004
|
||||
#endif
|
||||
#ifndef S_IWOTH
|
||||
# define S_IWOTH 0000002
|
||||
#endif
|
||||
#ifndef S_IXOTH
|
||||
# define S_IXOTH 0000001
|
||||
#endif
|
||||
|
||||
#define MODE_WXUSR (S_IWUSR | S_IXUSR)
|
||||
#define MODE_R (S_IRUSR | S_IRGRP | S_IROTH)
|
||||
#define MODE_RW (S_IWUSR | S_IWGRP | S_IWOTH | MODE_R)
|
||||
#define MODE_RWX (S_IXUSR | S_IXGRP | S_IXOTH | MODE_RW)
|
||||
#define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
|
||||
|
||||
/* Include <unistd.h> before any preprocessor test of _POSIX_VERSION. */
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0
|
||||
#endif
|
||||
#ifndef SEEK_CUR
|
||||
# define SEEK_CUR 1
|
||||
#endif
|
||||
#ifndef SEEK_END
|
||||
# define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
# define STDIN_FILENO 0
|
||||
#endif
|
||||
#ifndef STDOUT_FILENO
|
||||
# define STDOUT_FILENO 1
|
||||
#endif
|
||||
#ifndef STDERR_FILENO
|
||||
# define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
/* Declare make device, major and minor. Since major is a function on
|
||||
SVR4, we have to resort to GOT_MAJOR instead of just testing if
|
||||
major is #define'd. */
|
||||
|
||||
#if MAJOR_IN_MKDEV
|
||||
# include <sys/mkdev.h>
|
||||
# if !defined(makedev) && defined(mkdev)
|
||||
# define makedev(a,b) mkdev((a),(b))
|
||||
# endif
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
#if MAJOR_IN_SYSMACROS
|
||||
# include <sys/sysmacros.h>
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
/* Some <sys/types.h> defines the macros. */
|
||||
#ifdef major
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
#ifndef GOT_MAJOR
|
||||
# if MSDOS
|
||||
# define major(device) (device)
|
||||
# define minor(device) (device)
|
||||
# define makedev(major, minor) (((major) << 8) | (minor))
|
||||
# define GOT_MAJOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* For HP-UX before HP-UX 8, major/minor are not in <sys/sysmacros.h>. */
|
||||
#ifndef GOT_MAJOR
|
||||
# if defined(hpux) || defined(__hpux__) || defined(__hpux)
|
||||
# include <sys/mknod.h>
|
||||
# define GOT_MAJOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef GOT_MAJOR
|
||||
# define major(device) (((device) >> 8) & 0xff)
|
||||
# define minor(device) ((device) & 0xff)
|
||||
# define makedev(major, minor) (((major) << 8) | (minor))
|
||||
#endif
|
||||
|
||||
#undef GOT_MAJOR
|
||||
|
||||
/* Declare wait status. */
|
||||
|
||||
#if HAVE_SYS_WAIT_H
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
#ifndef WEXITSTATUS
|
||||
# define WEXITSTATUS(s) (((s) >> 8) & 0xff)
|
||||
#endif
|
||||
#ifndef WIFSIGNALED
|
||||
# define WIFSIGNALED(s) (((s) & 0xffff) - 1 < (unsigned) 0xff)
|
||||
#endif
|
||||
#ifndef WTERMSIG
|
||||
# define WTERMSIG(s) ((s) & 0x7f)
|
||||
#endif
|
||||
|
||||
/* FIXME: It is wrong to use BLOCKSIZE for buffers when the logical block
|
||||
size is greater than 512 bytes; so ST_BLKSIZE code below, in preparation
|
||||
for some cleanup in this area, later. */
|
||||
|
||||
/* Extract or fake data from a `struct stat'. ST_BLKSIZE gives the
|
||||
optimal I/O blocksize for the file, in bytes. Some systems, like
|
||||
Sequents, return st_blksize of 0 on pipes. */
|
||||
|
||||
#define DEFAULT_ST_BLKSIZE 512
|
||||
|
||||
#if !HAVE_ST_BLKSIZE
|
||||
# define ST_BLKSIZE(statbuf) DEFAULT_ST_BLKSIZE
|
||||
#else
|
||||
# define ST_BLKSIZE(statbuf) \
|
||||
((statbuf).st_blksize > 0 ? (statbuf).st_blksize : DEFAULT_ST_BLKSIZE)
|
||||
#endif
|
||||
|
||||
/* Extract or fake data from a `struct stat'. ST_NBLOCKS gives the
|
||||
number of ST_NBLOCKSIZE-byte blocks in the file (including indirect blocks).
|
||||
HP-UX counts st_blocks in 1024-byte units,
|
||||
this loses when mixing HP-UX and BSD filesystems with NFS. AIX PS/2
|
||||
counts st_blocks in 4K units. */
|
||||
|
||||
#if !HAVE_ST_BLOCKS
|
||||
# if defined(_POSIX_SOURCE) || !defined(BSIZE)
|
||||
# define ST_NBLOCKS(statbuf) ((statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0))
|
||||
# else
|
||||
off_t st_blocks ();
|
||||
# define ST_NBLOCKS(statbuf) (st_blocks ((statbuf).st_size))
|
||||
# endif
|
||||
#else
|
||||
# define ST_NBLOCKS(statbuf) ((statbuf).st_blocks)
|
||||
# if defined(hpux) || defined(__hpux__) || defined(__hpux)
|
||||
# define ST_NBLOCKSIZE 1024
|
||||
# else
|
||||
# if defined(_AIX) && defined(_I386)
|
||||
# define ST_NBLOCKSIZE (4 * 1024)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ST_NBLOCKSIZE
|
||||
# define ST_NBLOCKSIZE 512
|
||||
#endif
|
||||
|
||||
#define ST_IS_SPARSE(st) \
|
||||
(ST_NBLOCKS (st) \
|
||||
< ((st).st_size / ST_NBLOCKSIZE + ((st).st_size % ST_NBLOCKSIZE != 0)))
|
||||
|
||||
/* Declare standard functions. */
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
void *malloc ();
|
||||
char *getenv ();
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#if !defined _POSIX_VERSION && MSDOS
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#if WITH_DMALLOC
|
||||
# define DMALLOC_FUNC_CHECK
|
||||
# include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef MB_LEN_MAX
|
||||
# define MB_LEN_MAX 1
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <intprops.h>
|
||||
|
||||
#define UINTMAX_STRSIZE_BOUND INT_BUFSIZE_BOUND (uintmax_t)
|
||||
|
||||
/* Prototypes for external functions. */
|
||||
|
||||
#if HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
#endif
|
||||
#if !HAVE_SETLOCALE
|
||||
# define setlocale(category, locale) /* empty */
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* Library modules. */
|
||||
|
||||
#include <dirname.h>
|
||||
#include <error.h>
|
||||
#include <savedir.h>
|
||||
#include <unlocked-io.h>
|
||||
#include <xalloc.h>
|
||||
|
||||
#include <gettext.h>
|
||||
#define _(msgid) gettext (msgid)
|
||||
#define N_(msgid) msgid
|
||||
|
||||
#if MSDOS
|
||||
# include <process.h>
|
||||
# define SET_BINARY_MODE(arc) setmode(arc, O_BINARY)
|
||||
# define ERRNO_IS_EACCES errno == EACCES
|
||||
# define mkdir(file, mode) (mkdir) (file)
|
||||
# define TTY_NAME "con"
|
||||
# define sys_reset_uid_gid()
|
||||
#else
|
||||
# include <pwd.h>
|
||||
# include <grp.h>
|
||||
# define SET_BINARY_MODE(arc)
|
||||
# define ERRNO_IS_EACCES 0
|
||||
# define TTY_NAME "/dev/tty"
|
||||
# define sys_reset_uid_gid() \
|
||||
do { setuid (getuid ()); setgid (getgid ()); } while (0)
|
||||
#endif
|
||||
|
||||
#if XENIX
|
||||
# include <sys/inode.h>
|
||||
#endif
|
@ -1,3 +0,0 @@
|
||||
#define inttostr umaxtostr
|
||||
#define inttype uintmax_t
|
||||
#include "inttostr.c"
|
@ -1,137 +0,0 @@
|
||||
/* Prefer faster, non-thread-safe stdio functions if available.
|
||||
|
||||
Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Jim Meyering. */
|
||||
|
||||
#ifndef UNLOCKED_IO_H
|
||||
# define UNLOCKED_IO_H 1
|
||||
|
||||
/* These are wrappers for functions/macros from the GNU C library, and
|
||||
from other C libraries supporting POSIX's optional thread-safe functions.
|
||||
|
||||
The standard I/O functions are thread-safe. These *_unlocked ones are
|
||||
more efficient but not thread-safe. That they're not thread-safe is
|
||||
fine since all of the applications in this package are single threaded.
|
||||
|
||||
Also, some code that is shared with the GNU C library may invoke
|
||||
the *_unlocked functions directly. On hosts that lack those
|
||||
functions, invoke the non-thread-safe versions instead. */
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
# if HAVE_DECL_CLEARERR_UNLOCKED
|
||||
# undef clearerr
|
||||
# define clearerr(x) clearerr_unlocked (x)
|
||||
# else
|
||||
# define clearerr_unlocked(x) clearerr (x)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_FEOF_UNLOCKED
|
||||
# undef feof
|
||||
# define feof(x) feof_unlocked (x)
|
||||
# else
|
||||
# define feof_unlocked(x) feof (x)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_FERROR_UNLOCKED
|
||||
# undef ferror
|
||||
# define ferror(x) ferror_unlocked (x)
|
||||
# else
|
||||
# define ferror_unlocked(x) ferror (x)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_FFLUSH_UNLOCKED
|
||||
# undef fflush
|
||||
# define fflush(x) fflush_unlocked (x)
|
||||
# else
|
||||
# define fflush_unlocked(x) fflush (x)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_FGETS_UNLOCKED
|
||||
# undef fgets
|
||||
# define fgets(x,y,z) fgets_unlocked (x,y,z)
|
||||
# else
|
||||
# define fgets_unlocked(x,y,z) fgets (x,y,z)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_FPUTC_UNLOCKED
|
||||
# undef fputc
|
||||
# define fputc(x,y) fputc_unlocked (x,y)
|
||||
# else
|
||||
# define fputc_unlocked(x,y) fputc (x,y)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_FPUTS_UNLOCKED
|
||||
# undef fputs
|
||||
# define fputs(x,y) fputs_unlocked (x,y)
|
||||
# else
|
||||
# define fputs_unlocked(x,y) fputs (x,y)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_FREAD_UNLOCKED
|
||||
# undef fread
|
||||
# define fread(w,x,y,z) fread_unlocked (w,x,y,z)
|
||||
# else
|
||||
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_FWRITE_UNLOCKED
|
||||
# undef fwrite
|
||||
# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
|
||||
# else
|
||||
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_GETC_UNLOCKED
|
||||
# undef getc
|
||||
# define getc(x) getc_unlocked (x)
|
||||
# else
|
||||
# define getc_unlocked(x) getc (x)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_GETCHAR_UNLOCKED
|
||||
# undef getchar
|
||||
# define getchar() getchar_unlocked ()
|
||||
# else
|
||||
# define getchar_unlocked() getchar ()
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_PUTC_UNLOCKED
|
||||
# undef putc
|
||||
# define putc(x,y) putc_unlocked (x,y)
|
||||
# else
|
||||
# define putc_unlocked(x,y) putc (x,y)
|
||||
# endif
|
||||
|
||||
# if HAVE_DECL_PUTCHAR_UNLOCKED
|
||||
# undef putchar
|
||||
# define putchar(x) putchar_unlocked (x)
|
||||
# else
|
||||
# define putchar_unlocked(x) putchar (x)
|
||||
# endif
|
||||
|
||||
# undef flockfile
|
||||
# define flockfile(x) ((void) 0)
|
||||
|
||||
# undef ftrylockfile
|
||||
# define ftrylockfile(x) 0
|
||||
|
||||
# undef funlockfile
|
||||
# define funlockfile(x) ((void) 0)
|
||||
|
||||
#endif /* UNLOCKED_IO_H */
|
@ -1,189 +0,0 @@
|
||||
/* Set file access and modification times.
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
/* derived from a function in touch.c */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "utimens.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#endif
|
||||
|
||||
/* Some systems (even some that do have <utime.h>) don't declare this
|
||||
structure anywhere. */
|
||||
#ifndef HAVE_STRUCT_UTIMBUF
|
||||
struct utimbuf
|
||||
{
|
||||
long actime;
|
||||
long modtime;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Some systems don't have ENOSYS. */
|
||||
#ifndef ENOSYS
|
||||
# ifdef ENOTSUP
|
||||
# define ENOSYS ENOTSUP
|
||||
# else
|
||||
/* Some systems don't have ENOTSUP either. */
|
||||
# define ENOSYS EINVAL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __attribute__
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
|
||||
# define __attribute__(x)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ATTRIBUTE_UNUSED
|
||||
# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
|
||||
#endif
|
||||
|
||||
/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
|
||||
TIMESPEC[0] and TIMESPEC[1], respectively.
|
||||
FD must be either negative -- in which case it is ignored --
|
||||
or a file descriptor that is open on FILE.
|
||||
If FD is nonnegative, then FILE can be NULL, which means
|
||||
use just futimes (or equivalent) instead of utimes (or equivalent),
|
||||
and fail if on an old system without futimes (or equivalent).
|
||||
If TIMESPEC is null, set the time stamps to the current time.
|
||||
Return 0 on success, -1 (setting errno) on failure. */
|
||||
|
||||
int
|
||||
gl_futimens (int fd ATTRIBUTE_UNUSED,
|
||||
char const *file, struct timespec const timespec[2])
|
||||
{
|
||||
/* Some Linux-based NFS clients are buggy, and mishandle time stamps
|
||||
of files in NFS file systems in some cases. We have no
|
||||
configure-time test for this, but please see
|
||||
<http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
|
||||
some of the problems with Linux 2.6.16. If this affects you,
|
||||
compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
|
||||
help in some cases, albeit at a cost in performance. But you
|
||||
really should upgrade your kernel to a fixed version, since the
|
||||
problem affects many applications. */
|
||||
|
||||
#if HAVE_BUGGY_NFS_TIME_STAMPS
|
||||
if (fd < 0)
|
||||
sync ();
|
||||
else
|
||||
fsync (fd);
|
||||
#endif
|
||||
|
||||
/* There's currently no interface to set file timestamps with
|
||||
nanosecond resolution, so do the best we can, discarding any
|
||||
fractional part of the timestamp. */
|
||||
#if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
|
||||
struct timeval timeval[2];
|
||||
struct timeval const *t;
|
||||
if (timespec)
|
||||
{
|
||||
timeval[0].tv_sec = timespec[0].tv_sec;
|
||||
timeval[0].tv_usec = timespec[0].tv_nsec / 1000;
|
||||
timeval[1].tv_sec = timespec[1].tv_sec;
|
||||
timeval[1].tv_usec = timespec[1].tv_nsec / 1000;
|
||||
t = timeval;
|
||||
}
|
||||
else
|
||||
t = NULL;
|
||||
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
# if HAVE_FUTIMESAT
|
||||
return futimesat (AT_FDCWD, file, t);
|
||||
# endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If futimesat or futimes fails here, don't try to speed things
|
||||
up by returning right away. glibc can incorrectly fail with
|
||||
errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
|
||||
in high security mode doesn't allow ordinary users to read
|
||||
/proc/self, so glibc incorrectly fails with errno == EACCES.
|
||||
If errno == EIO, EPERM, or EROFS, it's probably safe to fail
|
||||
right away, but these cases are rare enough that they're not
|
||||
worth optimizing, and who knows what other messed-up systems
|
||||
are out there? So play it safe and fall back on the code
|
||||
below. */
|
||||
# if HAVE_FUTIMESAT
|
||||
if (futimesat (fd, NULL, t) == 0)
|
||||
return 0;
|
||||
# elif HAVE_FUTIMES
|
||||
if (futimes (fd, t) == 0)
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!file)
|
||||
{
|
||||
#if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
|
||||
errno = ENOSYS;
|
||||
#endif
|
||||
|
||||
/* Prefer EBADF to ENOSYS if both error numbers apply. */
|
||||
if (errno == ENOSYS)
|
||||
{
|
||||
int fd2 = dup (fd);
|
||||
int dup_errno = errno;
|
||||
if (0 <= fd2)
|
||||
close (fd2);
|
||||
errno = (fd2 < 0 && dup_errno == EBADF ? EBADF : ENOSYS);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if HAVE_WORKING_UTIMES
|
||||
return utimes (file, t);
|
||||
#else
|
||||
{
|
||||
struct utimbuf utimbuf;
|
||||
struct utimbuf const *ut;
|
||||
if (timespec)
|
||||
{
|
||||
utimbuf.actime = timespec[0].tv_sec;
|
||||
utimbuf.modtime = timespec[1].tv_sec;
|
||||
ut = &utimbuf;
|
||||
}
|
||||
else
|
||||
ut = NULL;
|
||||
|
||||
return utime (file, ut);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set the access and modification time stamps of FILE to be
|
||||
TIMESPEC[0] and TIMESPEC[1], respectively. */
|
||||
int
|
||||
utimens (char const *file, struct timespec const timespec[2])
|
||||
{
|
||||
return gl_futimens (-1, file, timespec);
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
#include <time.h>
|
||||
int gl_futimens (int, char const *, struct timespec const [2]);
|
||||
int utimens (char const *, struct timespec const [2]);
|
@ -1,42 +0,0 @@
|
||||
/* Report a memory allocation failure and exit.
|
||||
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "xalloc.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "error.h"
|
||||
#include "exitfail.h"
|
||||
|
||||
#include "gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
|
||||
void
|
||||
xalloc_die (void)
|
||||
{
|
||||
error (exit_failure, 0, "%s", _("memory exhausted"));
|
||||
|
||||
/* The `noreturn' cannot be given to error, since it may return if
|
||||
its first argument is 0. To help compilers understand the
|
||||
xalloc_die does not return, call abort. Also, the abort is a
|
||||
safety feature if exit_failure is 0 (which shouldn't happen). */
|
||||
abort ();
|
||||
}
|
@ -1,271 +0,0 @@
|
||||
/* xalloc.h -- malloc with out-of-memory checking
|
||||
|
||||
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2003, 2004, 2006, 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef XALLOC_H_
|
||||
# define XALLOC_H_
|
||||
|
||||
# include <stddef.h>
|
||||
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
|
||||
# ifndef __attribute__
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
|
||||
# define __attribute__(x)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef ATTRIBUTE_NORETURN
|
||||
# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
|
||||
# endif
|
||||
|
||||
/* This function is always triggered when memory is exhausted.
|
||||
It must be defined by the application, either explicitly
|
||||
or by using gnulib's xalloc-die module. This is the
|
||||
function to call when one wants the program to die because of a
|
||||
memory allocation failure. */
|
||||
extern void xalloc_die (void) ATTRIBUTE_NORETURN;
|
||||
|
||||
void *xmalloc (size_t s);
|
||||
void *xzalloc (size_t s);
|
||||
void *xcalloc (size_t n, size_t s);
|
||||
void *xrealloc (void *p, size_t s);
|
||||
void *x2realloc (void *p, size_t *pn);
|
||||
void *xmemdup (void const *p, size_t s);
|
||||
char *xstrdup (char const *str);
|
||||
|
||||
/* Return 1 if an array of N objects, each of size S, cannot exist due
|
||||
to size arithmetic overflow. S must be positive and N must be
|
||||
nonnegative. This is a macro, not an inline function, so that it
|
||||
works correctly even when SIZE_MAX < N.
|
||||
|
||||
By gnulib convention, SIZE_MAX represents overflow in size
|
||||
calculations, so the conservative dividend to use here is
|
||||
SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
|
||||
However, malloc (SIZE_MAX) fails on all known hosts where
|
||||
sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
|
||||
exactly-SIZE_MAX allocations on such hosts; this avoids a test and
|
||||
branch when S is known to be 1. */
|
||||
# define xalloc_oversized(n, s) \
|
||||
((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
|
||||
|
||||
|
||||
/* In the following macros, T must be an elementary or structure/union or
|
||||
typedef'ed type, or a pointer to such a type. To apply one of the
|
||||
following macros to a function pointer or array type, you need to typedef
|
||||
it first and use the typedef name. */
|
||||
|
||||
/* Allocate an object of type T dynamically, with error checking. */
|
||||
/* extern t *XMALLOC (typename t); */
|
||||
# define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
|
||||
|
||||
/* Allocate memory for N elements of type T, with error checking. */
|
||||
/* extern t *XNMALLOC (size_t n, typename t); */
|
||||
# define XNMALLOC(n, t) \
|
||||
((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
|
||||
|
||||
/* Allocate an object of type T dynamically, with error checking,
|
||||
and zero it. */
|
||||
/* extern t *XZALLOC (typename t); */
|
||||
# define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
|
||||
|
||||
/* Allocate memory for N elements of type T, with error checking,
|
||||
and zero it. */
|
||||
/* extern t *XCALLOC (size_t n, typename t); */
|
||||
# define XCALLOC(n, t) \
|
||||
((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
|
||||
|
||||
|
||||
# if HAVE_INLINE
|
||||
# define static_inline static inline
|
||||
# else
|
||||
void *xnmalloc (size_t n, size_t s);
|
||||
void *xnrealloc (void *p, size_t n, size_t s);
|
||||
void *x2nrealloc (void *p, size_t *pn, size_t s);
|
||||
char *xcharalloc (size_t n);
|
||||
# endif
|
||||
|
||||
# ifdef static_inline
|
||||
|
||||
/* Allocate an array of N objects, each with S bytes of memory,
|
||||
dynamically, with error checking. S must be nonzero. */
|
||||
|
||||
static_inline void *
|
||||
xnmalloc (size_t n, size_t s)
|
||||
{
|
||||
if (xalloc_oversized (n, s))
|
||||
xalloc_die ();
|
||||
return xmalloc (n * s);
|
||||
}
|
||||
|
||||
/* Change the size of an allocated block of memory P to an array of N
|
||||
objects each of S bytes, with error checking. S must be nonzero. */
|
||||
|
||||
static_inline void *
|
||||
xnrealloc (void *p, size_t n, size_t s)
|
||||
{
|
||||
if (xalloc_oversized (n, s))
|
||||
xalloc_die ();
|
||||
return xrealloc (p, n * s);
|
||||
}
|
||||
|
||||
/* If P is null, allocate a block of at least *PN such objects;
|
||||
otherwise, reallocate P so that it contains more than *PN objects
|
||||
each of S bytes. *PN must be nonzero unless P is null, and S must
|
||||
be nonzero. Set *PN to the new number of objects, and return the
|
||||
pointer to the new block. *PN is never set to zero, and the
|
||||
returned pointer is never null.
|
||||
|
||||
Repeated reallocations are guaranteed to make progress, either by
|
||||
allocating an initial block with a nonzero size, or by allocating a
|
||||
larger block.
|
||||
|
||||
In the following implementation, nonzero sizes are increased by a
|
||||
factor of approximately 1.5 so that repeated reallocations have
|
||||
O(N) overall cost rather than O(N**2) cost, but the
|
||||
specification for this function does not guarantee that rate.
|
||||
|
||||
Here is an example of use:
|
||||
|
||||
int *p = NULL;
|
||||
size_t used = 0;
|
||||
size_t allocated = 0;
|
||||
|
||||
void
|
||||
append_int (int value)
|
||||
{
|
||||
if (used == allocated)
|
||||
p = x2nrealloc (p, &allocated, sizeof *p);
|
||||
p[used++] = value;
|
||||
}
|
||||
|
||||
This causes x2nrealloc to allocate a block of some nonzero size the
|
||||
first time it is called.
|
||||
|
||||
To have finer-grained control over the initial size, set *PN to a
|
||||
nonzero value before calling this function with P == NULL. For
|
||||
example:
|
||||
|
||||
int *p = NULL;
|
||||
size_t used = 0;
|
||||
size_t allocated = 0;
|
||||
size_t allocated1 = 1000;
|
||||
|
||||
void
|
||||
append_int (int value)
|
||||
{
|
||||
if (used == allocated)
|
||||
{
|
||||
p = x2nrealloc (p, &allocated1, sizeof *p);
|
||||
allocated = allocated1;
|
||||
}
|
||||
p[used++] = value;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
static_inline void *
|
||||
x2nrealloc (void *p, size_t *pn, size_t s)
|
||||
{
|
||||
size_t n = *pn;
|
||||
|
||||
if (! p)
|
||||
{
|
||||
if (! n)
|
||||
{
|
||||
/* The approximate size to use for initial small allocation
|
||||
requests, when the invoking code specifies an old size of
|
||||
zero. 64 bytes is the largest "small" request for the
|
||||
GNU C library malloc. */
|
||||
enum { DEFAULT_MXFAST = 64 };
|
||||
|
||||
n = DEFAULT_MXFAST / s;
|
||||
n += !n;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set N = ceil (1.5 * N) so that progress is made if N == 1.
|
||||
Check for overflow, so that N * S stays in size_t range.
|
||||
The check is slightly conservative, but an exact check isn't
|
||||
worth the trouble. */
|
||||
if ((size_t) -1 / 3 * 2 / s <= n)
|
||||
xalloc_die ();
|
||||
n += (n + 1) / 2;
|
||||
}
|
||||
|
||||
*pn = n;
|
||||
return xrealloc (p, n * s);
|
||||
}
|
||||
|
||||
/* Return a pointer to a new buffer of N bytes. This is like xmalloc,
|
||||
except it returns char *. */
|
||||
|
||||
static_inline char *
|
||||
xcharalloc (size_t n)
|
||||
{
|
||||
return XNMALLOC (n, char);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
|
||||
/* C++ does not allow conversions from void * to other pointer types
|
||||
without a cast. Use templates to work around the problem when
|
||||
possible. */
|
||||
|
||||
template <typename T> inline T *
|
||||
xrealloc (T *p, size_t s)
|
||||
{
|
||||
return (T *) xrealloc ((void *) p, s);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
xnrealloc (T *p, size_t n, size_t s)
|
||||
{
|
||||
return (T *) xnrealloc ((void *) p, n, s);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
x2realloc (T *p, size_t *pn)
|
||||
{
|
||||
return (T *) x2realloc ((void *) p, pn);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
x2nrealloc (T *p, size_t *pn, size_t s)
|
||||
{
|
||||
return (T *) x2nrealloc ((void *) p, pn, s);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
xmemdup (T const *p, size_t s)
|
||||
{
|
||||
return (T *) xmemdup ((void const *) p, s);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
|
||||
#endif /* !XALLOC_H_ */
|
@ -1,123 +0,0 @@
|
||||
/* xmalloc.c -- malloc with out of memory checking
|
||||
|
||||
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if ! HAVE_INLINE
|
||||
# define static_inline
|
||||
#endif
|
||||
#include "xalloc.h"
|
||||
#undef static_inline
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
|
||||
/* 1 if calloc is known to be compatible with GNU calloc. This
|
||||
matters if we are not also using the calloc module, which defines
|
||||
HAVE_CALLOC and supports the GNU API even on non-GNU platforms. */
|
||||
#if defined HAVE_CALLOC || defined __GLIBC__
|
||||
enum { HAVE_GNU_CALLOC = 1 };
|
||||
#else
|
||||
enum { HAVE_GNU_CALLOC = 0 };
|
||||
#endif
|
||||
|
||||
/* Allocate N bytes of memory dynamically, with error checking. */
|
||||
|
||||
void *
|
||||
xmalloc (size_t n)
|
||||
{
|
||||
void *p = malloc (n);
|
||||
if (!p && n != 0)
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Change the size of an allocated block of memory P to N bytes,
|
||||
with error checking. */
|
||||
|
||||
void *
|
||||
xrealloc (void *p, size_t n)
|
||||
{
|
||||
p = realloc (p, n);
|
||||
if (!p && n != 0)
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* If P is null, allocate a block of at least *PN bytes; otherwise,
|
||||
reallocate P so that it contains more than *PN bytes. *PN must be
|
||||
nonzero unless P is null. Set *PN to the new block's size, and
|
||||
return the pointer to the new block. *PN is never set to zero, and
|
||||
the returned pointer is never null. */
|
||||
|
||||
void *
|
||||
x2realloc (void *p, size_t *pn)
|
||||
{
|
||||
return x2nrealloc (p, pn, 1);
|
||||
}
|
||||
|
||||
/* Allocate S bytes of zeroed memory dynamically, with error checking.
|
||||
There's no need for xnzalloc (N, S), since it would be equivalent
|
||||
to xcalloc (N, S). */
|
||||
|
||||
void *
|
||||
xzalloc (size_t s)
|
||||
{
|
||||
return memset (xmalloc (s), 0, s);
|
||||
}
|
||||
|
||||
/* Allocate zeroed memory for N elements of S bytes, with error
|
||||
checking. S must be nonzero. */
|
||||
|
||||
void *
|
||||
xcalloc (size_t n, size_t s)
|
||||
{
|
||||
void *p;
|
||||
/* Test for overflow, since some calloc implementations don't have
|
||||
proper overflow checks. But omit overflow and size-zero tests if
|
||||
HAVE_GNU_CALLOC, since GNU calloc catches overflow and never
|
||||
returns NULL if successful. */
|
||||
if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s))
|
||||
|| (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Clone an object P of size S, with error checking. There's no need
|
||||
for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
|
||||
need for an arithmetic overflow check. */
|
||||
|
||||
void *
|
||||
xmemdup (void const *p, size_t s)
|
||||
{
|
||||
return memcpy (xmalloc (s), p, s);
|
||||
}
|
||||
|
||||
/* Clone STRING. */
|
||||
|
||||
char *
|
||||
xstrdup (char const *string)
|
||||
{
|
||||
return xmemdup (string, strlen (string) + 1);
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/* Duplicate a bounded initial segment of a string, with out-of-memory
|
||||
checking.
|
||||
Copyright (C) 2003, 2006, 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include "xstrndup.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Return a newly allocated copy of at most N bytes of STRING.
|
||||
In other words, return a copy of the initial segment of length N of
|
||||
STRING. */
|
||||
char *
|
||||
xstrndup (const char *string, size_t n)
|
||||
{
|
||||
char *s = strndup (string, n);
|
||||
if (! s)
|
||||
xalloc_die ();
|
||||
return s;
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/* Duplicate a bounded initial segment of a string, with out-of-memory
|
||||
checking.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Return a newly allocated copy of at most N bytes of STRING.
|
||||
In other words, return a copy of the initial segment of length N of
|
||||
STRING. */
|
||||
extern char *xstrndup (const char *string, size_t n);
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,443 +0,0 @@
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/* copypass.c - cpio copy pass sub-function.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004,
|
||||
2006 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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "filetypes.h"
|
||||
#include "cpiohdr.h"
|
||||
#include "dstring.h"
|
||||
#include "extern.h"
|
||||
#include "paxlib.h"
|
||||
|
||||
#ifndef HAVE_LCHOWN
|
||||
# define lchown chown
|
||||
#endif
|
||||
|
||||
|
||||
/* A wrapper around set_perms using another set of arguments */
|
||||
static void
|
||||
set_copypass_perms (int fd, const char *name, struct stat *st)
|
||||
{
|
||||
struct cpio_file_stat header;
|
||||
header.c_name = name;
|
||||
stat_to_cpio (&header, st);
|
||||
set_perms (fd, &header);
|
||||
}
|
||||
|
||||
/* 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 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
|
||||
|
||||
umask (0); /* Reset umask to preserve modes of
|
||||
created files */
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
stat_error (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))
|
||||
{
|
||||
/* 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);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
open_error (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)
|
||||
{
|
||||
open_error (output_name.ds_string);
|
||||
close (in_file_des);
|
||||
continue;
|
||||
}
|
||||
|
||||
copy_files_disk_to_disk (in_file_des, out_file_des, in_file_stat.st_size, input_name.ds_string);
|
||||
disk_empty_output_buffer (out_file_des);
|
||||
/* Debian hack to fix a bug in the --sparse option.
|
||||
This bug has been reported to
|
||||
"bug-gnu-utils@prep.ai.mit.edu". (96/7/10) -BEM */
|
||||
if (delayed_seek_count > 0)
|
||||
{
|
||||
lseek (out_file_des, delayed_seek_count-1, SEEK_CUR);
|
||||
write (out_file_des, "", 1);
|
||||
delayed_seek_count = 0;
|
||||
}
|
||||
|
||||
set_copypass_perms (out_file_des,
|
||||
output_name.ds_string, &in_file_stat);
|
||||
|
||||
if (reset_time_flag)
|
||||
{
|
||||
set_file_times (in_file_des,
|
||||
input_name.ds_string,
|
||||
in_file_stat.st_atime,
|
||||
in_file_stat.st_mtime);
|
||||
set_file_times (out_file_des,
|
||||
output_name.ds_string,
|
||||
in_file_stat.st_atime,
|
||||
in_file_stat.st_mtime);
|
||||
}
|
||||
|
||||
if (close (in_file_des) < 0)
|
||||
close_error (input_name.ds_string);
|
||||
|
||||
if (close (out_file_des) < 0)
|
||||
close_error (output_name.ds_string);
|
||||
|
||||
warn_if_file_changed(input_name.ds_string, in_file_stat.st_size,
|
||||
in_file_stat.st_mtime);
|
||||
}
|
||||
}
|
||||
else if (S_ISDIR (in_file_stat.st_mode))
|
||||
{
|
||||
#ifdef HPUX_CDF
|
||||
cdf_flag = 0;
|
||||
#endif
|
||||
if (!existing_dir)
|
||||
{
|
||||
#ifdef HPUX_CDF
|
||||
/* If the directory name ends in a + and is SUID,
|
||||
then it is a CDF. Strip the trailing + from the name
|
||||
before creating it. */
|
||||
cdf_char = strlen (output_name.ds_string) - 1;
|
||||
if ( (cdf_char > 0) &&
|
||||
(in_file_stat.st_mode & 04000) &&
|
||||
(output_name.ds_string [cdf_char] == '+') )
|
||||
{
|
||||
output_name.ds_string [cdf_char] = '\0';
|
||||
cdf_flag = 1;
|
||||
}
|
||||
#endif
|
||||
res = mkdir (output_name.ds_string, in_file_stat.st_mode);
|
||||
|
||||
}
|
||||
else
|
||||
res = 0;
|
||||
if (res < 0 && create_dir_flag)
|
||||
{
|
||||
create_all_directories (output_name.ds_string);
|
||||
res = mkdir (output_name.ds_string, in_file_stat.st_mode);
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
/* In some odd cases where the output_name includes `.',
|
||||
the directory may have actually been created by
|
||||
create_all_directories(), so the mkdir will fail
|
||||
because the directory exists. If that's the case,
|
||||
don't complain about it. */
|
||||
if ( (errno != EEXIST) ||
|
||||
(lstat (output_name.ds_string, &out_file_stat) != 0) ||
|
||||
!(S_ISDIR (out_file_stat.st_mode) ) )
|
||||
{
|
||||
stat_error (output_name.ds_string);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
|
||||
}
|
||||
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)
|
||||
{
|
||||
#ifdef S_ISFIFO
|
||||
if (S_ISFIFO (in_file_stat.st_mode))
|
||||
res = mkfifo (output_name.ds_string, in_file_stat.st_mode);
|
||||
else
|
||||
#endif
|
||||
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);
|
||||
#ifdef S_ISFIFO
|
||||
if (S_ISFIFO (in_file_stat.st_mode))
|
||||
res = mkfifo (output_name.ds_string, in_file_stat.st_mode);
|
||||
else
|
||||
#endif
|
||||
res = mknod (output_name.ds_string, in_file_stat.st_mode,
|
||||
in_file_stat.st_rdev);
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
mknod_error (output_name.ds_string);
|
||||
continue;
|
||||
}
|
||||
set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef S_ISLNK
|
||||
else if (S_ISLNK (in_file_stat.st_mode))
|
||||
{
|
||||
char *link_name;
|
||||
int link_size;
|
||||
link_name = (char *) xmalloc ((unsigned int) in_file_stat.st_size + 1);
|
||||
|
||||
link_size = readlink (input_name.ds_string, link_name,
|
||||
in_file_stat.st_size);
|
||||
if (link_size < 0)
|
||||
{
|
||||
readlink_error (input_name.ds_string);
|
||||
free (link_name);
|
||||
continue;
|
||||
}
|
||||
link_name[link_size] = '\0';
|
||||
|
||||
res = UMASKED_SYMLINK (link_name, output_name.ds_string,
|
||||
in_file_stat.st_mode);
|
||||
if (res < 0 && create_dir_flag)
|
||||
{
|
||||
create_all_directories (output_name.ds_string);
|
||||
res = UMASKED_SYMLINK (link_name, output_name.ds_string,
|
||||
in_file_stat.st_mode);
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
symlink_error (output_name.ds_string, link_name);
|
||||
free (link_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set the attributes of the new link. */
|
||||
if (!no_chown_flag)
|
||||
{
|
||||
uid_t uid = set_owner_flag ? set_owner : in_file_stat.st_uid;
|
||||
gid_t gid = set_group_flag ? set_group : in_file_stat.st_gid;
|
||||
if ((lchown (output_name.ds_string, uid, gid) < 0)
|
||||
&& errno != EPERM)
|
||||
chown_error_details (output_name.ds_string, uid, gid);
|
||||
}
|
||||
free (link_name);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
error (0, 0, _("%s: unknown file type"), input_name.ds_string);
|
||||
}
|
||||
|
||||
if (verbose_flag)
|
||||
fprintf (stderr, "%s\n", output_name.ds_string);
|
||||
if (dot_flag)
|
||||
fputc ('.', stderr);
|
||||
}
|
||||
|
||||
if (dot_flag)
|
||||
fputc ('\n', stderr);
|
||||
if (!quiet_flag)
|
||||
{
|
||||
res = (output_bytes + io_block_size - 1) / io_block_size;
|
||||
fprintf (stderr, ngettext ("%d block\n", "%d blocks\n", res), 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 (char *file_name, int st_dev_maj, int st_dev_min,
|
||||
int st_ino)
|
||||
{
|
||||
int link_res;
|
||||
char *link_name;
|
||||
link_res = -1;
|
||||
/* 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);
|
||||
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 (char *link_name, char *link_target)
|
||||
{
|
||||
int 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 (will copy instead)"),
|
||||
link_target, link_name);
|
||||
}
|
||||
return res;
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/* Extended cpio format from POSIX.1.
|
||||
Copyright (C) 1992, 2005 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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 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. */
|
||||
|
||||
#define CPIO_TRAILER_NAME "TRAILER!!!"
|
||||
|
||||
/* 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 */
|
@ -1,106 +0,0 @@
|
||||
/* Extended cpio header from POSIX.1.
|
||||
Copyright (C) 1992, 2006 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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 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];
|
||||
};
|
||||
|
||||
struct old_ascii_header
|
||||
{
|
||||
char c_magic[6];
|
||||
char c_dev[6];
|
||||
char c_ino[6];
|
||||
char c_mode[6];
|
||||
char c_uid[6];
|
||||
char c_gid[6];
|
||||
char c_nlink[6];
|
||||
char c_rdev[6];
|
||||
char c_mtime[11];
|
||||
char c_namesize[6];
|
||||
char c_filesize[11];
|
||||
};
|
||||
|
||||
/* "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: */
|
||||
|
||||
struct new_ascii_header
|
||||
{
|
||||
char c_magic[6]; /* "070701" for "new" portable format
|
||||
"070702" for CRC format */
|
||||
char c_ino[8];
|
||||
char c_mode[8];
|
||||
char c_uid[8];
|
||||
char c_gid[8];
|
||||
char c_nlink[8];
|
||||
char c_mtime[8];
|
||||
char c_filesize[8]; /* must be 0 for FIFOs and directories */
|
||||
char c_dev_maj[8];
|
||||
char c_dev_min[8];
|
||||
char c_rdev_maj[8]; /* only valid for chr and blk special files */
|
||||
char c_rdev_min[8]; /* only valid for chr and blk special files */
|
||||
char c_namesize[8]; /* count includes terminating NUL in pathname */
|
||||
char c_chksum[8]; /* 0 for "new" portable format; for CRC format
|
||||
the sum of all the bytes in the file */
|
||||
};
|
||||
|
||||
struct cpio_file_stat /* Internal representation of a CPIO header */
|
||||
{
|
||||
unsigned short c_magic;
|
||||
ino_t c_ino;
|
||||
mode_t c_mode;
|
||||
uid_t c_uid;
|
||||
gid_t c_gid;
|
||||
size_t c_nlink;
|
||||
time_t c_mtime;
|
||||
off_t c_filesize;
|
||||
long c_dev_maj;
|
||||
long c_dev_min;
|
||||
long c_rdev_maj;
|
||||
long c_rdev_min;
|
||||
size_t c_namesize;
|
||||
unsigned long c_chksum;
|
||||
char *c_name;
|
||||
char *c_tar_linkname;
|
||||
};
|
||||
|
||||
|
||||
#endif /* cpiohdr.h */
|
@ -1,43 +0,0 @@
|
||||
/* defer.c - handle "defered" links in newc and crc archives
|
||||
Copyright (C) 1993, 2003, 2004, 2006 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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "cpiohdr.h"
|
||||
#include "extern.h"
|
||||
#include "defer.h"
|
||||
|
||||
struct deferment *
|
||||
create_deferment (struct cpio_file_stat *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 (struct deferment *d)
|
||||
{
|
||||
free (d->header.c_name);
|
||||
free (d);
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/* defer.h
|
||||
Copyright (C) 1993, 2001, 2004, 2006 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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
struct deferment
|
||||
{
|
||||
struct deferment *next;
|
||||
struct cpio_file_stat header;
|
||||
};
|
||||
|
||||
struct deferment *create_deferment (struct cpio_file_stat *file_hdr);
|
||||
void free_deferment (struct deferment *d);
|
@ -1,103 +0,0 @@
|
||||
/* dstring.c - The dynamic string handling routines used by cpio.
|
||||
Copyright (C) 1990, 1991, 1992, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#include "dstring.h"
|
||||
|
||||
char *xmalloc (unsigned n);
|
||||
char *xrealloc (char *p, unsigned n);
|
||||
|
||||
/* Initialiaze dynamic string STRING with space for SIZE characters. */
|
||||
|
||||
void
|
||||
ds_init (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 (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 (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 (FILE *f, dynamic_string *s)
|
||||
{
|
||||
return ds_fgetstr (f, s, '\n');
|
||||
}
|
||||
|
||||
char *
|
||||
ds_fgetname (FILE *f, dynamic_string *s)
|
||||
{
|
||||
return ds_fgetstr (f, s, '\0');
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/* dstring.h - Dynamic string handling include file. Requires strings.h.
|
||||
Copyright (C) 1990, 1991, 1992, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 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 (dynamic_string *string, int size);
|
||||
void ds_resize (dynamic_string *string, int size);
|
||||
char *ds_fgetname (FILE *f, dynamic_string *s);
|
||||
char *ds_fgets (FILE *f, dynamic_string *s);
|
||||
char *ds_fgetstr (FILE *f, dynamic_string *s, char eos);
|
@ -1,221 +0,0 @@
|
||||
/* extern.h - External declarations for cpio. Requires system.h.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2006 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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include "paxlib.h"
|
||||
#include "quotearg.h"
|
||||
#include "quote.h"
|
||||
|
||||
enum archive_format
|
||||
{
|
||||
arf_unknown, arf_binary, arf_oldascii, arf_newascii, arf_crcascii,
|
||||
arf_tar, arf_ustar, arf_hpoldascii, arf_hpbinary
|
||||
};
|
||||
|
||||
extern enum archive_format archive_format;
|
||||
extern int reset_time_flag;
|
||||
extern int io_block_size;
|
||||
extern int create_dir_flag;
|
||||
extern int rename_flag;
|
||||
extern char *rename_batch_file;
|
||||
extern int table_flag;
|
||||
extern int unconditional_flag;
|
||||
extern int verbose_flag;
|
||||
extern int dot_flag;
|
||||
extern int link_flag;
|
||||
extern int retain_time_flag;
|
||||
extern int crc_i_flag;
|
||||
extern int append_flag;
|
||||
extern int swap_bytes_flag;
|
||||
extern int swap_halfwords_flag;
|
||||
extern int swapping_bytes;
|
||||
extern int swapping_halfwords;
|
||||
extern int set_owner_flag;
|
||||
extern uid_t set_owner;
|
||||
extern int set_group_flag;
|
||||
extern gid_t set_group;
|
||||
extern int no_chown_flag;
|
||||
extern int sparse_flag;
|
||||
extern int quiet_flag;
|
||||
extern int only_verify_crc_flag;
|
||||
extern int abs_paths_flag;
|
||||
extern unsigned int warn_option;
|
||||
|
||||
/* Values for warn_option */
|
||||
#define CPIO_WARN_NONE 0
|
||||
#define CPIO_WARN_TRUNCATE 0x01
|
||||
#define CPIO_WARN_ALL (unsigned int)-1
|
||||
|
||||
extern bool to_stdout_option;
|
||||
|
||||
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 char *rsh_command_option;
|
||||
extern unsigned int crc;
|
||||
extern int delayed_seek_count;
|
||||
#ifdef DEBUG_CPIO
|
||||
extern int debug_flag;
|
||||
#endif
|
||||
|
||||
extern char *input_buffer, *output_buffer;
|
||||
extern char *in_buff, *out_buff;
|
||||
extern long input_buffer_size;
|
||||
extern long input_size, output_size;
|
||||
#ifdef __GNUC__
|
||||
extern long long input_bytes, output_bytes;
|
||||
#else
|
||||
extern long input_bytes, output_bytes;
|
||||
#endif
|
||||
extern char *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 char *program_name;
|
||||
extern int (*xstat) ();
|
||||
extern void (*copy_function) ();
|
||||
|
||||
|
||||
/* copyin.c */
|
||||
void warn_junk_bytes (long bytes_skipped);
|
||||
/* FIXME: make read_* static in copyin.c */
|
||||
void read_in_header (struct cpio_file_stat *file_hdr, int in_des);
|
||||
void read_in_old_ascii (struct cpio_file_stat *file_hdr, int in_des);
|
||||
void read_in_new_ascii (struct cpio_file_stat *file_hdr, int in_des);
|
||||
void read_in_binary (struct cpio_file_stat *file_hdr,
|
||||
struct old_cpio_header *short_hdr, int in_des);
|
||||
void swab_array (char *arg, int count);
|
||||
void process_copy_in (void);
|
||||
void long_format (struct cpio_file_stat *file_hdr, char *link_name);
|
||||
void print_name_with_quoting (char *p);
|
||||
|
||||
/* copyout.c */
|
||||
int write_out_header (struct cpio_file_stat *file_hdr, int out_des);
|
||||
void process_copy_out (void);
|
||||
|
||||
/* copypass.c */
|
||||
void process_copy_pass (void);
|
||||
int link_to_maj_min_ino (char *file_name, int st_dev_maj,
|
||||
int st_dev_min, int st_ino);
|
||||
int link_to_name (char *link_name, char *link_target);
|
||||
|
||||
/* dirname.c */
|
||||
char *dirname (char *path);
|
||||
|
||||
/* filemode.c */
|
||||
void mode_string (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 (int argc, char *argv[]);
|
||||
void initialize_buffers (void);
|
||||
|
||||
/* makepath.c */
|
||||
int make_path (char *argpath, int mode, int parent_mode,
|
||||
uid_t owner, gid_t group, char *verbose_fmt_string);
|
||||
|
||||
/* tar.c */
|
||||
void write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des);
|
||||
int null_block (long *block, int size);
|
||||
void read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des);
|
||||
int otoa (char *s, unsigned long *n);
|
||||
int is_tar_header (char *buf);
|
||||
int is_tar_filename_too_long (char *name);
|
||||
|
||||
/* userspec.c */
|
||||
#ifndef __MSDOS__
|
||||
char *parse_user_spec (char *name, uid_t *uid, gid_t *gid,
|
||||
char **username, char **groupname);
|
||||
#endif
|
||||
|
||||
/* util.c */
|
||||
void tape_empty_output_buffer (int out_des);
|
||||
void disk_empty_output_buffer (int out_des);
|
||||
void swahw_array (char *ptr, int count);
|
||||
void tape_buffered_write (char *in_buf, int out_des, off_t num_bytes);
|
||||
void tape_buffered_read (char *in_buf, int in_des, off_t num_bytes);
|
||||
int tape_buffered_peek (char *peek_buf, int in_des, int num_bytes);
|
||||
void tape_toss_input (int in_des, off_t num_bytes);
|
||||
void copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes);
|
||||
void copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes, char *filename);
|
||||
void copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes, char *filename);
|
||||
void warn_if_file_changed (char *file_name, unsigned long old_file_size,
|
||||
off_t old_file_mtime);
|
||||
void create_all_directories (char *name);
|
||||
void prepare_append (int out_file_des);
|
||||
char *find_inode_file (unsigned long node_num,
|
||||
unsigned long major_num, unsigned long minor_num);
|
||||
void add_inode (unsigned long node_num, char *file_name,
|
||||
unsigned long major_num, unsigned long minor_num);
|
||||
int open_archive (char *file);
|
||||
void tape_offline (int tape_des);
|
||||
void get_next_reel (int tape_des);
|
||||
void set_new_media_message (char *message);
|
||||
#if defined(__MSDOS__) && !defined(__GNUC__)
|
||||
int chown (char *path, int owner, int group);
|
||||
#endif
|
||||
#ifdef __TURBOC__
|
||||
int utime (char *filename, struct utimbuf *utb);
|
||||
#endif
|
||||
#ifdef HPUX_CDF
|
||||
char *add_cdf_double_slashes (char *filename);
|
||||
#endif
|
||||
void write_nuls_to_file (off_t num_bytes, int out_des,
|
||||
void (*writer) (char *in_buf,
|
||||
int out_des, off_t num_bytes));
|
||||
#define DISK_IO_BLOCK_SIZE 512
|
||||
|
||||
/* FIXME: Move to system.h? */
|
||||
#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 */
|
||||
|
||||
void set_perms (int fd, struct cpio_file_stat *header);
|
||||
void set_file_times (int fd, const char *name, unsigned long atime,
|
||||
unsigned long mtime);
|
||||
void stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st);
|
||||
void cpio_safer_name_suffix (char *name, bool link_target,
|
||||
bool absolute_names, bool strip_leading_dots);
|
||||
|
||||
/* FIXME: These two defines should be defined in paxutils */
|
||||
#define LG_8 3
|
||||
#define LG_16 4
|
||||
|
||||
uintmax_t from_ascii (char const *where, size_t digs, unsigned logbase);
|
||||
|
||||
#define FROM_OCTAL(f) from_ascii (f, sizeof f, LG_8)
|
||||
#define FROM_HEX(f) from_ascii (f, sizeof f, LG_16)
|
||||
|
@ -1,243 +0,0 @@
|
||||
/* filemode.c -- make a string describing file modes
|
||||
Copyright (C) 1985, 1990, 1993, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !S_IRUSR
|
||||
# if S_IREAD
|
||||
# define S_IRUSR S_IREAD
|
||||
# else
|
||||
# define S_IRUSR 00400
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !S_IWUSR
|
||||
# if S_IWRITE
|
||||
# define S_IWUSR S_IWRITE
|
||||
# else
|
||||
# define S_IWUSR 00200
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !S_IXUSR
|
||||
# if S_IEXEC
|
||||
# define S_IXUSR S_IEXEC
|
||||
# else
|
||||
# define S_IXUSR 00100
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef STAT_MACROS_BROKEN
|
||||
#undef S_ISBLK
|
||||
#undef S_ISCHR
|
||||
#undef S_ISDIR
|
||||
#undef S_ISFIFO
|
||||
#undef S_ISLNK
|
||||
#undef S_ISMPB
|
||||
#undef S_ISMPC
|
||||
#undef S_ISNWK
|
||||
#undef S_ISREG
|
||||
#undef S_ISSOCK
|
||||
#endif /* STAT_MACROS_BROKEN. */
|
||||
|
||||
#if !defined(S_ISBLK) && defined(S_IFBLK)
|
||||
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
#endif
|
||||
#if !defined(S_ISCHR) && defined(S_IFCHR)
|
||||
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
#endif
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#if !defined(S_ISREG) && defined(S_IFREG)
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#if !defined(S_ISFIFO) && defined(S_IFIFO)
|
||||
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
#endif
|
||||
#if !defined(S_ISLNK) && defined(S_IFLNK)
|
||||
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
|
||||
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
||||
#endif
|
||||
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
|
||||
#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
|
||||
#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
|
||||
#endif
|
||||
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
|
||||
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
|
||||
#endif
|
||||
|
||||
/* 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 (long bits)
|
||||
{
|
||||
#ifdef S_ISBLK
|
||||
if (S_ISBLK (bits))
|
||||
return 'b';
|
||||
#endif
|
||||
if (S_ISCHR (bits))
|
||||
return 'c';
|
||||
if (S_ISDIR (bits))
|
||||
return 'd';
|
||||
if (S_ISREG (bits))
|
||||
return '-';
|
||||
#ifdef S_ISFIFO
|
||||
if (S_ISFIFO (bits))
|
||||
return 'p';
|
||||
#endif
|
||||
#ifdef S_ISLNK
|
||||
if (S_ISLNK (bits))
|
||||
return 'l';
|
||||
#endif
|
||||
#ifdef S_ISSOCK
|
||||
if (S_ISSOCK (bits))
|
||||
return 's';
|
||||
#endif
|
||||
#ifdef S_ISMPC
|
||||
if (S_ISMPC (bits))
|
||||
return 'm';
|
||||
#endif
|
||||
#ifdef S_ISNWK
|
||||
if (S_ISNWK (bits))
|
||||
return 'n';
|
||||
#endif
|
||||
return '?';
|
||||
}
|
||||
|
||||
/* Look at read, write, and execute bits in BITS and set
|
||||
flags in CHARS accordingly. */
|
||||
|
||||
static void
|
||||
rwx (unsigned short bits, char *chars)
|
||||
{
|
||||
chars[0] = (bits & S_IRUSR) ? 'r' : '-';
|
||||
chars[1] = (bits & S_IWUSR) ? 'w' : '-';
|
||||
chars[2] = (bits & S_IXUSR) ? 'x' : '-';
|
||||
}
|
||||
|
||||
/* Set the 's' and 't' flags in file attributes string CHARS,
|
||||
according to the file mode BITS. */
|
||||
|
||||
static void
|
||||
setst (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
|
||||
}
|
||||
|
||||
/* Like filemodestring (see below), but only the relevant part of the
|
||||
`struct stat' is given as an argument. */
|
||||
|
||||
void
|
||||
mode_string (unsigned short mode, char *str)
|
||||
{
|
||||
str[0] = ftypelet ((long) mode);
|
||||
rwx ((mode & 0700) << 0, &str[1]);
|
||||
rwx ((mode & 0070) << 3, &str[4]);
|
||||
rwx ((mode & 0007) << 6, &str[7]);
|
||||
setst (mode, str);
|
||||
}
|
||||
|
||||
/* 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 (struct stat *statp, char *str)
|
||||
{
|
||||
mode_string (statp->st_mode, str);
|
||||
}
|
||||
|
@ -1,85 +0,0 @@
|
||||
/* filetypes.h - deal with POSIX annoyances
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 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 ();
|
@ -1,201 +0,0 @@
|
||||
/* global.c - global variables and initial values for cpio.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2006 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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "cpiohdr.h"
|
||||
#include "dstring.h"
|
||||
#include "extern.h"
|
||||
|
||||
/* If true, reset access times after reading files (-a). */
|
||||
int reset_time_flag = false;
|
||||
|
||||
/* Block size value, initially 512. -B sets to 5120. */
|
||||
int io_block_size = 512;
|
||||
|
||||
/* The header format to recognize and produce. */
|
||||
enum archive_format archive_format = arf_unknown;
|
||||
|
||||
/* If true, create directories as needed. (-d with -i or -p) */
|
||||
int create_dir_flag = false;
|
||||
|
||||
/* If true, interactively rename files. (-r) */
|
||||
int rename_flag = false;
|
||||
|
||||
/* If non-NULL, the name of a file that will be read to
|
||||
rename all of the files in the archive. --rename-batch-file. */
|
||||
char *rename_batch_file = NULL;
|
||||
|
||||
/* If true, print a table of contents of input. (-t) */
|
||||
int table_flag = false;
|
||||
|
||||
/* If true, copy unconditionally (older replaces newer). (-u) */
|
||||
int unconditional_flag = false;
|
||||
|
||||
/* If true, list the files processed, or ls -l style output with -t. (-v) */
|
||||
int verbose_flag = false;
|
||||
|
||||
/* If true, print a . for each file processed. (-V) */
|
||||
int dot_flag = false;
|
||||
|
||||
/* If true, link files whenever possible. Used with -p option. (-l) */
|
||||
int link_flag = false;
|
||||
|
||||
/* If true, retain previous file modification time. (-m) */
|
||||
int retain_time_flag = false;
|
||||
|
||||
/* Set true if crc_flag is true and we are doing a cpio -i. Used
|
||||
by copy_files so it knows whether to compute the crc. */
|
||||
int crc_i_flag = false;
|
||||
|
||||
/* If true, append to end of archive. (-A) */
|
||||
int append_flag = false;
|
||||
|
||||
/* If true, swap bytes of each file during cpio -i. */
|
||||
int swap_bytes_flag = false;
|
||||
|
||||
/* If true, swap halfwords of each file during cpio -i. */
|
||||
int swap_halfwords_flag = false;
|
||||
|
||||
/* If true, we are swapping halfwords on the current file. */
|
||||
int swapping_halfwords = false;
|
||||
|
||||
/* If true, we are swapping bytes on the current file. */
|
||||
int swapping_bytes = false;
|
||||
|
||||
/* If true, set ownership of all files to UID `set_owner'. */
|
||||
int set_owner_flag = false;
|
||||
uid_t set_owner;
|
||||
|
||||
/* If true, set group ownership of all files to GID `set_group'. */
|
||||
int set_group_flag = false;
|
||||
gid_t set_group;
|
||||
|
||||
/* If true, do not chown the files. */
|
||||
int no_chown_flag = false;
|
||||
|
||||
/* If true, try to write sparse ("holey") files. */
|
||||
int sparse_flag = false;
|
||||
|
||||
/* If true, don't report number of blocks copied. */
|
||||
int quiet_flag = false;
|
||||
|
||||
/* If true, only read the archive and verify the files' CRC's, don't
|
||||
actually extract the files. */
|
||||
int only_verify_crc_flag = false;
|
||||
|
||||
/* If true, don't use any absolute paths, prefix them by `./'. */
|
||||
int abs_paths_flag = false;
|
||||
|
||||
#ifdef DEBUG_CPIO
|
||||
/* If true, print debugging information. */
|
||||
int debug_flag = false;
|
||||
#endif
|
||||
|
||||
/* File position of last header read. Only used during -A to determine
|
||||
where the old TRAILER!!! record started. */
|
||||
int last_header_start = 0;
|
||||
|
||||
/* With -i; if true, copy only files that match any of the given patterns;
|
||||
if false, copy only files that do not match any of the patterns. (-f) */
|
||||
int copy_matching_files = true;
|
||||
|
||||
/* With -itv; if true, list numeric uid and gid instead of translating them
|
||||
into names. */
|
||||
int numeric_uid = false;
|
||||
|
||||
/* Name of file containing additional patterns (-E). */
|
||||
char *pattern_file_name = NULL;
|
||||
|
||||
/* Message to print when end of medium is reached (-M). */
|
||||
char *new_media_message = NULL;
|
||||
|
||||
/* With -M with %d, message to print when end of medium is reached. */
|
||||
char *new_media_message_with_number = NULL;
|
||||
char *new_media_message_after_number = NULL;
|
||||
|
||||
/* File descriptor containing the archive. */
|
||||
int archive_des;
|
||||
|
||||
/* Name of file containing the archive, if known; NULL if stdin/out. */
|
||||
char *archive_name = NULL;
|
||||
|
||||
/* Name of the remote shell command, if known; NULL otherwise. */
|
||||
char *rsh_command_option = NULL;
|
||||
|
||||
/* CRC checksum. */
|
||||
unsigned int crc;
|
||||
|
||||
/* Input and output buffers. */
|
||||
char *input_buffer, *output_buffer;
|
||||
|
||||
/* The size of the input buffer. */
|
||||
long input_buffer_size;
|
||||
|
||||
/* Current locations in `input_buffer' and `output_buffer'. */
|
||||
char *in_buff, *out_buff;
|
||||
|
||||
/* Current number of bytes stored at `input_buff' and `output_buff'. */
|
||||
long input_size, output_size;
|
||||
|
||||
/* Total number of bytes read and written for all files.
|
||||
Now that many tape drives hold more than 4Gb we need more than 32
|
||||
bits to hold input_bytes and output_bytes. But it's not worth
|
||||
the trouble of adding special multi-precision arithmetic if the
|
||||
compiler doesn't support 64 bit ints since input_bytes and
|
||||
output_bytes are only used to print the number of blocks copied. */
|
||||
#ifdef __GNUC__
|
||||
long long input_bytes, output_bytes;
|
||||
#else
|
||||
long input_bytes, output_bytes;
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Print extra warning messages */
|
||||
unsigned int warn_option = 0;
|
||||
|
||||
/* Extract to standard output? */
|
||||
bool to_stdout_option = false;
|
||||
|
||||
/* 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;
|
@ -1,207 +0,0 @@
|
||||
/* idcache.c -- map user and group IDs, cached for speed
|
||||
Copyright (C) 1985, 1988, 1989, 1990, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifndef _POSIX_VERSION
|
||||
struct passwd *getpwuid ();
|
||||
struct passwd *getpwnam ();
|
||||
struct group *getgrgid ();
|
||||
struct group *getgrnam ();
|
||||
#endif
|
||||
|
||||
char *xmalloc ();
|
||||
char *xstrdup ();
|
||||
|
||||
struct userid
|
||||
{
|
||||
union
|
||||
{
|
||||
uid_t u;
|
||||
gid_t g;
|
||||
} id;
|
||||
char *name;
|
||||
struct userid *next;
|
||||
};
|
||||
|
||||
static struct userid *user_alist;
|
||||
|
||||
/* The members of this list have names not in the local passwd file. */
|
||||
static struct userid *nouser_alist;
|
||||
|
||||
/* Translate UID to a login name or a stringified number,
|
||||
with cache. */
|
||||
|
||||
char *
|
||||
getuser (uid_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 (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_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 (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;
|
||||
}
|
@ -1,804 +0,0 @@
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/* main.c - main program and argument processing for cpio.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004, 2005, 2006
|
||||
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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
/* Written by Phil Nelson <phil@cs.wwu.edu>,
|
||||
David MacKenzie <djm@gnu.ai.mit.edu>,
|
||||
John Oleynick <juo@klinzhai.rutgers.edu>,
|
||||
and Sergey Poznyakoff <gray@mirddin.farlep.net> */
|
||||
|
||||
#include <system.h>
|
||||
#include <paxlib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <argp.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
#include "filetypes.h"
|
||||
#include "cpiohdr.h"
|
||||
#include "dstring.h"
|
||||
#include "extern.h"
|
||||
#include <rmt.h>
|
||||
#include <rmt-command.h>
|
||||
|
||||
enum cpio_options {
|
||||
NO_ABSOLUTE_FILENAMES_OPTION=256,
|
||||
ABSOLUTE_FILENAMES_OPTION,
|
||||
NO_PRESERVE_OWNER_OPTION,
|
||||
ONLY_VERIFY_CRC_OPTION,
|
||||
RENAME_BATCH_FILE_OPTION,
|
||||
RSH_COMMAND_OPTION,
|
||||
QUIET_OPTION,
|
||||
SPARSE_OPTION,
|
||||
FORCE_LOCAL_OPTION,
|
||||
DEBUG_OPTION,
|
||||
BLOCK_SIZE_OPTION,
|
||||
TO_STDOUT_OPTION,
|
||||
|
||||
HANG_OPTION,
|
||||
USAGE_OPTION,
|
||||
LICENSE_OPTION,
|
||||
VERSION_OPTION
|
||||
};
|
||||
|
||||
const char *argp_program_version = "cpio (" PACKAGE_NAME ") " VERSION;
|
||||
const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
|
||||
static char doc[] = N_("GNU `cpio' copies files to and from archives\n\
|
||||
\n\
|
||||
Examples:\n\
|
||||
# Copy files named in name-list to the archive\n\
|
||||
cpio -o < name-list [> archive]\n\
|
||||
# Extract files from the archive\n\
|
||||
cpio -i [< archive]\n\
|
||||
# Copy files named in name-list to destination-directory\n\
|
||||
cpio -p destination-directory < name-list\n");
|
||||
|
||||
/* Print usage error message and exit with error. */
|
||||
|
||||
#define CHECK_USAGE(cond, opt, mode_opt) \
|
||||
if (cond) \
|
||||
ERROR((PAXEXIT_FAILURE, 0, _("%s is meaningless with %s"), opt, mode_opt));
|
||||
|
||||
static struct argp_option options[] = {
|
||||
/* ********** */
|
||||
#define GRID 10
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Main operation mode:"), GRID },
|
||||
{"create", 'o', 0, 0,
|
||||
N_("Create the archive (run in copy-out mode)"), GRID },
|
||||
{"extract", 'i', 0, 0,
|
||||
N_("Extract files from an archive (run in copy-in mode)"), GRID },
|
||||
{"pass-through", 'p', 0, 0,
|
||||
N_("Run in copy-pass mode"), GRID },
|
||||
{"list", 't', 0, 0,
|
||||
N_("Print a table of contents of the input"), GRID },
|
||||
#undef GRID
|
||||
|
||||
/* ********** */
|
||||
#define GRID 100
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Operation modifiers valid in any mode:"), GRID },
|
||||
|
||||
{"file", 'F', N_("[[USER@]HOST:]FILE-NAME"), 0,
|
||||
N_("Use this FILE-NAME instead of standard input or output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
|
||||
{"force-local", FORCE_LOCAL_OPTION, 0, 0,
|
||||
N_("Archive file is local, even if its name contains colons"), GRID+1 },
|
||||
{"format", 'H', N_("FORMAT"), 0,
|
||||
N_("Use given archive FORMAT"), GRID+1 },
|
||||
{NULL, 'B', NULL, 0,
|
||||
N_("Set the I/O block size to 5120 bytes"), GRID+1 },
|
||||
{"block-size", BLOCK_SIZE_OPTION, N_("BLOCK-SIZE"), 0,
|
||||
N_("Set the I/O block size to BLOCK-SIZE * 512 bytes"), GRID+1 },
|
||||
{NULL, 'c', NULL, 0,
|
||||
N_("Use the old portable (ASCII) archive format"), GRID+1 },
|
||||
{"dot", 'V', NULL, 0,
|
||||
N_("Print a \".\" for each file processed"), GRID+1 },
|
||||
{"io-size", 'C', N_("NUMBER"), 0,
|
||||
N_("Set the I/O block size to the given NUMBER of bytes"), GRID+1 },
|
||||
{"message", 'M', N_("STRING"), 0,
|
||||
N_("Print STRING when the end of a volume of the backup media is reached"),
|
||||
GRID+1 },
|
||||
{"nonmatching", 'f', 0, 0,
|
||||
N_("Only copy files that do not match any of the given patterns"), GRID+1 },
|
||||
{"numeric-uid-gid", 'n', 0, 0,
|
||||
N_("In the verbose table of contents listing, show numeric UID and GID"),
|
||||
GRID+1 },
|
||||
{"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
|
||||
N_("Use remote COMMAND instead of rsh"), GRID+1 },
|
||||
{"quiet", QUIET_OPTION, NULL, 0,
|
||||
N_("Do not print the number of blocks copied"), GRID+1 },
|
||||
{"verbose", 'v', NULL, 0,
|
||||
N_("Verbosely list the files processed"), GRID+1 },
|
||||
#ifdef DEBUG_CPIO
|
||||
{"debug", DEBUG_OPTION, NULL, 0,
|
||||
N_("Enable debugging info"), GRID+1 },
|
||||
#endif
|
||||
{"warning", 'W', N_("FLAG"), 0,
|
||||
N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
/* ********** */
|
||||
#define GRID 200
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Operation modifiers valid only in copy-in mode:"), GRID },
|
||||
{"pattern-file", 'E', N_("FILE"), 0,
|
||||
N_("Read additional patterns specifying filenames to extract or list from FILE"), 210},
|
||||
{"absolute-filenames", ABSOLUTE_FILENAMES_OPTION, 0, 0,
|
||||
N_("do not strip leading file name components that contain \"..\" and leading slashes from file names"), 210},
|
||||
{"only-verify-crc", ONLY_VERIFY_CRC_OPTION, 0, 0,
|
||||
N_("When reading a CRC format archive, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
|
||||
{"rename", 'r', 0, 0,
|
||||
N_("Interactively rename files"), GRID+1 },
|
||||
{"rename-batch-file", RENAME_BATCH_FILE_OPTION, N_("FILE"), OPTION_HIDDEN,
|
||||
"", GRID+1 },
|
||||
{"swap", 'b', NULL, 0,
|
||||
N_("Swap both halfwords of words and bytes of halfwords in the data. Equivalent to -sS"), GRID+1 },
|
||||
{"swap-bytes", 's', NULL, 0,
|
||||
N_("Swap the bytes of each halfword in the files"), GRID+1 },
|
||||
{"swap-halfwords", 'S', NULL, 0,
|
||||
N_("Swap the halfwords of each word (4 bytes) in the files"),
|
||||
GRID+1 },
|
||||
{"to-stdout", TO_STDOUT_OPTION, NULL, 0,
|
||||
N_("Extract files to standard output"), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
/* ********** */
|
||||
#define GRID 300
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Operation modifiers valid only in copy-out mode:"), GRID },
|
||||
{"append", 'A', 0, 0,
|
||||
N_("Append to an existing archive."), GRID+1 },
|
||||
{NULL, 'O', N_("[[USER@]HOST:]FILE-NAME"), 0,
|
||||
N_("Archive filename to use instead of standard output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
/* ********** */
|
||||
#define GRID 400
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Operation modifiers valid only in copy-pass mode:"), GRID},
|
||||
{"link", 'l', 0, 0,
|
||||
N_("Link files instead of copying them, when possible"), GRID+1 },
|
||||
|
||||
#undef GRID
|
||||
|
||||
/* ********** */
|
||||
#define GRID 500
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Operation modifiers valid in copy-in and copy-out modes:"), GRID },
|
||||
{"absolute-filenames", ABSOLUTE_FILENAMES_OPTION, 0, 0,
|
||||
N_("Do not strip file system prefix components from the file names"),
|
||||
GRID+1 },
|
||||
{"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
|
||||
N_("Create all files relative to the current directory"), GRID+1 },
|
||||
#undef GRID
|
||||
/* ********** */
|
||||
#define GRID 600
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Operation modifiers valid in copy-out and copy-pass modes:"), GRID },
|
||||
{"null", '0', 0, 0,
|
||||
N_("A list of filenames is terminated by a null character instead of a newline"), GRID+1 },
|
||||
{NULL, 'I', N_("[[USER@]HOST:]FILE-NAME"), 0,
|
||||
N_("Archive filename to use instead of standard input. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
|
||||
{"dereference", 'L', 0, 0,
|
||||
N_("Dereference symbolic links (copy the files that they point to instead of copying the links)."), GRID+1 },
|
||||
{"owner", 'R', N_("[USER][:.][GROUP]"), 0,
|
||||
N_("Set the ownership of all files created to the specified USER and/or GROUP"), GRID+1 },
|
||||
{"reset-access-time", 'a', NULL, 0,
|
||||
N_("Reset the access times of files after reading them"), GRID+1 },
|
||||
|
||||
#undef GRID
|
||||
/* ********** */
|
||||
#define GRID 700
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Operation modifiers valid in copy-in and copy-pass modes:"), GRID },
|
||||
{"preserve-modification-time", 'm', 0, 0,
|
||||
N_("Retain previous file modification times when creating files"), GRID+1 },
|
||||
{"make-directories", 'd', 0, 0,
|
||||
N_("Create leading directories where needed"), GRID+1 },
|
||||
{"no-preserve-owner", NO_PRESERVE_OWNER_OPTION, 0, 0,
|
||||
N_("Do not change the ownership of the files"), GRID+1 },
|
||||
{"unconditional", 'u', NULL, 0,
|
||||
N_("Replace all files unconditionally"), GRID+1 },
|
||||
{"sparse", SPARSE_OPTION, NULL, 0,
|
||||
N_("Write files with large blocks of zeros as sparse files"), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
/* ********** */
|
||||
#define GRID 800
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Informative options:"), GRID },
|
||||
|
||||
{"help", '?', 0, 0, N_("Give this help list"), -1},
|
||||
{"usage", USAGE_OPTION, 0, 0, N_("Give a short usage message"), -1},
|
||||
{"license", LICENSE_OPTION, 0, 0, N_("Print license and exit"), -1},
|
||||
{"version", VERSION_OPTION, 0, 0, N_("Print program version"), -1},
|
||||
/* FIXME -V (--dot) conflicts with the default short option for
|
||||
--version */
|
||||
{"HANG", HANG_OPTION, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
|
||||
N_("hang for SECS seconds (default 3600)"), 0},
|
||||
#undef GRID
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static char *input_archive_name = 0;
|
||||
static char *output_archive_name = 0;
|
||||
|
||||
static void
|
||||
license ()
|
||||
{
|
||||
printf ("%s (%s) %s\n%s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION,
|
||||
"Copyright (C) 2004 Free Software Foundation, Inc.\n");
|
||||
printf (_(" GNU cpio is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
" (at your option) any later version.\n"
|
||||
"\n"
|
||||
" GNU cpio is distributed in the hope that it will be useful,\n"
|
||||
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
" GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
" You should have received a copy of the GNU General Public License\n"
|
||||
" along with GNU cpio; if not, write to the Free Software Foundation,\n"
|
||||
" Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n\n"));
|
||||
exit (0);
|
||||
}
|
||||
|
||||
static int
|
||||
warn_control (char *arg)
|
||||
{
|
||||
static struct warn_tab {
|
||||
char *name;
|
||||
int flag;
|
||||
} warn_tab[] = {
|
||||
{ "none", CPIO_WARN_ALL },
|
||||
{ "truncate", CPIO_WARN_TRUNCATE },
|
||||
{ "all", CPIO_WARN_ALL },
|
||||
{ NULL }
|
||||
};
|
||||
struct warn_tab *wt;
|
||||
int offset = 0;
|
||||
|
||||
if (strcmp (arg, "none") == 0)
|
||||
{
|
||||
warn_option = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strlen (arg) > 2 && memcmp (arg, "no-", 3) == 0)
|
||||
offset = 3;
|
||||
|
||||
for (wt = warn_tab; wt->name; wt++)
|
||||
if (strcmp (arg + offset, wt->name) == 0)
|
||||
{
|
||||
if (offset)
|
||||
warn_option &= ~wt->flag;
|
||||
else
|
||||
warn_option |= wt->flag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static error_t
|
||||
parse_opt (int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
static volatile int _argp_hang;
|
||||
switch (key)
|
||||
{
|
||||
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 BLOCK_SIZE_OPTION: /* --block-size */
|
||||
io_block_size = atoi (arg);
|
||||
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)
|
||||
error (0, EXIT_FAILURE, _("Archive format multiply defined"));
|
||||
#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 (arg);
|
||||
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 = arg;
|
||||
break;
|
||||
|
||||
case 'F': /* Archive file name. */
|
||||
archive_name = arg;
|
||||
break;
|
||||
|
||||
case 'H': /* Header format name. */
|
||||
if (archive_format != arf_unknown)
|
||||
error (PAXEXIT_FAILURE, 0, _("Archive format multiply defined"));
|
||||
if (!strcasecmp (arg, "crc"))
|
||||
archive_format = arf_crcascii;
|
||||
else if (!strcasecmp (arg, "newc"))
|
||||
archive_format = arf_newascii;
|
||||
else if (!strcasecmp (arg, "odc"))
|
||||
archive_format = arf_oldascii;
|
||||
else if (!strcasecmp (arg, "bin"))
|
||||
archive_format = arf_binary;
|
||||
else if (!strcasecmp (arg, "ustar"))
|
||||
archive_format = arf_ustar;
|
||||
else if (!strcasecmp (arg, "tar"))
|
||||
archive_format = arf_tar;
|
||||
else if (!strcasecmp (arg, "hpodc"))
|
||||
archive_format = arf_hpoldascii;
|
||||
else if (!strcasecmp (arg, "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)"), arg);
|
||||
break;
|
||||
|
||||
case 'i': /* Copy-in mode. */
|
||||
if (copy_function != 0)
|
||||
error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
|
||||
copy_function = process_copy_in;
|
||||
break;
|
||||
|
||||
case 'I': /* Input archive file name. */
|
||||
input_archive_name = arg;
|
||||
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 (arg);
|
||||
break;
|
||||
|
||||
case 'n': /* Long list owner and group as numbers. */
|
||||
numeric_uid = true;
|
||||
break;
|
||||
|
||||
case NO_ABSOLUTE_FILENAMES_OPTION: /* --no-absolute-filenames */
|
||||
abs_paths_flag = false;
|
||||
break;
|
||||
|
||||
case ABSOLUTE_FILENAMES_OPTION: /* --absolute-filenames */
|
||||
abs_paths_flag = true;
|
||||
break;
|
||||
|
||||
case NO_PRESERVE_OWNER_OPTION: /* --no-preserve-owner */
|
||||
if (set_owner_flag || set_group_flag)
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("--no-preserve-owner cannot be used with --owner"));
|
||||
no_chown_flag = true;
|
||||
break;
|
||||
|
||||
case 'o': /* Copy-out mode. */
|
||||
if (copy_function != 0)
|
||||
error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
|
||||
copy_function = process_copy_out;
|
||||
break;
|
||||
|
||||
case 'O': /* Output archive file name. */
|
||||
output_archive_name = arg;
|
||||
break;
|
||||
|
||||
case ONLY_VERIFY_CRC_OPTION:
|
||||
only_verify_crc_flag = true;
|
||||
break;
|
||||
|
||||
case 'p': /* Copy-pass mode. */
|
||||
if (copy_function != 0)
|
||||
error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
|
||||
copy_function = process_copy_pass;
|
||||
break;
|
||||
|
||||
case RSH_COMMAND_OPTION:
|
||||
rsh_command_option = arg;
|
||||
break;
|
||||
|
||||
case 'r': /* Interactively rename. */
|
||||
rename_flag = true;
|
||||
break;
|
||||
|
||||
case RENAME_BATCH_FILE_OPTION:
|
||||
rename_batch_file = arg;
|
||||
break;
|
||||
|
||||
case QUIET_OPTION:
|
||||
quiet_flag = true;
|
||||
break;
|
||||
|
||||
case 'R': /* Set the owner. */
|
||||
if (no_chown_flag)
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("--owner cannot be used with --no-preserve-owner"));
|
||||
else
|
||||
{
|
||||
char *e, *u, *g;
|
||||
|
||||
e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
|
||||
if (e)
|
||||
error (PAXEXIT_FAILURE, 0, "%s: %s", arg, e);
|
||||
if (u)
|
||||
{
|
||||
free (u);
|
||||
set_owner_flag = true;
|
||||
}
|
||||
if (g)
|
||||
{
|
||||
free (g);
|
||||
set_group_flag = true;
|
||||
}
|
||||
}
|
||||
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 'W':
|
||||
if (warn_control (arg))
|
||||
argp_error (state, _("Invalid value for --warning option: %s"), arg);
|
||||
break;
|
||||
|
||||
case SPARSE_OPTION:
|
||||
sparse_flag = true;
|
||||
break;
|
||||
|
||||
case FORCE_LOCAL_OPTION:
|
||||
force_local_option = 1;
|
||||
break;
|
||||
|
||||
#ifdef DEBUG_CPIO
|
||||
case DEBUG_OPTION:
|
||||
debug_flag = true;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TO_STDOUT_OPTION:
|
||||
to_stdout_option = true;
|
||||
break;
|
||||
|
||||
case HANG_OPTION:
|
||||
_argp_hang = atoi (arg ? arg : "3600");
|
||||
while (_argp_hang-- > 0)
|
||||
sleep (1);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
|
||||
break;
|
||||
|
||||
case USAGE_OPTION:
|
||||
argp_state_help (state, state->out_stream,
|
||||
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
|
||||
break;
|
||||
|
||||
case VERSION_OPTION:
|
||||
fprintf (state->out_stream, "%s\n", argp_program_version);
|
||||
exit (0);
|
||||
|
||||
case LICENSE_OPTION:
|
||||
license ();
|
||||
break;
|
||||
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct argp argp = {
|
||||
options,
|
||||
parse_opt,
|
||||
N_("[destination-directory]"),
|
||||
doc,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Process the arguments. Set all options and set up the copy pass
|
||||
directory or the copy in patterns. */
|
||||
|
||||
void
|
||||
process_args (int argc, char *argv[])
|
||||
{
|
||||
void (*copy_in) (); /* Work around for pcc bug. */
|
||||
void (*copy_out) ();
|
||||
int index;
|
||||
|
||||
if (argc < 2)
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
|
||||
program_name, program_name);
|
||||
|
||||
xstat = lstat;
|
||||
|
||||
if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP, &index, NULL))
|
||||
exit (1);
|
||||
|
||||
/* Do error checking and look at other args. */
|
||||
|
||||
if (copy_function == 0)
|
||||
{
|
||||
if (table_flag)
|
||||
copy_function = process_copy_in;
|
||||
else
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
|
||||
program_name, program_name);
|
||||
}
|
||||
|
||||
/* Work around for pcc bug. */
|
||||
copy_in = process_copy_in;
|
||||
copy_out = process_copy_out;
|
||||
|
||||
if (copy_function == copy_in)
|
||||
{
|
||||
archive_des = 0;
|
||||
CHECK_USAGE(link_flag, "--link", "--extract");
|
||||
CHECK_USAGE(reset_time_flag, "--reset", "--extract");
|
||||
CHECK_USAGE(xstat != lstat, "--dereference", "--extract");
|
||||
CHECK_USAGE(append_flag, "--append", "--extract");
|
||||
CHECK_USAGE(output_archive_name, "-O", "--extract");
|
||||
if (to_stdout_option)
|
||||
{
|
||||
CHECK_USAGE(create_dir_flag, "--make-directories", "--to-stdout");
|
||||
CHECK_USAGE(rename_flag, "--rename", "--to-stdout");
|
||||
CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--to-stdout");
|
||||
CHECK_USAGE(set_owner_flag||set_group_flag, "--owner", "--to-stdout");
|
||||
CHECK_USAGE(retain_time_flag, "--preserve-modification-time",
|
||||
"--to-stdout");
|
||||
}
|
||||
|
||||
if (archive_name && input_archive_name)
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("Both -I and -F are used in copy-in mode"));
|
||||
|
||||
if (archive_format == arf_crcascii)
|
||||
crc_i_flag = true;
|
||||
num_patterns = argc - index;
|
||||
save_patterns = &argv[index];
|
||||
if (input_archive_name)
|
||||
archive_name = input_archive_name;
|
||||
}
|
||||
else if (copy_function == copy_out)
|
||||
{
|
||||
if (index != argc)
|
||||
error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
|
||||
|
||||
archive_des = 1;
|
||||
CHECK_USAGE(create_dir_flag, "--make-directories", "--create");
|
||||
CHECK_USAGE(rename_flag, "--rename", "--create");
|
||||
CHECK_USAGE(table_flag, "--list", "--create");
|
||||
CHECK_USAGE(unconditional_flag, "--unconditional", "--create");
|
||||
CHECK_USAGE(link_flag, "--link", "--create");
|
||||
CHECK_USAGE(sparse_flag, "--sparse", "--create");
|
||||
CHECK_USAGE(retain_time_flag, "--preserve-modification-time",
|
||||
"--create");
|
||||
CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--create");
|
||||
CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--create");
|
||||
CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
|
||||
"--create");
|
||||
CHECK_USAGE(to_stdout_option, "--to-stdout", "--create");
|
||||
|
||||
if (append_flag && !(archive_name || output_archive_name))
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("--append is used but no archive file name is given (use -F or -O options)"));
|
||||
|
||||
CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--create");
|
||||
CHECK_USAGE(abs_paths_flag, "--absolute-pathnames", "--create");
|
||||
CHECK_USAGE(input_archive_name, "-I", "--create");
|
||||
if (archive_name && output_archive_name)
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("Both -O and -F are used in copy-out mode"));
|
||||
|
||||
if (archive_format == arf_unknown)
|
||||
archive_format = arf_binary;
|
||||
if (output_archive_name)
|
||||
archive_name = output_archive_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy pass. */
|
||||
if (index < argc - 1)
|
||||
error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
|
||||
else if (index > argc - 1)
|
||||
error (PAXEXIT_FAILURE, 0, _("Not enough arguments"));
|
||||
|
||||
if (archive_format != arf_unknown)
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("Archive format is not specified in copy-pass mode (use --format option)"));
|
||||
|
||||
CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--pass-through");
|
||||
CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
|
||||
"--pass-through");
|
||||
CHECK_USAGE(table_flag, "--list", "--pass-through");
|
||||
CHECK_USAGE(rename_flag, "--rename", "--pass-through");
|
||||
CHECK_USAGE(append_flag, "--append", "--pass-through");
|
||||
CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--pass-through");
|
||||
CHECK_USAGE(abs_paths_flag, "--absolute-pathnames",
|
||||
"--pass-through");
|
||||
CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through");
|
||||
|
||||
directory_name = argv[index];
|
||||
}
|
||||
|
||||
if (archive_name)
|
||||
{
|
||||
if (copy_function != copy_in && copy_function != copy_out)
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("-F can be used only with --create or --extract"));
|
||||
archive_des = open_archive (archive_name);
|
||||
if (archive_des < 0)
|
||||
error (PAXEXIT_FAILURE, errno, _("Cannot open %s"),
|
||||
quotearg_colon (archive_name));
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Initialize the input and output buffers to their proper size and
|
||||
initialize all variables associated with the input and output
|
||||
buffers. */
|
||||
|
||||
void
|
||||
initialize_buffers ()
|
||||
{
|
||||
int in_buf_size, out_buf_size;
|
||||
|
||||
if (copy_function == process_copy_in)
|
||||
{
|
||||
/* Make sure the input buffer can always hold 2 blocks and that it
|
||||
is big enough to hold 1 tar record (512 bytes) even if it
|
||||
is not aligned on a block boundary. The extra buffer space
|
||||
is needed by process_copyin and peek_in_buf to automatically
|
||||
figure out what kind of archive it is reading. */
|
||||
if (io_block_size >= 512)
|
||||
in_buf_size = 2 * io_block_size;
|
||||
else
|
||||
in_buf_size = 1024;
|
||||
out_buf_size = DISK_IO_BLOCK_SIZE;
|
||||
}
|
||||
else if (copy_function == process_copy_out)
|
||||
{
|
||||
in_buf_size = DISK_IO_BLOCK_SIZE;
|
||||
out_buf_size = io_block_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_buf_size = DISK_IO_BLOCK_SIZE;
|
||||
out_buf_size = DISK_IO_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
input_buffer = (char *) xmalloc (in_buf_size);
|
||||
in_buff = input_buffer;
|
||||
input_buffer_size = in_buf_size;
|
||||
input_size = 0;
|
||||
input_bytes = 0;
|
||||
|
||||
output_buffer = (char *) xmalloc (out_buf_size);
|
||||
out_buff = output_buffer;
|
||||
output_size = 0;
|
||||
output_bytes = 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
textdomain (PACKAGE);
|
||||
|
||||
program_name = argv[0];
|
||||
|
||||
process_args (argc, argv);
|
||||
umask (0);
|
||||
|
||||
initialize_buffers ();
|
||||
|
||||
(*copy_function) ();
|
||||
|
||||
if (archive_des >= 0 && rmtclose (archive_des) == -1)
|
||||
error (1, errno, _("error closing archive"));
|
||||
|
||||
exit (0);
|
||||
}
|
@ -1,267 +0,0 @@
|
||||
/* makepath.c -- Ensure that a directory path exists.
|
||||
Copyright (C) 1990, 2006 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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 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. */
|
||||
|
||||
#include <system.h>
|
||||
#include <paxlib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* 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 (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 = strchr (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
|
||||
)
|
||||
{
|
||||
chown_error_details (dirpath, owner, group);
|
||||
retval = 1;
|
||||
}
|
||||
if (re_protect)
|
||||
{
|
||||
struct ptr_list *new = (struct ptr_list *)
|
||||
alloca (sizeof (struct ptr_list));
|
||||
new->dirname_end = slash;
|
||||
new->next = leading_dirs;
|
||||
leading_dirs = new;
|
||||
}
|
||||
#ifdef HPUX_CDF
|
||||
if (iscdf)
|
||||
{
|
||||
/* If this is a CDF, "hide" the directory by setting
|
||||
its hidden/setuid bit. Also add the `+' back to
|
||||
its name (since once it's "hidden" we must refer
|
||||
to as `name+' instead of `name'). */
|
||||
chmod (dirpath, 04700);
|
||||
*(slash - 1) = '+';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (!S_ISDIR (stats.st_mode))
|
||||
{
|
||||
error (0, 0, _("`%s' exists but is not a directory"), dirpath);
|
||||
umask (oldmask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*slash++ = '/';
|
||||
|
||||
/* Avoid unnecessary calls to `stat' when given
|
||||
pathnames containing multiple adjacent slashes. */
|
||||
while (*slash == '/')
|
||||
slash++;
|
||||
}
|
||||
|
||||
/* We're done making leading directories.
|
||||
Make the final component of the path. */
|
||||
|
||||
if (mkdir (dirpath, mode))
|
||||
{
|
||||
/* In some cases, if the final component in dirpath was `.' then we
|
||||
just got an EEXIST error from that last mkdir(). If that's
|
||||
the case, ignore it. */
|
||||
if ( (errno != EEXIST) ||
|
||||
(stat (dirpath, &stats) != 0) ||
|
||||
(!S_ISDIR (stats.st_mode) ) )
|
||||
{
|
||||
error (0, errno, _("cannot make directory `%s'"), dirpath);
|
||||
umask (oldmask);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (verbose_fmt_string != NULL)
|
||||
error (0, 0, verbose_fmt_string, dirpath);
|
||||
|
||||
if (owner != (uid_t) -1 && group != (gid_t) -1)
|
||||
{
|
||||
if (chown (dirpath, owner, group)
|
||||
#ifdef AFS
|
||||
&& errno != EPERM
|
||||
#endif
|
||||
)
|
||||
{
|
||||
chown_error_details (dirpath, owner, group);
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
/* chown may have turned off some permission bits we wanted. */
|
||||
if ((mode & 07000) != 0 && chmod (dirpath, mode))
|
||||
{
|
||||
chmod_error_details (dirpath, mode);
|
||||
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))
|
||||
{
|
||||
chmod_error_details (dirpath, parent_mode);
|
||||
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
|
||||
)
|
||||
{
|
||||
chown_error_details (dirpath, owner, group);
|
||||
retval = 1;
|
||||
}
|
||||
if (chmod (dirpath, mode))
|
||||
{
|
||||
chmod_error_details (dirpath, mode);
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
|
||||
umask (oldmask);
|
||||
return retval;
|
||||
}
|
@ -1 +0,0 @@
|
||||
#define SAFE_STAT(path,pbuf) stat(path,pbuf)
|
@ -1,494 +0,0 @@
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/* tar.c - read in write tar headers for cpio
|
||||
Copyright (C) 1992, 2001, 2004, 2006 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., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "filetypes.h"
|
||||
#include "cpiohdr.h"
|
||||
#include "dstring.h"
|
||||
#include "extern.h"
|
||||
#include <rmt.h>
|
||||
#include "tarhdr.h"
|
||||
|
||||
/* Stash the tar linkname in static storage. */
|
||||
|
||||
static char *
|
||||
stash_tar_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;
|
||||
}
|
||||
|
||||
/* Try to split a long file name into prefix and suffix parts separated
|
||||
by a slash. Return the length of the prefix (not counting the slash). */
|
||||
|
||||
static size_t
|
||||
split_long_name (const char *name, size_t length)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (length > TARPREFIXSIZE)
|
||||
length = TARPREFIXSIZE+2;
|
||||
for (i = length - 1; i > 0; i--)
|
||||
if (name[i] == '/')
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Stash the tar filename and optional prefix in static storage. */
|
||||
|
||||
static char *
|
||||
stash_tar_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 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 (register long value, register int digits, register char *where)
|
||||
{
|
||||
--digits; /* Leave the trailing NUL slot alone. */
|
||||
|
||||
/* 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 zeroes, if necessary. */
|
||||
while (digits > 0)
|
||||
where[--digits] = '0';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Compute and return a checksum for TAR_HDR,
|
||||
counting the checksum bytes as if they were spaces. */
|
||||
|
||||
unsigned int
|
||||
tar_checksum (struct tar_header *tar_hdr)
|
||||
{
|
||||
unsigned int 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 (struct cpio_file_stat *file_hdr, int out_des)
|
||||
{
|
||||
int name_len;
|
||||
union tar_record tar_rec;
|
||||
struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
|
||||
|
||||
memset (&tar_rec, 0, sizeof tar_rec);
|
||||
|
||||
/* 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'. */
|
||||
int prefix_len = split_long_name (file_hdr->c_name, name_len);
|
||||
|
||||
strncpy (tar_hdr->prefix, file_hdr->c_name, prefix_len);
|
||||
strncpy (tar_hdr->name, file_hdr->c_name + prefix_len + 1,
|
||||
name_len - prefix_len - 1);
|
||||
}
|
||||
|
||||
/* Ustar standard (POSIX.1-1988) requires the mode to contain only 3 octal
|
||||
digits */
|
||||
to_oct (file_hdr->c_mode & MODE_ALL, 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;
|
||||
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 */
|
||||
}
|
||||
|
||||
if (archive_format == arf_ustar)
|
||||
{
|
||||
char *name;
|
||||
|
||||
strncpy (tar_hdr->magic, TMAGIC, TMAGLEN);
|
||||
strncpy (tar_hdr->magic + TMAGLEN, TVERSION, TVERSLEN);
|
||||
|
||||
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);
|
||||
|
||||
to_oct (file_hdr->c_rdev_maj, 8, tar_hdr->devmajor);
|
||||
to_oct (file_hdr->c_rdev_min, 8, tar_hdr->devminor);
|
||||
}
|
||||
|
||||
to_oct (tar_checksum (tar_hdr), 8, tar_hdr->chksum);
|
||||
|
||||
tape_buffered_write ((char *) &tar_rec, out_des, TARRECORDSIZE);
|
||||
}
|
||||
|
||||
/* Return nonzero iff all the bytes in BLOCK are NUL.
|
||||
SIZE is the number of bytes to check in BLOCK; it must be a
|
||||
multiple of sizeof (long). */
|
||||
|
||||
int
|
||||
null_block (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 (struct cpio_file_stat *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;
|
||||
uid_t *uidp;
|
||||
gid_t *gidp;
|
||||
|
||||
tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
|
||||
|
||||
/* Check for a block of 0's. */
|
||||
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
|
||||
{
|
||||
#if 0
|
||||
/* Found one block of 512 0's. If the next block is also all 0's
|
||||
then this is the end of the archive. If not, assume the
|
||||
previous block was all corruption and continue reading
|
||||
the archive. */
|
||||
/* Commented out because GNU tar sometimes creates archives with
|
||||
only one block of 0's at the end. This happened for the
|
||||
cpio 2.0 distribution! */
|
||||
tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
|
||||
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
|
||||
#endif
|
||||
{
|
||||
file_hdr->c_name = CPIO_TRAILER_NAME;
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
bytes_skipped = TARRECORDSIZE;
|
||||
#endif
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
file_hdr->c_chksum = FROM_OCTAL (tar_hdr->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;
|
||||
}
|
||||
memmove (&tar_rec, ((char *) &tar_rec) + 1, TARRECORDSIZE - 1);
|
||||
tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
|
||||
++bytes_skipped;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (archive_format != arf_ustar)
|
||||
file_hdr->c_name = stash_tar_filename (NULL, tar_hdr->name);
|
||||
else
|
||||
file_hdr->c_name = stash_tar_filename (tar_hdr->prefix, tar_hdr->name);
|
||||
file_hdr->c_nlink = 1;
|
||||
file_hdr->c_mode = FROM_OCTAL (tar_hdr->mode);
|
||||
file_hdr->c_mode = file_hdr->c_mode & 07777;
|
||||
/* Debian hack: This version of cpio uses the -n flag also to extract
|
||||
tar archives using the numeric UID/GID instead of the user/group
|
||||
names in /etc/passwd and /etc/groups. (98/10/15) -BEM */
|
||||
if (archive_format == arf_ustar && !numeric_uid
|
||||
&& (uidp = getuidbyname (tar_hdr->uname)))
|
||||
file_hdr->c_uid = *uidp;
|
||||
else
|
||||
file_hdr->c_uid = FROM_OCTAL (tar_hdr->uid);
|
||||
|
||||
if (archive_format == arf_ustar && !numeric_uid
|
||||
&& (gidp = getgidbyname (tar_hdr->gname)))
|
||||
file_hdr->c_gid = *gidp;
|
||||
else
|
||||
file_hdr->c_gid = FROM_OCTAL (tar_hdr->gid);
|
||||
file_hdr->c_filesize = FROM_OCTAL (tar_hdr->size);
|
||||
file_hdr->c_mtime = FROM_OCTAL (tar_hdr->mtime);
|
||||
file_hdr->c_rdev_maj = FROM_OCTAL (tar_hdr->devmajor);
|
||||
file_hdr->c_rdev_min = FROM_OCTAL (tar_hdr->devminor);
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
case 'x': case 'g':
|
||||
/* Ignore pax 'x' and 'g' extension entries. */
|
||||
/* Skip body of this entry. */
|
||||
while (file_hdr->c_filesize > 0) {
|
||||
tape_buffered_read(((char *) &tar_rec), in_des, TARRECORDSIZE);
|
||||
if (file_hdr->c_filesize > TARRECORDSIZE)
|
||||
file_hdr->c_filesize -= TARRECORDSIZE;
|
||||
else
|
||||
file_hdr->c_filesize = 0;
|
||||
}
|
||||
/* Read next header and return that instead. */
|
||||
read_in_tar_header(file_hdr, in_des);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (bytes_skipped > 0)
|
||||
warn_junk_bytes (bytes_skipped);
|
||||
}
|
||||
|
||||
/* 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 (char *buf)
|
||||
{
|
||||
struct tar_header *tar_hdr = (struct tar_header *) buf;
|
||||
unsigned long chksum;
|
||||
|
||||
chksum = FROM_OCTAL (tar_hdr->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 (char *name)
|
||||
{
|
||||
int whole_name_len;
|
||||
int prefix_name_len;
|
||||
|
||||
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. */
|
||||
prefix_name_len = split_long_name (name, whole_name_len);
|
||||
|
||||
/* 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 == 0
|
||||
|| whole_name_len - prefix_name_len - 1 > TARNAMESIZE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
/* Extended tar format from POSIX.1.
|
||||
Copyright (C) 1992 Free Software Foundation, Inc.
|
||||
Written by David J. MacKenzie.
|
||||
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General
|
||||
Public License along with this library; see the file COPYING.LIB.
|
||||
If not, write to the Free Software Foundation, Inc., 51 Franklin
|
||||
Street, Fifth Floor, Boston, MA 02110-1301 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 */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user