This commit was generated by cvs2svn to compensate for changes in r150765,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
tjr 2005-10-01 04:37:08 +00:00
commit c41ca4418d
84 changed files with 19558 additions and 10 deletions

705
contrib/cpio/ABOUT-NLS Normal file
View File

@ -0,0 +1,705 @@
Notes on the Free Translation Project
*************************************
Free software is going international! The Free Translation Project is
a way to get maintainers of free software, translators, and users all
together, so that will gradually become able to speak many languages.
A few packages already provide translations for their messages.
If you found this `ABOUT-NLS' file inside a distribution, you may
assume that the distributed package does use GNU `gettext' internally,
itself available at your nearest GNU archive site. But you do _not_
need to install GNU `gettext' prior to configuring, installing or using
this package with messages translated.
Installers will find here some useful hints. These notes also
explain how users should proceed for getting the programs to use the
available translations. They tell how people wanting to contribute and
work at translations should contact the appropriate team.
When reporting bugs in the `intl/' directory or bugs which may be
related to internationalization, you should tell about the version of
`gettext' which is used. The information can be found in the
`intl/VERSION' file, in internationalized packages.
Quick configuration advice
==========================
If you want to exploit the full power of internationalization, you
should configure it using
./configure --with-included-gettext
to force usage of internationalizing routines provided within this
package, despite the existence of internationalizing capabilities in the
operating system where this package is being installed. So far, only
the `gettext' implementation in the GNU C library version 2 provides as
many features (such as locale alias, message inheritance, automatic
charset conversion or plural form handling) as the implementation here.
It is also not possible to offer this additional functionality on top
of a `catgets' implementation. Future versions of GNU `gettext' will
very likely convey even more functionality. So it might be a good idea
to change to GNU `gettext' as soon as possible.
So you need _not_ provide this option if you are using GNU libc 2 or
you have installed a recent copy of the GNU gettext package with the
included `libintl'.
INSTALL Matters
===============
Some packages are "localizable" when properly installed; the programs
they contain can be made to speak your own native language. Most such
packages use GNU `gettext'. Other packages have their own ways to
internationalization, predating GNU `gettext'.
By default, this package will be installed to allow translation of
messages. It will automatically detect whether the system already
provides the GNU `gettext' functions. If not, the GNU `gettext' own
library will be used. This library is wholly contained within this
package, usually in the `intl/' subdirectory, so prior installation of
the GNU `gettext' package is _not_ required. Installers may use
special options at configuration time for changing the default
behaviour. The commands:
./configure --with-included-gettext
./configure --disable-nls
will respectively bypass any pre-existing `gettext' to use the
internationalizing routines provided within this package, or else,
_totally_ disable translation of messages.
When you already have GNU `gettext' installed on your system and run
configure without an option for your new package, `configure' will
probably detect the previously built and installed `libintl.a' file and
will decide to use this. This might be not what is desirable. You
should use the more recent version of the GNU `gettext' library. I.e.
if the file `intl/VERSION' shows that the library which comes with this
package is more recent, you should use
./configure --with-included-gettext
to prevent auto-detection.
The configuration process will not test for the `catgets' function
and therefore it will not be used. The reason is that even an
emulation of `gettext' on top of `catgets' could not provide all the
extensions of the GNU `gettext' library.
Internationalized packages have usually many `po/LL.po' files, where
LL gives an ISO 639 two-letter code identifying the language. Unless
translations have been forbidden at `configure' time by using the
`--disable-nls' switch, all available translations are installed
together with the package. However, the environment variable `LINGUAS'
may be set, prior to configuration, to limit the installed set.
`LINGUAS' should then contain a space separated list of two-letter
codes, stating which languages are allowed.
Using This Package
==================
As a user, if your language has been installed for this package, you
only have to set the `LANG' environment variable to the appropriate
`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code,
and `CC' is an ISO 3166 two-letter country code. For example, let's
suppose that you speak German and live in Germany. At the shell
prompt, merely execute `setenv LANG de_DE' (in `csh'),
`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').
This can be done from your `.login' or `.profile' file, once and for
all.
You might think that the country code specification is redundant.
But in fact, some languages have dialects in different countries. For
example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The
country code serves to distinguish the dialects.
The locale naming convention of `LL_CC', with `LL' denoting the
language and `CC' denoting the country, is the one use on systems based
on GNU libc. On other systems, some variations of this scheme are
used, such as `LL' or `LL_CC.ENCODING'. You can get the list of
locales supported by your system for your country by running the command
`locale -a | grep '^LL''.
Not all programs have translations for all languages. By default, an
English message is shown in place of a nonexistent translation. If you
understand other languages, you can set up a priority list of languages.
This is done through a different environment variable, called
`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG'
for the purpose of message handling, but you still need to have `LANG'
set to the primary language; this is required by other parts of the
system libraries. For example, some Swedish users who would rather
read translations in German than English for when Swedish is not
available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.
In the `LANGUAGE' environment variable, but not in the `LANG'
environment variable, `LL_CC' combinations can be abbreviated as `LL'
to denote the language's main dialect. For example, `de' is equivalent
to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'
(Portuguese as spoken in Portugal) in this context.
Translating Teams
=================
For the Free Translation Project to be a success, we need interested
people who like their own language and write it well, and who are also
able to synergize with other translators speaking the same language.
Each translation team has its own mailing list. The up-to-date list of
teams can be found at the Free Translation Project's homepage,
`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams"
area.
If you'd like to volunteer to _work_ at translating messages, you
should become a member of the translating team for your own language.
The subscribing address is _not_ the same as the list itself, it has
`-request' appended. For example, speakers of Swedish can send a
message to `sv-request@li.org', having this message body:
subscribe
Keep in mind that team members are expected to participate
_actively_ in translations, or at solving translational difficulties,
rather than merely lurking around. If your team does not exist yet and
you want to start one, or if you are unsure about what to do or how to
get started, please write to `translation@iro.umontreal.ca' to reach the
coordinator for all translator teams.
The English team is special. It works at improving and uniformizing
the terminology in use. Proven linguistic skill are praised more than
programming skill, here.
Available Packages
==================
Languages are not equally supported in all packages. The following
matrix shows the current state of internationalization, as of November
2003. The matrix shows, in regard of each package, for which languages
PO files have been submitted to translation coordination, with a
translation percentage of at least 50%.
Ready PO files am az be bg ca cs da de el en en_GB eo es
+-------------------------------------------+
a2ps | [] [] [] [] |
aegis | () |
ant-phone | () |
anubis | |
ap-utils | |
bash | [] [] [] [] |
batchelor | |
bfd | [] [] |
binutils | [] [] |
bison | [] [] [] |
bluez-pin | [] [] |
clisp | [] [] [] |
clisp | |
coreutils | [] [] [] [] |
cpio | [] [] [] |
darkstat | [] () [] |
diffutils | [] [] [] [] [] [] [] |
e2fsprogs | [] [] |
enscript | [] [] [] [] |
error | [] [] [] [] [] |
fetchmail | [] () [] [] [] [] |
fileutils | [] [] [] |
findutils | [] [] [] [] [] [] [] |
flex | [] [] [] [] |
fslint | |
gas | [] |
gawk | [] [] [] [] |
gbiff | [] |
gcal | [] |
gcc | [] [] |
gettext | [] [] [] [] [] |
gettext-examples | [] [] [] |
gettext-runtime | [] [] [] [] [] |
gettext-tools | [] [] [] |
gimp-print | [] [] [] [] [] |
gliv | |
glunarclock | [] [] [] |
gnubiff | [] |
gnucash | [] () [] [] |
gnucash-glossary | [] () [] |
gnupg | [] () [] [] [] [] |
gpe-aerial | [] |
gpe-beam | [] [] |
gpe-calendar | [] [] |
gpe-clock | [] [] |
gpe-conf | [] [] |
gpe-contacts | [] [] |
gpe-edit | [] |
gpe-go | [] |
gpe-login | [] [] |
gpe-ownerinfo | [] [] |
gpe-sketchbook | [] [] |
gpe-su | [] [] |
gpe-taskmanager | [] [] |
gpe-timesheet | [] |
gpe-today | [] [] |
gpe-todo | [] [] |
gphoto2 | [] [] [] [] |
gprof | [] [] [] |
gpsdrive | () () () |
gramadoir | [] |
grep | [] [] [] [] [] [] |
gretl | [] |
gtick | () |
hello | [] [] [] [] [] [] |
id-utils | [] [] |
indent | [] [] [] [] |
jpilot | [] [] [] |
jtag | |
jwhois | [] |
kbd | [] [] [] [] [] |
latrine | () |
ld | [] [] |
libc | [] [] [] [] [] [] |
libgpewidget | [] [] |
libiconv | [] [] [] [] [] |
lifelines | [] () |
lilypond | [] |
lingoteach | |
lingoteach_lessons | () () |
lynx | [] [] [] [] |
m4 | [] [] [] [] |
mailutils | [] [] |
make | [] [] [] |
man-db | [] () [] [] () |
minicom | [] [] [] |
mysecretdiary | [] [] [] |
nano | [] () [] [] [] |
nano_1_0 | [] () [] [] [] |
opcodes | [] |
parted | [] [] [] [] [] |
ptx | [] [] [] [] [] |
python | |
radius | |
recode | [] [] [] [] [] [] [] |
screem | |
scrollkeeper | [] [] [] [] [] [] |
sed | [] [] [] [] [] |
sh-utils | [] [] [] |
shared-mime-info | |
sharutils | [] [] [] [] [] [] |
sketch | [] () [] |
soundtracker | [] [] [] |
sp | [] |
tar | [] [] [] [] |
texinfo | [] [] [] |
textutils | [] [] [] [] |
tin | () () |
tuxpaint | [] [] [] [] [] [] [] |
util-linux | [] [] [] [] [] |
vorbis-tools | [] [] [] [] |
wastesedge | () |
wdiff | [] [] [] [] |
wget | [] [] [] [] [] [] |
xchat | [] [] [] [] |
xfree86_xkb_xml | [] |
xpad | [] |
+-------------------------------------------+
am az be bg ca cs da de el en en_GB eo es
0 1 8 3 37 37 54 73 15 1 5 12 62
et fa fi fr ga gl he hr hu id is it ja
+----------------------------------------+
a2ps | [] [] [] () |
aegis | |
ant-phone | |
anubis | [] |
ap-utils | [] |
bash | [] [] |
batchelor | [] |
bfd | [] |
binutils | [] [] |
bison | [] [] [] [] |
bluez-pin | [] [] [] [] [] |
clisp | [] |
clisp | |
coreutils | [] [] [] [] [] [] |
cpio | [] [] [] |
darkstat | () [] [] [] |
diffutils | [] [] [] [] [] [] [] |
e2fsprogs | |
enscript | [] [] |
error | [] [] [] [] |
fetchmail | [] |
fileutils | [] [] [] [] [] [] |
findutils | [] [] [] [] [] [] [] [] [] [] |
flex | [] [] |
fslint | |
gas | [] |
gawk | [] [] [] |
gbiff | |
gcal | [] |
gcc | [] |
gettext | [] [] |
gettext-examples | [] [] |
gettext-runtime | [] [] [] [] |
gettext-tools | [] [] |
gimp-print | [] [] |
gliv | () |
glunarclock | [] [] [] [] [] |
gnubiff | |
gnucash | () [] |
gnucash-glossary | [] |
gnupg | [] [] [] [] [] [] [] |
gpe-aerial | [] |
gpe-beam | [] |
gpe-calendar | [] [] [] |
gpe-clock | [] |
gpe-conf | [] |
gpe-contacts | [] [] |
gpe-edit | [] [] |
gpe-go | [] |
gpe-login | [] [] |
gpe-ownerinfo | [] [] [] |
gpe-sketchbook | [] |
gpe-su | [] |
gpe-taskmanager | [] |
gpe-timesheet | [] [] [] |
gpe-today | [] [] |
gpe-todo | [] [] |
gphoto2 | [] [] [] |
gprof | [] [] |
gpsdrive | () [] () () |
gramadoir | [] |
grep | [] [] [] [] [] [] [] [] [] [] [] |
gretl | [] |
gtick | [] [] |
hello | [] [] [] [] [] [] [] [] [] [] [] [] |
id-utils | [] [] [] [] |
indent | [] [] [] [] [] [] [] [] [] |
jpilot | [] () |
jtag | |
jwhois | [] [] [] [] |
kbd | [] |
latrine | |
ld | [] |
libc | [] [] [] [] [] |
libgpewidget | [] [] [] [] |
libiconv | [] [] [] [] [] [] [] [] [] |
lifelines | () |
lilypond | [] |
lingoteach | [] [] |
lingoteach_lessons | |
lynx | [] [] [] [] |
m4 | [] [] [] [] |
mailutils | |
make | [] [] [] [] [] |
man-db | () () |
minicom | [] [] [] [] |
mysecretdiary | [] [] |
nano | [] [] [] [] |
nano_1_0 | [] [] [] [] |
opcodes | [] |
parted | [] [] [] |
ptx | [] [] [] [] [] [] [] |
python | |
radius | |
recode | [] [] [] [] [] [] |
screem | |
scrollkeeper | [] |
sed | [] [] [] [] [] [] [] [] [] |
sh-utils | [] [] [] [] [] [] [] |
shared-mime-info | [] |
sharutils | [] [] [] [] [] |
sketch | [] |
soundtracker | [] [] [] [] |
sp | [] () |
tar | [] [] [] [] [] [] [] [] [] |
texinfo | [] [] [] [] |
textutils | [] [] [] [] [] |
tin | [] () |
tuxpaint | [] [] [] [] [] [] [] [] |
util-linux | [] [] [] [] () [] |
vorbis-tools | [] |
wastesedge | () |
wdiff | [] [] [] [] [] [] |
wget | [] [] [] [] [] [] [] |
xchat | [] [] [] |
xfree86_xkb_xml | |
xpad | [] |
+----------------------------------------+
et fa fi fr ga gl he hr hu id is it ja
21 1 24 84 24 24 8 10 38 31 1 22 33
ko lg lt lv ms nb nl nn no pl pt pt_BR ro
+-------------------------------------------+
a2ps | () [] [] () () [] [] |
aegis | () () |
ant-phone | [] [] |
anubis | [] [] [] [] [] |
ap-utils | [] () [] |
bash | [] [] |
batchelor | [] |
bfd | [] |
binutils | |
bison | [] [] [] [] |
bluez-pin | [] [] [] |
clisp | [] |
clisp | |
coreutils | [] |
cpio | [] [] [] [] [] |
darkstat | [] [] [] [] |
diffutils | [] [] [] [] |
e2fsprogs | [] |
enscript | [] [] [] |
error | [] [] [] |
fetchmail | [] [] () |
fileutils | [] |
findutils | [] [] [] [] [] |
flex | [] [] [] [] |
fslint | [] [] |
gas | |
gawk | [] [] [] |
gbiff | [] [] |
gcal | |
gcc | |
gettext | [] [] [] |
gettext-examples | [] [] |
gettext-runtime | [] [] [] |
gettext-tools | [] [] [] |
gimp-print | [] |
gliv | [] [] [] |
glunarclock | [] [] [] |
gnubiff | |
gnucash | [] [] () |
gnucash-glossary | [] [] |
gnupg | [] |
gpe-aerial | [] [] [] |
gpe-beam | [] [] [] |
gpe-calendar | [] [] [] |
gpe-clock | [] [] [] |
gpe-conf | [] [] [] |
gpe-contacts | [] [] [] |
gpe-edit | [] [] [] |
gpe-go | [] [] |
gpe-login | [] [] [] |
gpe-ownerinfo | [] [] [] |
gpe-sketchbook | [] [] [] |
gpe-su | [] [] [] |
gpe-taskmanager | [] [] [] |
gpe-timesheet | [] [] [] |
gpe-today | [] [] [] |
gpe-todo | [] [] [] |
gphoto2 | [] |
gprof | [] [] |
gpsdrive | () () () [] |
gramadoir | [] |
grep | [] [] [] [] |
gretl | |
gtick | [] [] |
hello | [] [] [] [] [] [] [] [] [] [] |
id-utils | [] [] [] |
indent | [] [] [] |
jpilot | () () |
jtag | |
jwhois | [] [] [] [] |
kbd | [] [] [] |
latrine | [] |
ld | |
libc | [] [] [] [] [] |
libgpewidget | [] [] [] |
libiconv | [] [] [] [] |
lifelines | |
lilypond | |
lingoteach | |
lingoteach_lessons | |
lynx | [] [] |
m4 | [] [] [] [] |
mailutils | [] |
make | [] [] [] [] |
man-db | [] |
minicom | [] [] [] |
mysecretdiary | [] [] [] |
nano | [] [] [] [] |
nano_1_0 | [] [] [] [] [] |
opcodes | [] [] |
parted | [] [] [] [] |
ptx | [] [] [] [] [] [] [] |
python | |
radius | [] |
recode | [] [] [] |
screem | |
scrollkeeper | [] [] [] [] |
sed | [] [] [] |
sh-utils | [] |
shared-mime-info | [] |
sharutils | [] |
sketch | [] [] |
soundtracker | |
sp | |
tar | [] [] [] [] [] [] |
texinfo | [] [] [] |
textutils | [] [] |
tin | |
tuxpaint | [] [] [] [] [] [] [] [] [] |
util-linux | [] [] |
vorbis-tools | [] [] |
wastesedge | |
wdiff | [] [] [] [] |
wget | [] [] |
xchat | [] [] |
xfree86_xkb_xml | [] |
xpad | [] [] |
+-------------------------------------------+
ko lg lt lv ms nb nl nn no pl pt pt_BR ro
11 0 1 2 12 10 60 4 4 38 23 34 74
ru sk sl sr sv ta tr uk vi wa zh_CN zh_TW
+-------------------------------------------+
a2ps | [] [] [] [] [] | 16
aegis | () | 0
ant-phone | | 2
anubis | [] [] [] | 9
ap-utils | () | 3
bash | [] | 9
batchelor | | 2
bfd | [] [] | 6
binutils | [] [] [] | 7
bison | [] [] [] | 14
bluez-pin | [] [] [] | 13
clisp | | 5
clisp | | 0
coreutils | [] [] [] [] [] | 16
cpio | [] [] [] | 14
darkstat | [] [] [] () () | 12
diffutils | [] [] [] [] | 22
e2fsprogs | [] [] | 5
enscript | [] [] [] | 12
error | [] [] [] | 15
fetchmail | [] [] [] | 11
fileutils | [] [] [] [] [] [] | 16
findutils | [] [] [] [] [] [] [] | 29
flex | [] [] [] | 13
fslint | | 2
gas | [] | 3
gawk | [] [] | 12
gbiff | | 3
gcal | [] [] | 4
gcc | [] | 4
gettext | [] [] [] [] [] [] | 16
gettext-examples | [] [] | 9
gettext-runtime | [] [] [] [] [] [] [] [] [] | 21
gettext-tools | [] [] [] [] [] [] | 14
gimp-print | [] [] | 10
gliv | | 3
glunarclock | [] [] [] [] | 15
gnubiff | | 1
gnucash | [] [] [] | 9
gnucash-glossary | [] [] [] | 8
gnupg | [] [] [] [] | 17
gpe-aerial | [] [] | 7
gpe-beam | [] [] | 8
gpe-calendar | [] [] [] [] [] | 13
gpe-clock | [] [] [] | 9
gpe-conf | [] [] [] | 9
gpe-contacts | [] [] [] [] | 11
gpe-edit | [] [] [] [] [] | 11
gpe-go | [] | 5
gpe-login | [] [] [] [] [] | 12
gpe-ownerinfo | [] [] [] [] | 12
gpe-sketchbook | [] [] [] | 9
gpe-su | [] [] [] | 9
gpe-taskmanager | [] [] [] | 9
gpe-timesheet | [] [] [] [] | 11
gpe-today | [] [] [] [] [] | 12
gpe-todo | [] [] [] [] [] | 12
gphoto2 | [] [] [] | 11
gprof | [] [] | 9
gpsdrive | [] [] | 4
gramadoir | | 3
grep | [] [] [] [] [] | 26
gretl | | 2
gtick | [] | 5
hello | [] [] [] [] [] | 33
id-utils | [] [] [] | 12
indent | [] [] [] [] [] | 21
jpilot | [] [] [] [] [] | 9
jtag | [] | 1
jwhois | () () [] [] | 11
kbd | [] [] | 11
latrine | | 1
ld | [] [] | 5
libc | [] [] [] [] | 20
libgpewidget | [] [] [] | 12
libiconv | [] [] [] [] [] [] [] [] [] | 27
lifelines | [] | 2
lilypond | [] | 3
lingoteach | | 2
lingoteach_lessons | () | 0
lynx | [] [] [] [] | 14
m4 | [] [] [] | 15
mailutils | [] | 4
make | [] [] [] [] | 16
man-db | [] | 5
minicom | [] | 11
mysecretdiary | [] [] | 10
nano | [] [] [] [] [] | 17
nano_1_0 | [] [] [] [] | 17
opcodes | [] [] | 6
parted | [] [] [] | 15
ptx | [] [] [] | 22
python | | 0
radius | [] | 2
recode | [] [] [] [] | 20
screem | [] [] | 2
scrollkeeper | [] [] [] [] | 15
sed | [] [] [] [] [] [] | 23
sh-utils | [] [] [] | 14
shared-mime-info | [] [] | 4
sharutils | [] [] [] [] [] | 17
sketch | [] | 6
soundtracker | [] [] | 9
sp | [] | 3
tar | [] [] [] [] [] | 24
texinfo | [] [] [] [] | 14
textutils | [] [] [] [] [] | 16
tin | | 1
tuxpaint | [] [] [] [] [] | 29
util-linux | [] [] [] | 15
vorbis-tools | [] | 8
wastesedge | | 0
wdiff | [] [] [] [] | 18
wget | [] [] [] [] [] [] [] [] | 23
xchat | [] [] [] [] [] | 14
xfree86_xkb_xml | [] [] [] [] | 6
xpad | | 4
+-------------------------------------------+
51 teams ru sk sl sr sv ta tr uk vi wa zh_CN zh_TW
117 domains 58 41 16 16 78 0 53 12 1 10 21 22 1230
Some counters in the preceding matrix are higher than the number of
visible blocks let us expect. This is because a few extra PO files are
used for implementing regional variants of languages, or language
dialects.
For a PO file in the matrix above to be effective, the package to
which it applies should also have been internationalized and
distributed as such by its maintainer. There might be an observable
lag between the mere existence a PO file and its wide availability in a
distribution.
If November 2003 seems to be old, you may fetch a more recent copy
of this `ABOUT-NLS' file on most GNU archive sites. The most
up-to-date matrix with full percentage details can be found at
`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'.
Using `gettext' in new packages
===============================
If you are writing a freely available program and want to
internationalize it you are welcome to use GNU `gettext' in your
package. Of course you have to respect the GNU Library General Public
License which covers the use of the GNU `gettext' library. This means
in particular that even non-free programs can use `libintl' as a shared
library, whereas only free software can use `libintl' as a static
library or use modified versions of `libintl'.
Once the sources are changed appropriately and the setup can handle
the use of `gettext' the only thing missing are the translations. The
Free Translation Project is also available for packages which are not
developed inside the GNU project. Therefore the information given above
applies also for every other Free Software Project. Contact
`translation@iro.umontreal.ca' to make the `.pot' files available to
the translation teams.

6
contrib/cpio/AUTHORS Normal file
View File

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

View File

@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
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
@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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
@ -305,14 +305,15 @@ the "copyright" line and a pointer to where the full notice is found.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision 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.

View File

@ -1,3 +1,433 @@
2004-12-20 Sergey Poznyakoff <gray@Mirddin.farlep.net>
Released version 2.6. Sources up to this point are tagged
release_2_6.
* configure.ac: Raised version number to 2.6
* NEWS: Likewise
* bootstrap (update_po): Give -r to wget. Always remove index.html
Ignore alloca-opt module (it duplicates alloca)
2004-11-23 Sergey Poznyakoff <gray@Mirddin.farlep.net>
* src/main.c (enum cpio_options): Bugfix: Initialize first enum
value to 256.
* bootstrap: Add unlocked-io
* headers/argp.h: Removed
* headers/getopt.h: Removed
* headers/Makefile.am: Updated
2004-10-14 Sergey Poznyakoff <gray@Mirddin.farlep.net>
* src/copyout.c: Add trailing slash to directory names in
ustar format.
* src/makepath.c: Removed redeclaration of error().
* src/tar.c: Fixed deviations from POSIX.1-1988:
Properly split long file names. Fill in octal fields with zeros,
not spaces. Save only protection modes, not the whole mode.
* NEWS: Updated
2004-09-08 Sergey Poznyakoff <gray@Mirddin.farlep.net>
* NEWS: Updated
* TODO: Updated
* bootstrap: Install po files by default
* po/LINGUAS: Removed. File is generated automatically
* po/.cvsignore: Updated
* src/copyin.c: Implemented --to-stdout option
* src/copyout.c: Display the annoying 'truncating inode number'
message only if the user wishes it.
* src/extern.h: Added new globals.
* src/global.c: Likewise.
* src/main.c: Added support for --to-stdout and --warning options
* src/tar.c (read_in_tar_header): Use warn_junk_bytes()
* src/util.c (create_all_directories): Use dir_name.
* configure.ac: Added support for the test suite
* Makefile.am: Likewise
* tests: New directory
* tests/.cvsignore: New file
* tests/Makefile.am: New file
* tests/testsuite.at: New file
* tests/inout.at: New file
* tests/version.at: New file
* tests/atlocal.in: New file
2004-09-07 Sergey Poznyakoff <gray@Mirddin.farlep.net>
* src/main.c (process_args): Bugfix. Allow extra arguments
in copy_in mode.
* src/util.c (write_nuls_to_file): Use buffered I/O. All
callers changed. Thanks Matthew Braithwaite <mab@cnet.com>
for noticing.
Bugfix: extra_bytes was mistakenly used instead of blocks.
* THANKS: Added Matthew Braithwaite.
2004-09-06 Sergey Poznyakoff <gray@Mirddin.farlep.net>
Started merging with tar into paxutils. Sources before
this point are tagged alpha-2_50_90.
* bootstrap: New file
* autogen.sh: Removed
* Makefile.am: Updated
* NEWS: Updated
* README-alpha: Updated
* configure.ac: Updated
* doc/cpio.1: Updated
* po/POTFILES.in: Updated
* src/Makefile.am: Updated
* src/error.c: Removed
* src/dirname.c: Likewise
* src/xmalloc.c: Likewise
* src/stripslash.c: Likewise
* src/xstrdup.c
* src/gettext.h: Likewise
* src/system.h: Likewise
* src/rmt.h: Likewise
* src/getopt.c: Likewise
* src/getopt1.c: Likewise
* src/bcopy.c: Likewise
* src/fnmatch.c: Likewise
* src/mkdir.c: Likewise
* src/strdup.c: Likewise
* src/argp-ba.c: Likewise
* src/argp-eexst.c: Likewise
* src/argp-fmtstream.c: Likewise
* src/argp-fs-xinl.c: Likewise
* src/argp-help.c: Likewise
* src/argp-parse.c: Likewise
* src/argp-pv.c: Likewise
* src/argp-pvh.c: Likewise
* src/argp-xinl.c: Likewise
* src/pin.c: Likewise
* src/alloca.c: Likewise
* src/argmatch.c: Likewise
* src/rmt.c: Likewise
* src/rtapelib.c: Likewise
* src/strerror.c: Likewise
* src/copyin.c: Switched to ANSI C (sigh)
* src/copyout.c: Likewise
* src/copypass.c: Likewise
* src/defer.c: Likewise
* src/defer.h: Likewise
* src/dstring.c: Likewise
* src/dstring.h: Likewise
* src/extern.h: Likewise
* src/filemode.c: Likewise
* src/global.c: Likewise
* src/idcache.c: Likewise
* src/main.c: Likewise
* src/makepath.c: Likewise
* src/mt.c: Likewise
* src/tar.c: Likewise
* src/userspec.c: Likewise
* src/util.c: Likewise
* lib: New directory
* lib/Makefile.tmpl: New file
* lib/bcopy.c: Moved from ../src
* lib/mkdir.c: Likewise.
* lib/strdup.c: Likewise.
* lib/strerror.c: Likewise.
2004-08-30 Sergey Poznyakoff <gray@Mirddin.farlep.net>
* Makefile.am: Added headers to SUBDIRS.
* configure.ac: Check for AC_SYS_LARGEFILE.
Use AC_CONFIG_LINKS to provide for fnmatch.h and getopt.h on
the systems where these are missing
Check for argp and replace it if necessary.
* src/Makefile.am: Updated
* src/fnmatch.h: Moved to headers/
* src/getopt.h: Likewise.
* src/main.c: Option parsing rewritten using argp. Improved
option consistency checking.
* src/rmt.c: Include getopt.h
* src/argp-ba.c: New file
* src/argp-eexst.c: New file
* src/argp-fmtstream.c: New file
* src/argp-fs-xinl.c: New file
* src/argp-help.c: New file
* src/argp-parse.c: New file
* src/argp-pv.c: New file
* src/argp-pvh.c: New file
* src/argp-xinl.c: New file
* src/pin.c: New file
* headers: New directory
* headers/Makefile.am: New file
* headers/getopt.h: New file
* headers/argp.h: New file
* headers/fnmatch.h: New file
* headers/.cvsignore: New file
2004-03-02 Sergey Poznyakoff <gray@Mirddin.farlep.net>
* src/util.c (copy_files_disk_to_disk): Bugfix. If a file
grew n bytes in copy-pass mode, these n bytes got prepended
to the contents of all subsequent files. Fix provided by
Holger Fleischmann <holger_fleischmann@mra.man.de>
* THANKS: Added Holger Fleischmann.
2004-02-27 Sergey Poznyakoff <gray@Mirddin.farlep.net>
* src/makepath.c: Remove unneded typedefs
* src/copyin.c: Remove __MSDOS__ conditionals
* src/copyout.c: Likewise
* src/copypass.c: Likewise
* src/main.c: Likewise
* src/tar.c: Likewise
* src/util.c: Likewise
2004-02-27 Sergey Poznyakoff <gray@Mirddin.farlep.net>
Changed from flat to deep package layout. Added the framework
for NLS support.
* .cvsignore: Updated
* Makefile.am: Updated
* configure.ac: Updated
* NEWS: Updated
* README-alpha: Updated
* THANKS: Updated
* autogen.sh: New file
* alloca.c: Moved to src
* argmatch.c: Likewise
* bcopy.c: Likewise
* dstring.h: Likewise
* copyin.c: Likewise
* copyout.c: Likewise
* copypass.c: Likewise
* cpio.h: Likewise
* cpiohdr.h: Likewise
* defer.c: Likewise
* defer.h: Likewise
* dirname.c: Likewise
* dstring.c: Likewise
* dstring.h: Likewise
* error.c: Likewise
* extern.h: Likewise
* filemode.c: Likewise
* filetypes.h: Likewise
* fnmatch.c: Likewise
* fnmatch.h: Likewise
* getopt.c: Likewise
* getopt.h: Likewise
* getopt1.c: Likewise
* global.c: Likewise
* idcache.c: Likewise
* main.c: Likewise
* makepath.c: Likewise
* mkdir.c: Likewise
* mt.c: Likewise
* rmt.c: Likewise
* rmt.h: Likewise
* rtapelib.c: Likewise
* safe-stat.h: Likewise
* strdup.c: Likewise
* strerror.c: Likewise
* stripslash.c: Likewise
* system.h: Likewise
* tar.c: Likewise
* tar.h: Likewise
* tarhdr.h: Likewise
* userspec.c: Likewise
* util.c: Likewise
* xmalloc.c: Likewise
* xstrdup.c: Likewise
* cpio.1: Moved to doc
* cpio.texi: Likewise
* mt.1: Likewise
* src: New directory
* src/.cvsignore: New file
* src/Makefile.am: Likewise
* src/alloca.c: Likewise
* src/argmatch.c: Likewise
* src/bcopy.c: Likewise
* src/copyin.c: Likewise
* src/copyout.c: Likewise
* src/copypass.c: Likewise
* src/cpio.h: Likewise
* src/cpiohdr.h: Likewise
* src/defer.c: Likewise
* src/defer.h: Likewise
* src/dirname.c: Likewise
* src/dstring.c: Likewise
* src/dstring.h: Likewise
* src/error.c: Likewise
* src/extern.h: Likewise
* src/filemode.c: Likewise
* src/filetypes.h: Likewise
* src/fnmatch.c: Likewise
* src/fnmatch.h: Likewise
* src/getopt.c: Likewise
* src/getopt.h: Likewise
* src/getopt1.c: Likewise
* src/gettext.h: Likewise
* src/global.c: Likewise
* src/idcache.c: Likewise
* src/main.c: Likewise
* src/makepath.c: Likewise
* src/mkdir.c: Likewise
* src/mt.c: Likewise
* src/rmt.c: Likewise
* src/rmt.h: Likewise
* src/rtapelib.c: Likewise
* src/safe-stat.h: Likewise
* src/strdup.c: Likewise
* src/strerror.c: Likewise
* src/stripslash.c: Likewise
* src/system.h: Likewise
* src/tar.c: Likewise
* src/tar.h: Likewise
* src/tarhdr.h: Likewise
* src/userspec.c: Likewise
* src/util.c: Likewise
* src/xmalloc.c: Likewise
* src/xstrdup.c: Likewise
* doc: New directory
* doc/.cvsignore: New file
* doc/Makefile.am: New file
* doc/cpio.1: New file
* doc/cpio.info: New file
* doc/cpio.texi: New file
* doc/mt.1: New file
* po: New directory
* po/.cvsignore: New file
* po/LINGUAS: New file
* po/Makevars: New file
* po/POTFILES.in: New file
2003-11-28 Sergey Poznyakoff <gray@Mirddin.farlep.net>
* configure.ac: Added various checks
* Makefile.am (rmt_LDADD): Added.
* error.c: Updated
* rmt.c: Removed useless private_errstring
* system.h: Updated
* userspec.c: Changed the way of handling declared vs. undeclared
system calls.
* strerror.c: New file. Borrowed from GNU Radius.
* copyin.c: Removed kludgy declaration of delayed_seek_count.
* copypass.c: Likewise
* extern.h: Declare delayed_seek_count.
* mkdir.c: Fixed handling of undeclared errno
* mt.c: Likewise
* util.c: Likewise
* rtapelib.c: Likewise
2003-11-28 Sergey Poznyakoff <gray@Mirddin.farlep.net>
* TODO: New file
* README-alpha: New file
* Makefile.am: Require at least version 1.7.1
* configure.ac: Check for locale.h
* main.c (main): Call setlocale. Thanks
Mitsuru Chinen <mchinen@yamato.ibm.com> for the patch.
* THANKS: Updated
2003-11-21 Sergey Poznyakoff <gray@Mirddin.farlep.net>
* configure.ac: Added to the repository
* Makefile.am: Likewise
* NEWS: Likewise
* README: Likewise
* AUTHORS: Likewise
* .cvsignore: Likewise
* configure.in: Removed
* Makefile.in: Removed
* makefile.pc: Removed
* configure: Removed
* alloca.c: Added to the repository
* argmatch.c: Likewise
* bcopy.c: Likewise
* cpio.h: Likewise
* cpiohdr.h: Likewise
* defer.c: Likewise
* defer.h: Likewise
* dirname.c: Likewise
* dstring.c: Likewise
* dstring.h: Likewise
* error.c: Likewise
* filemode.c: Likewise
* filetypes.h: Likewise
* fnmatch.c: Likewise
* fnmatch.h: Likewise
* getopt.c: Likewise
* getopt.h: Likewise
* getopt1.c: Likewise
* idcache.c: Likewise
* mkdir.c: Likewise
* rmt.h: Likewise
* rtapelib.c: Likewise
* safe-stat.h: Likewise
* strdup.c: Likewise
* stripslash.c: Likewise
* tar.c: Likewise
* tar.h: Likewise
* tarhdr.h: Likewise
* xmalloc.c: Likewise
* xstrdup.c: Likewise
* makepath.c: Updated
* mt.c: Likewise.
* rmt.c: Likewise.
* util.c: Likewise.
* copyin.c: Likewise.
* copyout.c: Likewise.
* copypass.c: Likewise.
* global.c: Likewise.
* main.c: Likewise.
Thu Jun 13 20:14:48 2002 John Oleynick (juo@gnu.org)
* copyin.c: Strip leading / on absolute filenames after
comparing to the list of files specified on the command line
(instead of before). Problem reported by Jeff Holt.
* Version 2.5 released.
Thu Jun 13 00:20:30 2002 John Oleynick (juo@gnu.org)
* Makefile.in: Fixed problem of looking in srcdir for info files.
Bug reported by Mike Castle.
* cpio.texi: Fixed typo. Problem reported by Fabrice Bauzac.
Sun Jan 13 18:45:02 2002 John Oleynick (juo@gnu.org)
* copyin.c: Fixed a problem skipping files with multiple links
in a newc or CRC format archive. If the file with the shared copy
of the data was skipped, but other links were not skipped, the
other links were created as empty files. Bug reported by
Hendrik-Jan Thomassen.
Thu Dec 6 20:05:10 2001 John Oleynick (juo@gnu.org)
* mt.c, mt.1: Merged Debian --rsh-command option and -V fix.
* copyout.c, copypass.c, util.c, extern.h: Modified to warn
if a file grows or its mtime is changed while it is being
copied.
Wed Dec 6 00:02:04 2001 John Oleynick (juo@gnu.org)
* Many files: Updated FSF's address in copyright notices.
Wed Aug 29 23:57:05 2001 John Oleynick (juo@gnu.org)
* Many files: Numerous fixes from Debian, Red Hat and SuSE
GNU/Linux distributions.
Tue Jan 16 19:03:05 1996 John Oleynick (juo@wombat.gnu.ai.mit.edu)
* util.c: An I/O error reading a file would cause the last byte
of the next file to be corrupted in the archive. Thanks to a
@ -962,7 +1392,6 @@ Sat Dec 2 13:22:37 1989 David J. MacKenzie (djm at hobbes.ai.mit.edu)
(usage): Mention long options in message.
Local Variables:
mode: indented-text
left-margin: 8
mode: change-log
version-control: never
End:

231
contrib/cpio/INSTALL Normal file
View File

@ -0,0 +1,231 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
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 only 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. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. 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=c89 CFLAGS=-O2 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 must use a version of `make' that
supports the `VPATH' variable, such as 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 `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have 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' will install the package's files in
`/usr/local/bin', `/usr/local/man', 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
give `configure' the option `--exec-prefix=PREFIX', the package will
use PREFIX as the prefix for installing programs and libraries.
Documentation and other data files will 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 `--target=TYPE' option 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
will cause the specified gcc to be used as the C compiler (unless it is
overridden in the site shell script).
`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.

View File

@ -1,3 +1,44 @@
GNU cpio NEWS -- history of user-visible changes. 2004-12-20
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
See the end of file for copying conditions.
Please send cpio bug reports to <bug-cpio@gnu.org>.
Version 2.6
* 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:
@ -62,3 +103,23 @@ Some options have changed meaning in 2.0, for SVR4 compatibility:
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 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: "[ ]*$"
end:

View File

@ -9,7 +9,8 @@ operations, respectively.
See the file INSTALL for compilation and installation instructions for Unix.
For non-Unix systems:
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.
@ -67,5 +68,4 @@ than 100 characters. That's why it's not an official part of GNU tar.
*stdp = 1;
if (wantug) {
Mail suggestions and bug reports for GNU cpio to
bug-gnu-utils@prep.ai.mit.edu.
Mail suggestions and bug reports for GNU cpio to bug-cpio@gnu.org.

14
contrib/cpio/THANKS Normal file
View File

@ -0,0 +1,14 @@
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.
Matthew Braithwaite <mab@cnet.com>
Mitsuru Chinen <mchinen@yamato.ibm.com>
Holger Fleischmann <holger_fleischmann@mra.man.de>

356
contrib/cpio/TODO Normal file
View File

@ -0,0 +1,356 @@
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 sorted
in reverse chronological order.
4. copyin.c cpio probably questions/rfc (score: 35)
Author: Grzegorz Jaskiewicz <gj@pointblue.com.pl>
Date: Tue, 24 Jun 2003 17:12:45 +0100
Hi! I am currently working on module that (in GNU software)
will be able to read/write cpio format (only ascii). Thus i am
separating some of cpio structures into libcpio. I've been
going through cop
/archive/html/bug-gnu-utils/2003-06/msg00422.html (5,430 bytes)
5. RE: Problem when building on HP-UX 11i(11.11) (score: 4)
Author: "Leon Strydom" <leon.strydom@tasima.co.za>
Date: Thu, 13 Mar 2003 09:10:02 +0200
Hi Bob, I got it to compile, thanks. The reason why I had to
try GNU-Tar is because of the 2GB file size limit problems:
Here are the errors I got: With TAR(hp-ux 11i tar): CMD: tar
cvf backup.tar /a
/archive/html/bug-gnu-utils/2003-03/msg00106.html (5,191 bytes)
6. cpio - large file support (score: 35)
Author: "Keith Ansell" <keitha@edp.fastfreenet.com>
Date: Tue, 4 Mar 2003 16:24:37 -0000
Can you help. I need to archive a large database, this will
create a cpio file greater than 2 Gigabytes. Have you added
large file support to the build of cpio. Regards Keith
Ansell.....
/archive/html/bug-gnu-utils/2003-03/msg00024.html (4,329 bytes)
7. cpio-2.5 typos (score: 36)
Author: Thomas Klausner <wiz@danbala.ifoer.tuwien.ac.at>
Date: Sat, 21 Dec 2002 23:53:38 +0100
In cpio-2.5, in cpio.texi (and thus cpio.1) and main.c the word
'compatibility' is misspelled as 'compatability'. Please fix,
thanks. Thomas -- Thomas Klausner - wiz@bogus.example.com What
is wanted
/archive/html/bug-gnu-utils/2002-12/msg00200.html (3,783 bytes)
9. Re: bug in cpio with tapechange in copy-in-mode (score: 46)
Author: Paul Eggert <eggert@twinsun.com>
Date: Mon, 5 Aug 2002 12:28:33 -0700 (PDT)
Thanks for your bug report. Can you please verify that the bug
still exists in the latest CPIO version
<ftp://ftp.gnu.org/gnu/cpio/cpio-2.5.tar.gz>, and if so, please
send a patch to <bug-cpio@bogus.
/archive/html/bug-gnu-utils/2002-08/msg00127.html (4,275 bytes)
10. 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)
11. Re: CPIO Bug ? (score: 36)
Author: Albert Chin <bug-gnu-utils@lists.thewrittenword.com>
Date: Thu, 4 Jul 2002 19:31:04 -0500
I think the default CPIO format understands only 16-bit inodes.
Look at the -H option. '-H newc' should work better for you. --
albert chin (china@bogus.example.com)
/archive/html/bug-gnu-utils/2002-07/msg00091.html (4,286 bytes)
14. 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)
15. bug in cpio? (score: 34)
Author: "Jeff Holt" <jeff.holt@hotsos.com>
Date: Wed, 12 Jun 2002 14:07:59 -0500
According to the man page, I should be able to extract an
absolute pathname from an archive and have the file created
relative to the current directory (by removing the leading
&#8216;/&#8217;).<o:p>
/archive/html/bug-gnu-utils/2002-06/msg00296.html (5,331 bytes)
16. CPIO Bug ? (score: 35)
Author: =?iso-8859-1?Q?Gr=E9goire_Fiot?=
<gfiot@eiffageconstruction.fr>
Date: Tue, 14 May 2002 17:01:18 +0200
Hello, We ve got a problem here using cpio: many "troncating
inode number" appear during the process: cpio -ocv Is that a
real problem? Does it corrupt files? Well.. what does that
mean? We have look
/archive/html/bug-gnu-utils/2002-05/msg00333.html (3,855 bytes)
23. [cpio texinfo] typo (score: 2)
Author: fabrice bauzac <fabrice.bauzac@wanadoo.fr>
Date: Tue, 7 May 2002 16:37:28 +0200
Good afternoon, There is a typo in the Texinfo documentation of
GNU cpio, node "Copy-in mode": [--format=format]
[--owner=[user][:.][group]] [--no- preserve-owner]
[--message=message] [--help] [--ver
/archive/html/bug-gnu-utils/2002-05/msg00153.html (4,040 bytes)
26. cpio: memory exhausted (score: 43)
Author: Thomas McLaughlin <tamm@scotlegal.com>
Date: Thu, 18 Apr 2002 09:51:18 +0100
This is probably not the place for my query, but I have
exhausted other avenues and would be glad of some help. I can't
work out what's going on with my nightly cpio backup. If I do:
cd / find . -pri
/archive/html/bug-gnu-utils/2002-04/msg00406.html (4,988 bytes)
30. 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)
32. 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)
35. GNU cpio compile problem (score: 34)
Author: Daniel Savard <dsavard@videotron.ca>
Date: Wed, 14 Nov 2001 12:43:11 -0500
Hi, I am trying to make the GNU cpio utility (version 2.4.2)
using the gcc 3.0.2 compiler. The make failed on the userspec.c
file compilation. I then tried to compile with gcc 2.95.3 with
the followi
/archive/html/bug-gnu-utils/2001-11/msg00180.html (5,518 bytes)
36. 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)
38. [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)
39. 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)
40. cpio-2.4.2 patch (score: 39)
Author: Alex Efros <powerman@sky.net.ua>
Date: Wed, 29 Aug 2001 07:36:31 +0300 (EEST)
Hi. Linux-2.4.9, GCC-3.0, GLIBC-2.2.4, cpio-2.4.2. Compile-time
errors: --cut-- gcc -c -DRETSIGTYPE=void -DHAVE_SYS_MTIO_H=1
-DHAVE_NETDB_H=1 -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1
-DHAVE_STRING_H=1 -DHA
/archive/html/bug-gnu-utils/2001-08/msg00264.html (5,259 bytes)
41. 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)
42. 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)
43. (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)
44. gnu cpio and files over 2G (score: 37)
Author: J.S.Peatfield@damtp.cam.ac.uk
Date: Wed, 2 May 2001 06:28:18 +0100
As an increasing number of opertaing systems now support files
over 2G I took a look at the cpio (2.4.2) source to see how
hard it would be to make it cope, and was slightly shocked at
the number of
/archive/html/bug-gnu-utils/2001-05/msg00010.html (4,802 bytes)
45. 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)
46. [cpio 2.4.2] rmt build fails (score: 8)
Author: Gert <n8w8@n8w8.wox.org>
Date: Thu, 29 Mar 2001 21:28:52 +0200 (CEST)
Hi, The cpio 2.4.2 rmt tool fails to build on my system. I run
the following software: - Linux 2.4.2 - GCC 2.95.2 - GNU Make
3.79.1 - GNU ld 2.10 (with BFD 2.10) - glibc 2.1.3 The build
fails like th
/archive/html/bug-gnu-utils/2001-03/msg00262.html (5,498 bytes)
47. 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)
49. Re: bug with gnu cpio 2.4.2 (score: 38)
Author: Hans-Bernhard Broeker <broeker@physik.rwth-aachen.de>
Date: 6 Mar 2001 15:19:34 GMT
This would happen if cpio want to do any user interaction (ask
for the next tape cartridge, because the current one is full,
e.g.). Cron jobs don't have access to a terminal (/dev/tty), so
this will
/archive/html/bug-gnu-utils/2001-03/msg00029.html (5,062 bytes)
50. bug with gnu cpio 2.4.2 (score: 37)
Author: dominique.bieber@sagem.com
Date: Tue, 6 Mar 2001 12:27:14 +0100
Hi, I have a problem using cpio with a Red Hat 6.2 whith a
2.2.14-5.0smp kernel. The backup device is a HP DAT DDS4 20/40
with the right cartridge. The cpio is launched by the cron.
During the backup
/archive/html/bug-gnu-utils/2001-03/msg00024.html (4,315 bytes)
52. [PATCH] cpio 2.4.2 does not compile with libc 2.2, gcc 2.95
(score: 38)
Author: "John Fremlin" <chief@bandits.org>
Date: 11 Feb 2001 22:19:09 +0000
In fact it violates the GNU coding standards by declaring stuff
when it shouldn't. Tsk, tsk. Attachment: cpio-2.4.2-build.patch
Description: Text Data -- http://www.penguinpowered.com/~vii
/archive/html/bug-gnu-utils/2001-02/msg00065.html (4,169 bytes)
53. 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)
54. 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)
55. 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)
56. cpio-2.4.2 compilation problems (score: 34)
Author: Thomas =?iso-8859-1?q?K=F6ller?= <tkoeller@gmx.net>
Date: Wed, 20 Dec 2000 02:50:24 +0100
I encountered several problems building cpio-2.4.2. I am
running linux-2.2.17, glibc-2.1.3 and gcc 2.95.2. The errors I
received were mostly due to the source files re-declaring
things unconditionall
/archive/html/bug-gnu-utils/2000-12/msg00109.html (5,782 bytes)
58. cpio-2.4.2 & glibc-2.* (score: 46)
Author: Florian Wunderlich <fwunderlich@devbrain.de>
Date: Mon, 18 Dec 2000 16:25:00 +0100
I still do not see a new version of cpio or at least extra
patches that fix it so it works with the glibc. Thus, here is a
simple patch to make it compile with glibc: diff -u
cpio-2.4.2-old/rmt.c cpi
/archive/html/bug-gnu-utils/2000-12/msg00098.html (4,846 bytes)
60. cpio-2.4.2 signed-unsigned int disagreement with malloc (score:
39)
Author: Antonomasia <ant@notatla.demon.co.uk>
Date: Mon, 27 Nov 2000 07:05:01 GMT
copyin.c: 534 link_name = (char *) xmalloc ((unsigned int)
file_hdr.c_filesize + 1); 535 link_name[file_hdr.c_filesize] =
'\0'; file_hdr.c_filesize can be a large negative number as
seen here then th
/archive/html/bug-gnu-utils/2000-11/msg00171.html (4,718 bytes)
61. gnu CPIO (score: 38)
Author: Clark Cooper <Clark.Cooper@vc3.com>
Date: Mon, 13 Nov 2000 13:21:07 -0500 (EST)
The gnu version of CPIO appears to send all output to stderr.
Take for instance a need to have the list of files copied and
any errors separated as should be produced by the following:
find . -print
/archive/html/bug-gnu-utils/2000-11/msg00089.html (3,903 bytes)
62. Desire enhancement to GNU cpio 2.4.2 (score: 35)
Author: Dave Dykstra <dwd@bell-labs.com>
Date: Mon, 13 Nov 2000 10:24:56 -0600
I have a new GNU/Linux system with large disks on which I need
to generate cpio files for many different systems including
older ones that don't support the "newc" format, only the "odc"
format. The
/archive/html/bug-gnu-utils/2000-11/msg00087.html (5,115 bytes)
65. 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)
66. [Bug-gnu-utils] A small problem with cpio (score: 36)
Author: Chris Hall <Chris@clapham.org>
Date: Fri, 15 Sep 2000 11:05:56 +0100
Hi, I'm running cpio 2.4.2 on AIX 4.3.3 and have a problem with
very large files, I get this output when running the command: $
ls -l total 2867988 drwxrwxrwx 2 root sys 512 Sep 14 17:05
chris/ -rw-r
/archive/html/bug-gnu-utils/2000-09/msg00004.html (4,481 bytes)

41
contrib/cpio/doc/cpio.1 Normal file
View File

@ -0,0 +1,41 @@
.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] [\-\-no\-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

563
contrib/cpio/doc/cpio.texi Normal file
View File

@ -0,0 +1,563 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename cpio.info
@settitle cpio
@setchapternewpage off
@set VERSION GNU cpio 2.5
@set RELEASEDATE June 2002
@c %**end of header
@ifinfo
@format
START-INFO-DIR-ENTRY
* cpio: (cpio). Making tape (or disk) archives.
END-INFO-DIR-ENTRY
@end format
@end ifinfo
@ifinfo
This file documents @value{VERSION}.
Copyright (C) 1995, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
@ignore
Permission is granted to process this file through TeX and print the
results, provided the printed document carries copying permission
notice identical to this one except for the removal of this paragraph
@end ignore
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation approved
by the Foundation.
@end ifinfo
@titlepage
@title GNU CPIO
@subtitle @value{VERSION} @value{RELEASEDATE}
@author by Robert Carleton
@c copyright page
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1995, 2001, 2002 Free Software Foundation, Inc.
@sp 2
This is the first edition of the GNU cpio documentation,@*
and is consistent with @value{VERSION}.@*
@sp 2
Published by the Free Software Foundation @*
59 Temple Place - Suite 330, @*
Boston, MA 02111-1307, USA @*
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation
approved by the Free Software Foundation.
@end titlepage
@ifinfo
@node Top, Introduction, (dir), (dir)
@comment node-name, next, previous, up
@top
GNU cpio is a tool for creating and extracting archives, or copying
files from one place to another. It handles a number of cpio formats as
well as reading and writing tar files. This is the first edition of the
GNU cpio documentation and is consistant with @value{VERSION}.
@menu
* Introduction::
* Tutorial:: Getting started.
* Invoking `cpio':: How to invoke `cpio'.
* Media:: Using tapes and other archive media.
* Concept Index:: Concept index.
--- The Detailed Node Listing ---
Invoking cpio
* Copy-out mode::
* Copy-in mode::
* Copy-pass mode::
* Options::
@end menu
@end ifinfo
@node Introduction, Tutorial, Top, Top
@comment node-name, next, previous, up
@chapter Introduction
GNU cpio copies files into or out of a cpio or tar archive, The archive
can be another file on the disk, a magnetic tape, or a pipe.
GNU cpio supports the following archive formats: binary, old ASCII, new
ASCII, crc, HPUX binary, HPUX old ASCII, old tar, and POSIX.1 tar. The
tar format is provided for compatability with the tar program. By
default, cpio creates binary format archives, for compatibility with
older cpio programs. When extracting from archives, cpio automatically
recognizes which kind of archive it is reading and can read archives
created on machines with a different byte-order.
@node Tutorial, Invoking `cpio', Introduction, Top
@comment node-name, next, previous, up
@chapter Tutorial
@cindex creating a cpio archive
@cindex extracting a cpio archive
@cindex copying directory structures
@cindex passing directory structures
GNU cpio performs three primary functions. Copying files to an
archive, Extracting files from an archive, and passing files to another
directory tree. An archive can be a file on disk, one or more floppy
disks, or one or more tapes.
When creating an archive, cpio takes the list of files to be processed
from the standard input, and then sends the archive to the standard
output, or to the device defined by the @samp{-F} option.
@xref{Copy-out mode}. Usually find or ls is used to provide this list
to the standard input. In the following example you can see the
possibilities for archiving the contents of a single directory.
@example
@cartouche
% ls | cpio -ov > directory.cpio
@end cartouche
@end example
The @samp{-o} option creates the archive, and the @samp{-v} option
prints the names of the files archived as they are added. Notice that
the options can be put together after a single @samp{-} or can be placed
separately on the command line. The @samp{>} redirects the cpio output
to the file @samp{directory.cpio}.
If you wanted to archive an entire directory tree, the find command can
provide the file list to cpio:
@example
@cartouche
% find . -print -depth | cpio -ov > tree.cpio
@end cartouche
@end example
This will take all the files in the current directory, the directories
below and place them in the archive tree.cpio. Again the @samp{-o}
creates an archive, and the @samp{-v} option shows you the name of the
files as they are archived. @xref{Copy-out mode}. Using the `.' in the
find statement will give you more flexibility when doing restores, as it
will save file names with a relative path vice a hard wired, absolute
path. The @samp{-depth} option forces @samp{find} to print of the
entries in a directory before printing the directory itself. This
limits the effects of restrictive directory permissions by printing the
directory entries in a directory before the directory name itself.
Extracting an archive requires a bit more thought because cpio will not
create directories by default. Another characteristic, is it will not
overwrite existing files unless you tell it to.
@example
@cartouche
% cpio -iv < directory.cpio
@end cartouche
@end example
This will retrieve the files archived in the file directory.cpio and
place them in the present directory. The @samp{-i} option extracts the
archive and the @samp{-v} shows the file names as they are extracted.
If you are dealing with an archived directory tree, you need to use the
@samp{-d} option to create directories as necessary, something like:
@example
@cartouche
% cpio -idv < tree.cpio
@end cartouche
@end example
This will take the contents of the archive tree.cpio and extract it to
the current directory. If you try to extract the files on top of files
of the same name that already exist (and have the same or later
modification time) cpio will not extract the file unless told to do so
by the -u option. @xref{Copy-in mode}.
In copy-pass mode, cpio copies files from one directory tree to another,
combining the copy-out and copy-in steps without actually using an
archive. It reads the list of files to copy from the standard input;
the directory into which it will copy them is given as a non-option
argument. @xref{Copy-pass mode}.
@example
@cartouche
% find . -depth -print0 | cpio --null -pvd new-dir
@end cartouche
@end example
The example shows copying the files of the present directory, and
sub-directories to a new directory called new-dir. Some new options are
the @samp{-print0} available with GNU find, combined with the
@samp{--null} option of cpio. These two options act together to send
file names between find and cpio, even if special characters are
embedded in the file names. Another is @samp{-p}, which tells cpio to
pass the files it finds to the directory @samp{new-dir}.
@node Invoking `cpio', Media, Tutorial, Top
@comment node-name, next, previous, up
@chapter Invoking cpio
@cindex invoking cpio
@cindex command line options
@menu
* Copy-out mode::
* Copy-in mode::
* Copy-pass mode::
* Options::
@end menu
@node Copy-out mode, Copy-in mode, Invoking `cpio', Invoking `cpio'
@comment node-name, next, previous, up
@section Copy-out mode
In copy-out mode, cpio copies files into an archive. It reads a list
of filenames, one per line, on the standard input, and writes the
archive onto the standard output. A typical way to generate the list
of filenames is with the find command; you should give find the -depth
option to minimize problems with permissions on directories that are
unreadable.
@xref{Options}.
@example
cpio @{-o|--create@} [-0acvABLV] [-C bytes] [-H format]
[-M message] [-O [[user@@]host:]archive] [-F [[user@@]host:]archive]
[--file=[[user@@]host:]archive] [--format=format]
[--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 `.' in a
filename does match a wildcard at the start of a pattern, and a `/' in a
filename can match wildcards. If no patterns are given, all files are
extracted. @xref{Options}.
@example
cpio @{-i|--extract@} [-bcdfmnrtsuvBSV] [-C bytes] [-E file]
[-H format] [-M message] [-R [user][:.][group]]
[-I [[user@@]host:]archive] [-F [[user@@]host:]archive]
[--file=[[user@@]host:]archive] [--make-directories]
[--nonmatching] [--preserve-modification-time]
[--numeric-uid-gid] [--rename] [--list] [--swap-bytes] [--swap]
[--dot] [--unconditional] [--verbose] [--block-size=blocks]
[--swap-halfwords] [--io-size=bytes] [--pattern-file=file]
[--format=format] [--owner=[user][:.][group]]
[--no-preserve-owner] [--message=message] [--help] [--version]
[-no-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, --null
Read a list of filenames terminated by a null character, instead of a
newline, so that files whose names contain newlines can be archived.
GNU find is one way to produce a list of null-terminated filenames.
This option may be used in copy-out and copy-pass modes.
@item -a, --reset-access-time
Reset the access times of files after reading them, so
that it does not look like they have just been read.
@item -A, --append
Append to an existing archive. Only works in copy-out
mode. The archive must be a disk file specified with
the -O or -F (--file) option.
@item -b, --swap
Swap both halfwords of words and bytes of halfwords in the data.
Equivalent to -sS. This option may be used in copy-in mode. Use this
option to convert 32-bit integers between big-endian and little-endian
machines.
@item -B
Set the I/O block size to 5120 bytes. Initially the
block size is 512 bytes.
@item --block-size=BLOCK-SIZE
Set the I/O block size to BLOCK-SIZE * 512 bytes.
@item -c
Use the old portable (ASCII) archive format.
@item -C IO-SIZE, --io-size=IO-SIZE
Set the I/O block size to IO-SIZE bytes.
@item -d, --make-directories
Create leading directories where needed.
@item -E FILE, --pattern-file=FILE
Read additional patterns specifying filenames to extract or list from
FILE. The lines of FILE are treated as if they had been non-option
arguments to cpio. This option is used in copy-in mode,
@item -f, --nonmatching
Only copy files that do not match any of the given
patterns.
@item -F, --file=archive
Archive filename to use instead of standard input or output. To use a
tape drive on another machine as the archive, use a filename that starts
with `HOSTNAME:'. The hostname can be preceded by a username and an
`@@' to access the remote tape drive as that user, if you have
permission to do so (typically an entry in that user's `~/.rhosts'
file).
@item --force-local
With -F, -I, or -O, take the archive file name to be a
local file even if it contains a colon, which would
ordinarily indicate a remote host name.
@item -H FORMAT, --format=FORMAT
Use archive format FORMAT. The valid formats are listed below; the same
names are also recognized in all-caps. The default in copy-in mode is
to automatically detect the archive format, and in copy-out mode is
@samp{bin}.
@table @samp
@item bin
The obsolete binary format.
@item odc
The old (POSIX.1) portable format.
@item newc
The new (SVR4) portable format, which supports file systems having more
than 65536 i-nodes.
@item crc
The new (SVR4) portable format with a checksum added.
@item tar
The old tar format.
@item ustar
The POSIX.1 tar format. Also recognizes GNU tar archives, which are
similar but not identical.
@item hpbin
The obsolete binary format used by HPUX's cpio (which stores device
files differently).
@item hpodc
The portable format used by HPUX's cpio (which stores device files
differently).
@end table
@item -i, --extract
Run in copy-in mode.
@xref{Copy-in mode}.
@item -I archive
Archive filename to use instead of standard input. To use a tape drive
on another machine as the archive, use a filename that starts with
`HOSTNAME:'. The hostname can be preceded by a username and an `@@' to
access the remote tape drive as that user, if you have permission to do
so (typically an entry in that user's `~/.rhosts' file).
@item -k
Ignored; for compatibility with other versions of cpio.
@item -l, --link
Link files instead of copying them, when possible.
@item -L, --dereference
Copy the file that a symbolic link points to, rather than the symbolic
link itself.
@item -m, --preserve-modification-time
Retain previous file modification times when creating files.
@item -M MESSAGE, --message=MESSAGE
Print MESSAGE when the end of a volume of the backup media (such as a
tape or a floppy disk) is reached, to prompt the user to insert a new
volume. If MESSAGE contains the string "%d", it is replaced by the
current volume number (starting at 1).
@item -n, --numeric-uid-gid
Show numeric UID and GID instead of translating them into names when using the
@samp{--verbose option}.
@item --no-absolute-filenames
Create all files relative to the current directory in copy-in mode, even
if they have an absolute file name in the archive.
@item --no-preserve-owner
Do not change the ownership of the files; leave them owned by the user
extracting them. This is the default for non-root users, so that users
on System V don't inadvertantly give away files. This option can be
used in copy-in mode and copy-pass mode
@item -o, --create
Run in copy-out mode.
@xref{Copy-out mode}.
@item -O archive
Archive filename to use instead of standard output. To use a tape drive
on another machine as the archive, use a filename that starts with
`HOSTNAME:'. The hostname can be preceded by a username and an `@@' to
access the remote tape drive as that user, if you have permission to do
so (typically an entry in that user's `~/.rhosts' file).
@item --only-verify-crc
Verify the CRC's of each file in the archive, when reading a CRC format
archive. Don't actually extract the files.
@item -p, --pass-through
Run in copy-pass mode.
@xref{Copy-pass mode}.
@item --quiet
Do not print the number of blocks copied.
@item -r, --rename
Interactively rename files.
@item -R [user][:.][group], --owner [user][:.][group]
Set the ownership of all files created to the specified user and/or
group in copy-out and copy-pass modes. Either the user, the group, or
both, must be present. If the group is omitted but the ":" or "."
separator is given, use the given user's login group. Only the
super-user can change files' ownership.
@item --rsh-command=COMMAND
Notifies cpio that is should use COMMAND to communicate with remote
devices.
@item -s, --swap-bytes
Swap the bytes of each halfword (pair of bytes) in the files.This option
can be used in copy-in mode.
@item -S, --swap-halfwords
Swap the halfwords of each word (4 bytes) in the files. This option may
be used in copy-in mode.
@item --sparse
Write files with large blocks of zeros as sparse files. This option is
used in copy-in and copy-pass modes.
@item -t, --list
Print a table of contents of the input.
@item -u, --unconditional
Replace all files, without asking whether to replace
existing newer files with older files.
@item -v, --verbose
List the files processed, or with @samp{-t}, give an @samp{ls -l} style
table of contents listing. In a verbose table of contents of a ustar
archive, user and group names in the archive that do not exist on the
local system are replaced by the names that correspond locally to the
numeric UID and GID stored in the archive.
@item -V --dot
Print a @kbd{.} for each file processed.
@item --version
Print the cpio program version number and exit.
@end table
@node Media, Concept Index, Invoking `cpio', Top
@comment node-name, next, previous, up
@chapter Magnetic Media
@cindex magnetic media
Archives are usually written on removable media--tape cartridges, mag
tapes, or floppy disks.
The amount of data a tape or disk holds depends not only on its size,
but also on how it is formatted. A 2400 foot long reel of mag tape
holds 40 megabytes of data when formated at 1600 bits per inch. The
physically smaller EXABYTE tape cartridge holds 2.3 gigabytes.
Magnetic media are re-usable--once the archive on a tape is no longer
needed, the archive can be erased and the tape or disk used over. Media
quality does deteriorate with use, however. Most tapes or disks should
be disgarded when they begin to produce data errors.
Magnetic media are written and erased using magnetic fields, and should
be protected from such fields to avoid damage to stored data. Sticking
a floppy disk to a filing cabinet using a magnet is probably not a good
idea.
@node Concept Index, , Media, Top
@comment node-name, next, previous, up
@unnumbered Concept Index
@printindex cp
@contents
@bye

View File

@ -0,0 +1,54 @@
/* Memory allocation on the stack.
Copyright (C) 1995, 1999, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
/* When this file is included, it may be preceded only by preprocessor
declarations. Thanks to AIX. Therefore we include it right after
"config.h", not later. */
#ifndef _ALLOCA_H
# define _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.
*/
#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 /* _ALLOCA_H */

View File

@ -0,0 +1,25 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;

View File

@ -0,0 +1,31 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;

View File

@ -0,0 +1,440 @@
/* Word-wrapping and line-truncating streams
Copyright (C) 1997,1998,1999,2001,2002,2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
if (_IO_fwide (fs->stream, 0) > 0)
__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf);
else
#endif
fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
}
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. */
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 USE_IN_LIBIO
if (_IO_fwide (fs->stream, 0) > 0)
__fwprintf (fs->stream, L"%.*s\n",
(int) (nl - fs->buf), fs->buf);
else
#endif
{
if (nl > fs->buf)
fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
putc_unlocked ('\n', fs->stream);
}
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 USE_IN_LIBIO
if (_IO_fwide (fs->stream, 0) > 0)
{
__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf);
wrote = fs->p - fs->buf;
}
else
#endif
wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
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 */

View File

@ -0,0 +1,309 @@
/* Word-wrapping and line-truncating streams.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#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. */
#ifndef __const
#define __const const
#endif
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 */

View File

@ -0,0 +1,43 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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

1884
contrib/cpio/lib/argp-help.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,156 @@
/* Name frobnication for compiling argp outside of glibc
Copyright (C) 1997, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
#include "mempcpy.h"
#include "strcase.h"
#include "strchrnul.h"
#include "strndup.h"
/* 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
extern char *__argp_basename (char *name);
#endif /* !_LIBC */
#ifndef __set_errno
#define __set_errno(e) (errno = (e))
#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

View File

@ -0,0 +1,926 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <alloca.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"
/* 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,"NAME", OPTION_HIDDEN, N_("Set the program name"), 0},
{"HANG", OPT_HANG, "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 = strrchr (arg, '/');
if (state->name)
state->name++;
else
state->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;
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. */
#define GLEN (szs.num_groups + 1) * sizeof (struct group)
#define CLEN (szs.num_child_inputs * sizeof (void *))
#define LLEN ((szs.long_len + 1) * sizeof (struct option))
#define SLEN (szs.short_len + 1)
parser->storage = malloc (GLEN + CLEN + LLEN + SLEN);
if (! parser->storage)
return ENOMEM;
parser->groups = parser->storage;
parser->child_inputs = parser->storage + GLEN;
parser->long_opts = parser->storage + GLEN + CLEN;
parser->short_opts = parser->storage + GLEN + CLEN + LLEN;
parser->opt_data = opt_data;
memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *));
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. */
{
char *short_name = strrchr (argv[0], '/');
parser->state.name = short_name ? short_name + 1 : 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;
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

View File

@ -0,0 +1,24 @@
/* Default definition for ARGP_PROGRAM_VERSION.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 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;

View File

@ -0,0 +1,31 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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;

View File

@ -0,0 +1,43 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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

604
contrib/cpio/lib/argp.h Normal file
View File

@ -0,0 +1,604 @@
/* Hierarchial argument parsing, layered over getopt.
Copyright (C) 1995-1999,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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _ARGP_H
#define _ARGP_H
#include <stdio.h>
#include <ctype.h>
#include <getopt.h>
#define __need_error_t
#include <errno.h>
#ifndef __const
# define __const const
#endif
#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". */
#ifndef __restrict
# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
# if defined restrict || 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 `:'. */
__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). */
__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. */
/* 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
__NTH (__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 && 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 */

View File

@ -0,0 +1,79 @@
/* basename.c -- return the last element in a path
Copyright (C) 1990, 1998, 1999, 2000, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "dirname.h"
#include <string.h>
/* 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 address of the last file name component of NAME. If
NAME has no file name components because it is all slashes, return
NAME if it is empty, the address of its last slash otherwise. */
char *
base_name (char const *name)
{
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
char const *p;
for (p = base; *p; p++)
{
if (ISSLASH (*p))
{
/* Treat multiple adjacent slashes like a single slash. */
do p++;
while (ISSLASH (*p));
/* If the file name ends in slash, use the trailing slash as
the basename if no non-slashes have been found. */
if (! *p)
{
if (ISSLASH (*base))
base = p - 1;
break;
}
/* *P is a non-slash preceded by a slash. */
base = p;
}
}
return (char *) base;
}
/* Return the length of of the basename NAME. Typically NAME is the
value returned by base_name. Act like strlen (NAME), except omit
redundant trailing slashes. */
size_t
base_len (char const *name)
{
size_t len;
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
continue;
return len;
}

121
contrib/cpio/lib/dirname.c Normal file
View File

@ -0,0 +1,121 @@
/* dirname.c -- return all but the last element in a path
Copyright (C) 1990, 1998, 2000, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "dirname.h"
#include <string.h>
#include "xalloc.h"
/* Return the length of `dirname (PATH)', or zero if PATH is
in the working directory. Works properly even if
there are trailing slashes (by effectively ignoring them). */
size_t
dir_len (char const *path)
{
size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (path);
size_t length;
/* Strip the basename and any redundant slashes before it. */
for (length = base_name (path) - path; prefix_length < length; length--)
if (! ISSLASH (path[length - 1]))
return length;
/* But don't strip the only slash from "/". */
return prefix_length + ISSLASH (path[prefix_length]);
}
/* Return the leading directories part of PATH,
allocated with xmalloc.
Works properly even if there are trailing slashes
(by effectively ignoring them). */
char *
dir_name (char const *path)
{
size_t length = dir_len (path);
bool append_dot = (length == FILE_SYSTEM_PREFIX_LEN (path));
char *newpath = xmalloc (length + append_dot + 1);
memcpy (newpath, path, length);
if (append_dot)
newpath[length++] = '.';
newpath[length] = 0;
return newpath;
}
#ifdef TEST_DIRNAME
/*
Run the test like this (expect no output):
gcc -DHAVE_CONFIG_H -DTEST_DIRNAME -I.. -O -Wall \
basename.c dirname.c xmalloc.c error.c
sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out
If it's been built on a DOS or Windows platforms, run another test like
this (again, expect no output):
sed -n '/^BEGIN-DOS-DATA$/,/^END-DOS-DATA$/p' dirname.c|grep -v DATA|./a.out
BEGIN-DATA
foo//// .
bar/foo//// bar
foo/ .
/ /
. .
a .
END-DATA
BEGIN-DOS-DATA
c:///// c:/
c:/ c:/
c:/. c:/
c:foo c:.
c:foo/bar c:foo
END-DOS-DATA
*/
# define MAX_BUFF_LEN 1024
# include <stdio.h>
char *program_name;
int
main (int argc, char *argv[])
{
char buff[MAX_BUFF_LEN + 1];
program_name = argv[0];
buff[MAX_BUFF_LEN] = 0;
while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
{
char path[MAX_BUFF_LEN];
char expected_result[MAX_BUFF_LEN];
char const *result;
sscanf (buff, "%s %s", path, expected_result);
result = dir_name (path);
if (strcmp (result, expected_result))
printf ("%s: got %s, expected %s\n", path, result, expected_result);
}
return 0;
}
#endif

View File

@ -0,0 +1,47 @@
/* Take file names apart into directory and base names.
Copyright (C) 1998, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
# endif
# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
char *base_name (char const *path);
char *dir_name (char const *path);
size_t base_len (char const *path);
size_t dir_len (char const *path);
bool strip_trailing_slashes (char *path);
#endif /* not DIRNAME_H_ */

306
contrib/cpio/lib/error.c Normal file
View File

@ -0,0 +1,306 @@
/* Error handler for noninteractive utilities
Copyright (C) 1990-1998, 2000-2002, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "error.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _LIBC
# include <libintl.h>
#else
# include "gettext.h"
#endif
#ifdef _LIBC
# 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 <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
# ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
# 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
#endif /* not _LIBC */
static void
print_errno_message (int errnum)
{
char const *s = NULL;
#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;
# endif
#endif
#if !_LIBC
if (! s && ! (s = strerror (errnum)))
s = _("Unknown system error");
#endif
#if _LIBC
if (_IO_fwide (stderr, 0) > 0)
{
__fwprintf (stderr, L": %s", s);
return;
}
#endif
fprintf (stderr, ": %s", s);
}
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;
const wchar_t *wmessage = L"out of memory";
wchar_t *wbuf = (len < ALLOCA_LIMIT
? alloca (len * sizeof *wbuf)
: len <= SIZE_MAX / sizeof *wbuf
? malloc (len * sizeof *wbuf)
: NULL);
if (wbuf)
{
size_t res;
mbstate_t st;
const char *tmp = message;
memset (&st, '\0', sizeof (st));
res = mbsrtowcs (wbuf, &tmp, len, &st);
wmessage = res == (size_t) -1 ? L"???" : wbuf;
}
__vfwprintf (stderr, wmessage, args);
if (! (len < ALLOCA_LIMIT))
free (wbuf);
}
else
#endif
vfprintf (stderr, message, args);
va_end (args);
++error_message_count;
if (errnum)
print_errno_message (errnum);
#if _LIBC
if (_IO_fwide (stderr, 0) > 0)
putwc (L'\n', stderr);
else
#endif
putc ('\n', stderr);
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
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s: ", program_name);
else
#endif
fprintf (stderr, "%s: ", program_name);
}
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
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s: ", program_name);
else
#endif
fprintf (stderr, "%s:", program_name);
}
if (file_name != NULL)
{
#if _LIBC
if (_IO_fwide (stderr, 0) > 0)
__fwprintf (stderr, L"%s:%d: ", file_name, line_number);
else
#endif
fprintf (stderr, "%s:%d: ", file_name, line_number);
}
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

66
contrib/cpio/lib/error.h Normal file
View File

@ -0,0 +1,66 @@
/* Declaration for error-reporting function
Copyright (C) 1995, 1996, 1997, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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)
# 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 */

32
contrib/cpio/lib/exit.h Normal file
View File

@ -0,0 +1,32 @@
/* exit() function.
Copyright (C) 1995, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _EXIT_H
#define _EXIT_H
/* Get exit() declaration. */
#include <stdlib.h>
/* Some systems do not define EXIT_*, even with STDC_HEADERS. */
#ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
#endif
#endif /* _EXIT_H */

View File

@ -0,0 +1,27 @@
/* Failure exit status
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; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "exitfail.h"
#include "exit.h"
int volatile exit_failure = EXIT_FAILURE;

View File

@ -0,0 +1,20 @@
/* 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,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
extern int volatile exit_failure;

View File

@ -0,0 +1,83 @@
/* An interface to read and write that retries (if necessary) until complete.
Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
/* 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 = 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;
}

View File

@ -0,0 +1,35 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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

1241
contrib/cpio/lib/getopt.c Normal file

File diff suppressed because it is too large Load Diff

174
contrib/cpio/lib/getopt1.c Normal file
View File

@ -0,0 +1,174 @@
/* 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
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef _LIBC
# include <getopt.h>
#else
# 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 */

227
contrib/cpio/lib/getopt_.h Normal file
View File

@ -0,0 +1,227 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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>
# if HAVE_UNISTD_H
# include <unistd.h>
# endif
# 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 '\0'. This behavior is specific to the GNU
`getopt'. */
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 */

View File

@ -0,0 +1,131 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 */

View File

@ -0,0 +1,68 @@
/* Convenience header for conditional use of GNU <libintl.h>.
Copyright (C) 1995-1998, 2000-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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>
#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
/* 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) ((const char *) (Msgid))
# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define dngettext(Domainname, Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define textdomain(Domainname) ((const char *) (Domainname))
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
# define bind_textdomain_codeset(Domainname, Codeset) ((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
#endif /* _LIBGETTEXT_H */

View File

@ -0,0 +1,4 @@
#define LOCALEDIR "/usr/local/share/locale"
#ifndef DEFAULT_RMT_COMMAND
# define DEFAULT_RMT_COMMAND "/usr/local/libexec/rmt"
#endif

View File

@ -0,0 +1,29 @@
/* Copy memory area and return pointer after last written byte.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Specification. */
#include "mempcpy.h"
#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;
}

View File

@ -0,0 +1,36 @@
/* Copy memory area and return pointer after last written byte.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef mempcpy
# if HAVE_MEMPCPY
/* Get mempcpy() declaration. */
# include <string.h>
# else
/* Get size_t */
# include <stddef.h>
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
last written byte. */
extern void *mempcpy (void *dest, const void *src, size_t n);
# endif
#endif

99
contrib/cpio/lib/rmt.h Normal file
View File

@ -0,0 +1,99 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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))

740
contrib/cpio/lib/rtapelib.c Normal file
View File

@ -0,0 +1,740 @@
/* Functions for communicating with a remote tape drive.
Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004 Free
Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* 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 <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 <localedir.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
#ifdef O_NONBLOCK
if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK");
#endif
#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)
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 */
}
}

View File

@ -0,0 +1,82 @@
/* An interface to read and write that retries after interrupts.
Copyright (C) 1993, 1994, 1998, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
/* Specification. */
#ifdef SAFE_WRITE
# include "safe-write.h"
#else
# include "safe-read.h"
#endif
/* Get ssize_t. */
#include <sys/types.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#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;
}
}

View File

@ -0,0 +1,25 @@
/* An interface to read() 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <stddef.h>
#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);

View File

@ -0,0 +1,19 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define SAFE_WRITE
#include "safe-read.c"

View File

@ -0,0 +1,25 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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);

123
contrib/cpio/lib/savedir.c Normal file
View File

@ -0,0 +1,123 @@
/* savedir.c -- save the list of files in a directory in a string
Copyright 1990, 1997, 1998, 1999, 2000, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "savedir.h"
#include <sys/types.h>
#include <errno.h>
#if HAVE_DIRENT_H
# include <dirent.h>
#else
# define dirent direct
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#ifdef CLOSEDIR_VOID
/* Fake a return value. */
# define CLOSEDIR(d) (closedir (d), 0)
#else
# define CLOSEDIR(d) closedir (d)
#endif
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "xalloc.h"
/* Return a freshly allocated string containing the filenames
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. */
#ifndef NAME_SIZE_DEFAULT
# define NAME_SIZE_DEFAULT 512
#endif
char *
savedir (const char *dir)
{
DIR *dirp;
struct dirent *dp;
char *name_space;
size_t allocated = NAME_SIZE_DEFAULT;
size_t used = 0;
int save_errno;
dirp = opendir (dir);
if (dirp == NULL)
return NULL;
name_space = xmalloc (allocated);
errno = 0;
while ((dp = readdir (dirp)) != NULL)
{
/* Skip "", ".", and "..". "" is returned by at least one buggy
implementation: Solaris 2.4 readdir on NFS file systems. */
char const *entry = dp->d_name;
if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
{
size_t entry_size = strlen (entry) + 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;
}

View File

@ -0,0 +1,26 @@
/* Save the list of files in a directory in a string.
Copyright 1997, 1999, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#if !defined SAVEDIR_H_
# define SAVEDIR_H_
char *savedir (const char *dir);
#endif

View File

@ -0,0 +1,47 @@
/* Case-insensitive string comparison functions.
Copyright (C) 1995-1996, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _STRCASE_H
#define _STRCASE_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
greater than zero if S1 is lexicographically less than, equal to or greater
than S2.
Note: This function does not work correctly in multibyte locales. */
extern int strcasecmp (const char *s1, const char *s2);
/* Compare no more than N characters of strings S1 and S2, ignoring case,
returning less than, equal to or greater than zero if S1 is
lexicographically less than, equal to or greater than S2.
Note: This function can not work correctly in multibyte locales. */
extern int strncasecmp (const char *s1, const char *s2, size_t n);
#ifdef __cplusplus
}
#endif
#endif /* _STRCASE_H */

View File

@ -0,0 +1,30 @@
/* Searching in a string.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Specification. */
#include "strchrnul.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;
}

View File

@ -0,0 +1,28 @@
/* Searching in a string.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_STRCHRNUL
/* Get strchrnul() declaration. */
#include <string.h>
#else
/* Find the first occurrence of C in S or the final NUL byte. */
extern char *strchrnul (const char *s, int c_in);
#endif

View File

@ -0,0 +1,39 @@
/* stripslash.c -- remove redundant trailing slashes from a file name
Copyright (C) 1990, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "dirname.h"
/* Remove trailing slashes from PATH.
Return true if a trailing slash was removed.
This is useful when using filename completion from a shell that
adds a "/" after directory names (such as tcsh and bash), because
the Unix rename and rmdir system calls return an "Invalid argument" error
when given a path that ends in "/" (except for the root directory). */
bool
strip_trailing_slashes (char *path)
{
char *base = base_name (path);
char *base_lim = base + base_len (base);
bool had_slash = (*base_lim != '\0');
*base_lim = '\0';
return had_slash;
}

View File

@ -0,0 +1,55 @@
/* Copyright (C) 1996, 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#ifndef HAVE_DECL_STRNLEN
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRNLEN
size_t strnlen ();
#endif
#undef __strndup
#undef strndup
#ifndef weak_alias
# define __strndup strndup
#endif
char *
__strndup (const char *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);
}
#ifdef weak_alias
weak_alias (__strndup, strndup)
#endif

View File

@ -0,0 +1,30 @@
/* Duplicate a size-bounded string.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_STRNDUP
/* Get strndup() declaration. */
#include <string.h>
#else
#include <stddef.h>
/* Return a newly allocated copy of at most N bytes of STRING. */
extern char *strndup (const char *string, size_t n);
#endif

View File

@ -0,0 +1,48 @@
/* Find the length of STRING, but scan at most MAXLEN characters.
Copyright (C) 1996, 1997, 1998, 2000-2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#undef strnlen
#include <string.h>
#undef __strnlen
#undef strnlen
#ifndef _LIBC
# define strnlen rpl_strnlen
#endif
#ifndef weak_alias
# define __strnlen strnlen
#endif
/* 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;
}
#ifdef weak_alias
weak_alias (__strnlen, strnlen)
#endif

524
contrib/cpio/lib/system.h Normal file
View File

@ -0,0 +1,524 @@
/* System dependent definitions for GNU tar.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
/* MS-DOG forever, with my love! */
#ifndef O_BINARY
# define O_BINARY 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. */
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#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>
# 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
/* 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
/* 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
# undef HAVE_DECL_VALLOC
# define DMALLOC_FUNC_CHECK
# include <dmalloc.h>
#endif
#include <limits.h>
#ifndef MB_LEN_MAX
# define MB_LEN_MAX 1
#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
/* These macros work even on ones'-complement hosts (!).
The extra casts work around common compiler bugs. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
#define TYPE_MINIMUM(t) (TYPE_SIGNED (t) \
? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
: (t) 0)
#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
/* Bound on length of the string representing an integer value of type t.
Subtract one for the sign bit if t is signed;
302 / 1000 is log10 (2) rounded up;
add one for integer division truncation;
add one more for a minus sign if t is signed. */
#define INT_STRLEN_BOUND(t) \
((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
+ 1 + TYPE_SIGNED (t))
#define UINTMAX_STRSIZE_BOUND (INT_STRLEN_BOUND (uintmax_t) + 1)
/* Prototypes for external functions. */
#if HAVE_LOCALE_H
# include <locale.h>
#endif
#if !HAVE_SETLOCALE
# define setlocale(category, locale) /* empty */
#endif
#include <time.h>
#if defined(HAVE_SYS_TIME_H) && defined(TIME_WITH_SYS_TIME)
# include <sys/time.h>
#endif
#if ! HAVE_DECL_TIME
time_t time ();
#endif
#ifdef HAVE_UTIME_H
# include <utime.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

View File

@ -0,0 +1,137 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 */

View File

@ -0,0 +1,45 @@
/* Report a memory allocation failure and exit.
Copyright (C) 1997, 1998, 1999, 2000, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "xalloc.h"
#include <stdlib.h>
#include "error.h"
#include "exitfail.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
#define N_(msgid) 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 ();
}

79
contrib/cpio/lib/xalloc.h Normal file
View File

@ -0,0 +1,79 @@
/* xalloc.h -- malloc with out-of-memory checking
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#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 *xnmalloc (size_t n, size_t s);
void *xzalloc (size_t s);
void *xcalloc (size_t n, size_t s);
void *xrealloc (void *p, size_t s);
void *xnrealloc (void *p, size_t n, size_t s);
void *x2realloc (void *p, size_t *pn);
void *x2nrealloc (void *p, size_t *pn, size_t s);
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))
# ifdef __cplusplus
}
# endif
#endif /* !XALLOC_H_ */

229
contrib/cpio/lib/xmalloc.c Normal file
View File

@ -0,0 +1,229 @@
/* xmalloc.c -- malloc with out of memory checking
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "xalloc.h"
#include <stdlib.h>
#include <string.h>
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
/* Allocate an array of N objects, each with S bytes of memory,
dynamically, with error checking. S must be nonzero. */
static inline void *
xnmalloc_inline (size_t n, size_t s)
{
void *p;
if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0))
xalloc_die ();
return p;
}
void *
xnmalloc (size_t n, size_t s)
{
return xnmalloc_inline (n, s);
}
/* Allocate N bytes of memory dynamically, with error checking. */
void *
xmalloc (size_t n)
{
return xnmalloc_inline (n, 1);
}
/* 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_inline (void *p, size_t n, size_t s)
{
if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0))
xalloc_die ();
return p;
}
void *
xnrealloc (void *p, size_t n, size_t s)
{
return xnrealloc_inline (p, n, s);
}
/* Change the size of an allocated block of memory P to N bytes,
with error checking. */
void *
xrealloc (void *p, size_t n)
{
return xnrealloc_inline (p, n, 1);
}
/* 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 doubled so that
repeated reallocations have O(N log N) overall cost rather than
O(N**2) cost, but the specification for this function does not
guarantee that sizes are doubled.
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_inline (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
{
if (SIZE_MAX / 2 / s < n)
xalloc_die ();
n *= 2;
}
*pn = n;
return xrealloc (p, n * s);
}
void *
x2nrealloc (void *p, size_t *pn, size_t s)
{
return x2nrealloc_inline (p, pn, s);
}
/* 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_inline (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. */
if (xalloc_oversized (n, s) || (! (p = calloc (n, s)) && 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);
}

1588
contrib/cpio/src/copyin.c Normal file

File diff suppressed because it is too large Load Diff

803
contrib/cpio/src/copyout.c Normal file
View File

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

464
contrib/cpio/src/copypass.c Normal file
View File

@ -0,0 +1,464 @@
/* copypass.c - cpio copy pass sub-function.
Copyright (C) 1990, 1991, 1992, 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.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
#ifndef HAVE_LCHOWN
#define lchown chown
#endif
/* Copy files listed on the standard input into directory `directory_name'.
If `link_flag', link instead of copying. */
void
process_copy_pass ()
{
dynamic_string input_name; /* Name of file from stdin. */
dynamic_string output_name; /* Name of new file. */
int dirname_len; /* Length of `directory_name'. */
int res; /* Result of functions. */
char *slash; /* For moving past slashes in input name. */
struct utimbuf times; /* For resetting file times after copy. */
struct stat in_file_stat; /* Stat record for input file. */
struct stat out_file_stat; /* Stat record for output file. */
int in_file_des; /* Input file descriptor. */
int out_file_des; /* Output file descriptor. */
int existing_dir; /* True if file is a dir & already exists. */
#ifdef HPUX_CDF
int cdf_flag;
int cdf_char;
#endif
/* Initialize the copy pass. */
dirname_len = strlen (directory_name);
ds_init (&input_name, 128);
ds_init (&output_name, dirname_len + 2);
strcpy (output_name.ds_string, directory_name);
output_name.ds_string[dirname_len] = '/';
output_is_seekable = true;
/* Initialize this in case it has members we don't know to set. */
bzero (&times, sizeof (struct utimbuf));
/* Copy files with names read from stdin. */
while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
{
int link_res = -1;
/* Check for blank line and ignore it if found. */
if (input_name.ds_string[0] == '\0')
{
error (0, 0, _("blank line ignored"));
continue;
}
/* Check for current directory and ignore it if found. */
if (input_name.ds_string[0] == '.'
&& (input_name.ds_string[1] == '\0'
|| (input_name.ds_string[1] == '/'
&& input_name.ds_string[2] == '\0')))
continue;
if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
{
error (0, errno, "%s", input_name.ds_string);
continue;
}
/* Make the name of the new file. */
for (slash = input_name.ds_string; *slash == '/'; ++slash)
;
#ifdef HPUX_CDF
/* For CDF's we add a 2nd `/' after all "hidden" directories.
This kind of a kludge, but it's what we do when creating
archives, and it's easier to do this than to separately
keep track of which directories in a path are "hidden". */
slash = add_cdf_double_slashes (slash);
#endif
ds_resize (&output_name, dirname_len + strlen (slash) + 2);
strcpy (output_name.ds_string + dirname_len + 1, slash);
existing_dir = false;
if (lstat (output_name.ds_string, &out_file_stat) == 0)
{
if (S_ISDIR (out_file_stat.st_mode)
&& S_ISDIR (in_file_stat.st_mode))
{
/* If there is already a directory there that
we are trying to create, don't complain about it. */
existing_dir = true;
}
else if (!unconditional_flag
&& in_file_stat.st_mtime <= out_file_stat.st_mtime)
{
error (0, 0, _("%s not created: newer or same age version exists"),
output_name.ds_string);
continue; /* Go to the next file. */
}
else if (S_ISDIR (out_file_stat.st_mode)
? rmdir (output_name.ds_string)
: unlink (output_name.ds_string))
{
error (0, errno, _("cannot remove current %s"),
output_name.ds_string);
continue; /* Go to the next file. */
}
}
/* Do the real copy or link. */
if (S_ISREG (in_file_stat.st_mode))
{
/* 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)
{
error (0, errno, "%s", input_name.ds_string);
continue;
}
out_file_des = open (output_name.ds_string,
O_CREAT | O_WRONLY | O_BINARY, 0600);
if (out_file_des < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
out_file_des = open (output_name.ds_string,
O_CREAT | O_WRONLY | O_BINARY, 0600);
}
if (out_file_des < 0)
{
error (0, errno, "%s", output_name.ds_string);
close (in_file_des);
continue;
}
copy_files_disk_to_disk (in_file_des, out_file_des, in_file_stat.st_size, input_name.ds_string);
disk_empty_output_buffer (out_file_des);
/* 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;
}
if (close (in_file_des) < 0)
error (0, errno, "%s", input_name.ds_string);
if (close (out_file_des) < 0)
error (0, errno, "%s", output_name.ds_string);
/* Set the attributes of the new file. */
if (!no_chown_flag)
if ((chown (output_name.ds_string,
set_owner_flag ? set_owner : in_file_stat.st_uid,
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
/* chown may have turned off some permissions we wanted. */
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
error (0, errno, "%s", output_name.ds_string);
if (reset_time_flag)
{
times.actime = in_file_stat.st_atime;
times.modtime = in_file_stat.st_mtime;
/* Debian hack: Silently ignore EROFS because
reading the file won't have upset its timestamp
if it's on a read-only filesystem. This has been
submitted as a suggestion to
"bug-gnu-utils@prep.ai.mit.edu". -BEM */
if (utime (input_name.ds_string, &times) < 0
&& errno != EROFS)
error (0, errno, "%s", input_name.ds_string);
if (utime (output_name.ds_string, &times) < 0
&& errno != EROFS)
error (0, errno, "%s", output_name.ds_string);
}
if (retain_time_flag)
{
times.actime = times.modtime = in_file_stat.st_mtime;
if (utime (output_name.ds_string, &times) < 0)
error (0, errno, "%s", output_name.ds_string);
}
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) ) )
{
error (0, errno, "%s", output_name.ds_string);
continue;
}
}
if (!no_chown_flag)
if ((chown (output_name.ds_string,
set_owner_flag ? set_owner : in_file_stat.st_uid,
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
/* chown may have turned off some permissions we wanted. */
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
error (0, errno, "%s", output_name.ds_string);
#ifdef HPUX_CDF
if (cdf_flag)
/* Once we "hide" the directory with the chmod(),
we have to refer to it using name+ isntead of name. */
output_name.ds_string [cdf_char] = '+';
#endif
if (retain_time_flag)
{
times.actime = times.modtime = in_file_stat.st_mtime;
if (utime (output_name.ds_string, &times) < 0)
error (0, errno, "%s", output_name.ds_string);
}
}
else if (S_ISCHR (in_file_stat.st_mode) ||
S_ISBLK (in_file_stat.st_mode) ||
#ifdef S_ISFIFO
S_ISFIFO (in_file_stat.st_mode) ||
#endif
#ifdef S_ISSOCK
S_ISSOCK (in_file_stat.st_mode) ||
#endif
0)
{
/* Can the current file be linked to a another file?
Set link_name to the original file name. */
if (link_flag)
/* User said to link it if possible. */
link_res = link_to_name (output_name.ds_string,
input_name.ds_string);
if ( (link_res < 0) && (in_file_stat.st_nlink > 1) )
link_res = link_to_maj_min_ino (output_name.ds_string,
major (in_file_stat.st_dev),
minor (in_file_stat.st_dev),
in_file_stat.st_ino);
if (link_res < 0)
{
res = mknod (output_name.ds_string, in_file_stat.st_mode,
in_file_stat.st_rdev);
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
res = mknod (output_name.ds_string, in_file_stat.st_mode,
in_file_stat.st_rdev);
}
if (res < 0)
{
error (0, errno, "%s", output_name.ds_string);
continue;
}
if (!no_chown_flag)
if ((chown (output_name.ds_string,
set_owner_flag ? set_owner : in_file_stat.st_uid,
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
/* chown may have turned off some permissions we wanted. */
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
error (0, errno, "%s", output_name.ds_string);
if (retain_time_flag)
{
times.actime = times.modtime = in_file_stat.st_mtime;
if (utime (output_name.ds_string, &times) < 0)
error (0, errno, "%s", output_name.ds_string);
}
}
}
#ifdef S_ISLNK
else if (S_ISLNK (in_file_stat.st_mode))
{
char *link_name;
int link_size;
link_name = (char *) xmalloc ((unsigned int) in_file_stat.st_size + 1);
link_size = readlink (input_name.ds_string, link_name,
in_file_stat.st_size);
if (link_size < 0)
{
error (0, errno, "%s", input_name.ds_string);
free (link_name);
continue;
}
link_name[link_size] = '\0';
res = UMASKED_SYMLINK (link_name, output_name.ds_string,
in_file_stat.st_mode);
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
res = UMASKED_SYMLINK (link_name, output_name.ds_string,
in_file_stat.st_mode);
}
if (res < 0)
{
error (0, errno, "%s", output_name.ds_string);
free (link_name);
continue;
}
/* Set the attributes of the new link. */
if (!no_chown_flag)
if ((lchown (output_name.ds_string,
set_owner_flag ? set_owner : in_file_stat.st_uid,
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
free (link_name);
}
#endif
else
{
error (0, 0, _("%s: unknown file type"), input_name.ds_string);
}
if (verbose_flag)
fprintf (stderr, "%s\n", output_name.ds_string);
if (dot_flag)
fputc ('.', stderr);
}
if (dot_flag)
fputc ('\n', stderr);
if (!quiet_flag)
{
res = (output_bytes + io_block_size - 1) / io_block_size;
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"),
link_target, link_name);
}
return res;
}

69
contrib/cpio/src/cpio.h Normal file
View File

@ -0,0 +1,69 @@
/* Extended cpio format from POSIX.1.
Copyright (C) 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _CPIO_H
#define _CPIO_H 1
/* A cpio archive consists of a sequence of files.
Each file has a 76 byte header,
a variable length, NUL terminated filename,
and variable length file data.
A header for a filename "TRAILER!!!" indicates the end of the archive. */
/* All the fields in the header are ISO 646 (approximately ASCII) strings
of octal numbers, left padded, not NUL terminated.
Field Name Length in Bytes Notes
c_magic 6 must be "070707"
c_dev 6
c_ino 6
c_mode 6 see below for value
c_uid 6
c_gid 6
c_nlink 6
c_rdev 6 only valid for chr and blk special files
c_mtime 11
c_namesize 6 count includes terminating NUL in pathname
c_filesize 11 must be 0 for FIFOs and directories */
/* Values for c_mode, OR'd together: */
#define C_IRUSR 000400
#define C_IWUSR 000200
#define C_IXUSR 000100
#define C_IRGRP 000040
#define C_IWGRP 000020
#define C_IXGRP 000010
#define C_IROTH 000004
#define C_IWOTH 000002
#define C_IXOTH 000001
#define C_ISUID 004000
#define C_ISGID 002000
#define C_ISVTX 001000
#define C_ISBLK 060000
#define C_ISCHR 020000
#define C_ISDIR 040000
#define C_ISFIFO 010000
#define C_ISSOCK 0140000
#define C_ISLNK 0120000
#define C_ISCTG 0110000
#define C_ISREG 0100000
#endif /* cpio.h */

View File

@ -0,0 +1,90 @@
/* Extended cpio header from POSIX.1.
Copyright (C) 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _CPIOHDR_H
#define _CPIOHDR_H 1
#include <cpio.h>
struct old_cpio_header
{
unsigned short c_magic;
short c_dev;
unsigned short c_ino;
unsigned short c_mode;
unsigned short c_uid;
unsigned short c_gid;
unsigned short c_nlink;
short c_rdev;
unsigned short c_mtimes[2];
unsigned short c_namesize;
unsigned short c_filesizes[2];
unsigned long c_mtime; /* Long-aligned copy of `c_mtimes'. */
unsigned long c_filesize; /* Long-aligned copy of `c_filesizes'. */
char *c_name;
};
/* "New" portable format and CRC format:
Each file has a 110 byte header,
a variable length, NUL terminated filename,
and variable length file data.
A header for a filename "TRAILER!!!" indicates the end of the archive. */
/* All the fields in the header are ISO 646 (approximately ASCII) strings
of hexadecimal numbers, left padded, not NUL terminated.
Field Name Length in Bytes Notes
c_magic 6 "070701" for "new" portable format
"070702" for CRC format
c_ino 8
c_mode 8
c_uid 8
c_gid 8
c_nlink 8
c_mtime 8
c_filesize 8 must be 0 for FIFOs and directories
c_maj 8
c_min 8
c_rmaj 8 only valid for chr and blk special files
c_rmin 8 only valid for chr and blk special files
c_namesize 8 count includes terminating NUL in pathname
c_chksum 8 0 for "new" portable format; for CRC format
the sum of all the bytes in the file */
struct new_cpio_header
{
unsigned short c_magic;
unsigned long c_ino;
unsigned long c_mode;
unsigned long c_uid;
unsigned long c_gid;
unsigned long c_nlink;
unsigned long c_mtime;
unsigned long c_filesize;
long c_dev_maj;
long c_dev_min;
long c_rdev_maj;
long c_rdev_min;
unsigned long c_namesize;
unsigned long c_chksum;
char *c_name;
char *c_tar_linkname;
};
#endif /* cpiohdr.h */

42
contrib/cpio/src/defer.c Normal file
View File

@ -0,0 +1,42 @@
/* defer.c - handle "defered" links in newc and crc archives
Copyright (C) 1993,2003,2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <system.h>
#include <stdio.h>
#include <sys/types.h>
#include "cpiohdr.h"
#include "extern.h"
#include "defer.h"
struct deferment *
create_deferment (struct new_cpio_header *file_hdr)
{
struct deferment *d;
d = (struct deferment *) xmalloc (sizeof (struct deferment) );
d->header = *file_hdr;
d->header.c_name = (char *) xmalloc (strlen (file_hdr->c_name) + 1);
strcpy (d->header.c_name, file_hdr->c_name);
return d;
}
void
free_deferment (struct deferment *d)
{
free (d->header.c_name);
free (d);
}

25
contrib/cpio/src/defer.h Normal file
View File

@ -0,0 +1,25 @@
/* defer.h
Copyright (C) 1993, 2001, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
struct deferment
{
struct deferment *next;
struct new_cpio_header header;
};
struct deferment *create_deferment P_((struct new_cpio_header *file_hdr));
void free_deferment P_((struct deferment *d));

107
contrib/cpio/src/dstring.c Normal file
View File

@ -0,0 +1,107 @@
/* 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.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, 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"
#if __STDC__
# define P_(s) s
#else
# define P_(s) ()
#endif
char *xmalloc P_((unsigned n));
char *xrealloc P_((char *p, unsigned n));
/* Initialiaze dynamic string STRING with space for SIZE characters. */
void
ds_init (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');
}

View File

@ -0,0 +1,49 @@
/* 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.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, 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);

200
contrib/cpio/src/extern.h Normal file
View File

@ -0,0 +1,200 @@
/* extern.h - External declarations for cpio. Requires system.h.
Copyright (C) 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
enum archive_format
{
arf_unknown, arf_binary, arf_oldascii, arf_newascii, arf_crcascii,
arf_tar, arf_ustar, arf_hpoldascii, arf_hpbinary
};
extern enum archive_format archive_format;
extern int reset_time_flag;
extern int io_block_size;
extern int create_dir_flag;
extern int rename_flag;
extern char *rename_batch_file;
extern int table_flag;
extern int unconditional_flag;
extern int verbose_flag;
extern int dot_flag;
extern int link_flag;
extern int retain_time_flag;
extern int crc_i_flag;
extern int append_flag;
extern int swap_bytes_flag;
extern int swap_halfwords_flag;
extern int swapping_bytes;
extern int swapping_halfwords;
extern int set_owner_flag;
extern uid_t set_owner;
extern int set_group_flag;
extern gid_t set_group;
extern int no_chown_flag;
extern int sparse_flag;
extern int quiet_flag;
extern int only_verify_crc_flag;
extern int no_abs_paths_flag;
extern 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 long 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 zeros_512[];
extern char *directory_name;
extern char **save_patterns;
extern int num_patterns;
extern char name_end;
extern char input_is_special;
extern char output_is_special;
extern char input_is_seekable;
extern char output_is_seekable;
extern char *program_name;
extern int (*xstat) ();
extern void (*copy_function) ();
#if defined PROTOTYPES || (defined __STDC__ && __STDC__)
# define P_(s) s
#else
# define P_(s) ()
#endif
/* copyin.c */
void warn_junk_bytes P_((long bytes_skipped));
void read_in_header P_((struct new_cpio_header *file_hdr, int in_des));
void read_in_old_ascii P_((struct new_cpio_header *file_hdr, int in_des));
void read_in_new_ascii P_((struct new_cpio_header *file_hdr, int in_des));
void read_in_binary P_((struct new_cpio_header *file_hdr, int in_des));
void swab_array P_((char *arg, int count));
void process_copy_in P_((void));
void long_format P_((struct new_cpio_header *file_hdr, char *link_name));
void print_name_with_quoting P_((char *p));
/* copyout.c */
void write_out_header P_((struct new_cpio_header *file_hdr, int out_des));
void process_copy_out P_((void));
/* copypass.c */
void process_copy_pass P_((void));
int link_to_maj_min_ino P_((char *file_name, int st_dev_maj,
int st_dev_min, int st_ino));
int link_to_name P_((char *link_name, char *link_target));
/* dirname.c */
char *dirname P_((char *path));
/* filemode.c */
void mode_string P_((unsigned int mode, char *str));
/* idcache.c */
#ifndef __MSDOS__
char *getgroup ();
char *getuser ();
uid_t *getuidbyname ();
gid_t *getgidbyname ();
#endif
/* main.c */
void process_args P_((int argc, char *argv[]));
void initialize_buffers P_((void));
/* makepath.c */
int make_path P_((char *argpath, int mode, int parent_mode,
uid_t owner, gid_t group, char *verbose_fmt_string));
/* tar.c */
void write_out_tar_header P_((struct new_cpio_header *file_hdr, int out_des));
int null_block P_((long *block, int size));
void read_in_tar_header P_((struct new_cpio_header *file_hdr, int in_des));
int otoa P_((char *s, unsigned long *n));
int is_tar_header P_((char *buf));
int is_tar_filename_too_long P_((char *name));
/* userspec.c */
#ifndef __MSDOS__
char *parse_user_spec P_((char *name, uid_t *uid, gid_t *gid,
char **username, char **groupname));
#endif
/* util.c */
void tape_empty_output_buffer P_((int out_des));
void disk_empty_output_buffer P_((int out_des));
void swahw_array P_((char *ptr, int count));
void tape_buffered_write P_((char *in_buf, int out_des, long num_bytes));
void tape_buffered_read P_((char *in_buf, int in_des, long num_bytes));
int tape_buffered_peek P_((char *peek_buf, int in_des, int num_bytes));
void tape_toss_input P_((int in_des, long num_bytes));
void copy_files_tape_to_disk P_((int in_des, int out_des, long num_bytes));
void copy_files_disk_to_tape P_((int in_des, int out_des, long num_bytes, char *filename));
void copy_files_disk_to_disk P_((int in_des, int out_des, long num_bytes, char *filename));
void warn_if_file_changed P_((char *file_name, unsigned long old_file_size,
unsigned long old_file_mtime));
void create_all_directories P_((char *name));
void prepare_append P_((int out_file_des));
char *find_inode_file P_((unsigned long node_num,
unsigned long major_num, unsigned long minor_num));
void add_inode P_((unsigned long node_num, char *file_name,
unsigned long major_num, unsigned long minor_num));
int open_archive P_((char *file));
void tape_offline P_((int tape_des));
void get_next_reel P_((int tape_des));
void set_new_media_message P_((char *message));
#if defined(__MSDOS__) && !defined(__GNUC__)
int chown P_((char *path, int owner, int group));
#endif
#ifdef __TURBOC__
int utime P_((char *filename, struct utimbuf *utb));
#endif
#ifdef HPUX_CDF
char *add_cdf_double_slashes P_((char *filename));
#endif
#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 */

242
contrib/cpio/src/filemode.c Normal file
View File

@ -0,0 +1,242 @@
/* 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.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, 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);
}

View File

@ -0,0 +1,84 @@
/* filetypes.h - deal with POSIX annoyances
Copyright (C) 1991 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ();

203
contrib/cpio/src/global.c Normal file
View File

@ -0,0 +1,203 @@
/* global.c - global variables and initial values for cpio.
Copyright (C) 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#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 no_abs_paths_flag = false;
#ifdef DEBUG_CPIO
/* If true, print debugging information. */
int debug_flag = false;
#endif
/* File position of last header read. Only used during -A to determine
where the old TRAILER!!! record started. */
int last_header_start = 0;
/* With -i; if true, copy only files that match any of the given patterns;
if false, copy only files that do not match any of the patterns. (-f) */
int copy_matching_files = true;
/* With -itv; if true, list numeric uid and gid instead of translating them
into names. */
int numeric_uid = false;
/* Name of file containing additional patterns (-E). */
char *pattern_file_name = NULL;
/* Message to print when end of medium is reached (-M). */
char *new_media_message = NULL;
/* With -M with %d, message to print when end of medium is reached. */
char *new_media_message_with_number = NULL;
char *new_media_message_after_number = NULL;
/* File descriptor containing the archive. */
int archive_des;
/* Name of file containing the archive, if known; NULL if stdin/out. */
char *archive_name = NULL;
/* Name of the remote shell command, if known; NULL otherwise. */
char *rsh_command_option = NULL;
/* CRC checksum. */
unsigned long crc;
/* Input and output buffers. */
char *input_buffer, *output_buffer;
/* The size of the input buffer. */
long input_buffer_size;
/* Current locations in `input_buffer' and `output_buffer'. */
char *in_buff, *out_buff;
/* Current number of bytes stored at `input_buff' and `output_buff'. */
long input_size, output_size;
/* Total number of bytes read and written for all files.
Now that many tape drives hold more than 4Gb we need more than 32
bits to hold input_bytes and output_bytes. But it's not worth
the trouble of adding special multi-precision arithmetic if the
compiler doesn't support 64 bit ints since input_bytes and
output_bytes are only used to print the number of blocks copied. */
#ifdef __GNUC__
long long input_bytes, output_bytes;
#else
long input_bytes, output_bytes;
#endif
/* 512 bytes of 0; used for various padding operations. */
char zeros_512[512];
/* Saving of argument values for later reference. */
char *directory_name = NULL;
char **save_patterns;
int num_patterns;
/* Character that terminates file names read from stdin. */
char name_end = '\n';
/* true if input (cpio -i) or output (cpio -o) is a device node. */
char input_is_special = false;
char output_is_special = false;
/* true if lseek works on the input. */
char input_is_seekable = false;
/* true if lseek works on the output. */
char output_is_seekable = false;
/* 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;

206
contrib/cpio/src/idcache.c Normal file
View File

@ -0,0 +1,206 @@
/* idcache.c -- map user and group IDs, cached for speed
Copyright (C) 1985, 1988, 1989, 1990, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#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;
}

763
contrib/cpio/src/main.c Normal file
View File

@ -0,0 +1,763 @@
/* main.c - main program and argument processing for cpio.
Copyright (C) 1990, 1991, 1992, 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.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 <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 <localedir.h>
enum cpio_options {
NO_ABSOLUTE_FILENAMES_OPTION=256,
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,
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 USAGE_ERROR(args) do { error args; exit(2); } while (0)
#define CHECK_USAGE(cond, opt, mode_opt) \
if (cond) USAGE_ERROR((0, 0, _("%s is meaningless with %s"), opt, mode_opt));
static struct argp_option options[] = {
{NULL, 0, NULL, 0,
N_("Main operation mode:"), 10},
{"create", 'o', 0, 0,
N_("Create the archive (run in copy-out mode)"), 10},
{"extract", 'i', 0, 0,
N_("Extract files from an archive (run in copy-in mode)")},
{"pass-through", 'p', 0, 0,
N_("Run in copy-pass mode"), 10},
{"list", 't', 0, 0,
N_("Print a table of contents of the input"), 10},
{NULL, 0, NULL, 0,
N_("Operation modifiers valid in any mode:"), 100},
{"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"), 110},
{"force-local", FORCE_LOCAL_OPTION, 0, 0,
N_("Archive file is local, even if its name contains colons"), 110},
{"format", 'H', N_("FORMAT"), 0,
N_("Use given archive FORMAT"), 110},
{NULL, 'B', NULL, 0,
N_("Set the I/O block size to 5120 bytes"), 110},
{"block-size", BLOCK_SIZE_OPTION, N_("BLOCK-SIZE"), 0,
N_("Set the I/O block size to BLOCK-SIZE * 512 bytes"), 110},
{NULL, 'c', NULL, 0,
N_("Use the old portable (ASCII) archive format"), 0},
{"dot", 'V', NULL, 0,
N_("Print a \".\" for each file processed"), 110},
{"io-size", 'C', N_("NUMBER"), 0,
N_("Set the I/O block size to the given NUMBER of bytes"), 110},
{"message", 'M', N_("STRING"), 0,
N_("Print STRING when the end of a volume of the backup media is reached"),
110},
{"nonmatching", 'f', 0, 0,
N_("Only copy files that do not match any of the given patterns"), 110},
{"numeric-uid-gid", 'n', 0, 0,
N_("In the verbose table of contents listing, show numeric UID and GID"),
110},
{"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
N_("Use remote COMMAND instead of rsh"), 110},
{"quiet", QUIET_OPTION, NULL, 0,
N_("Do not print the number of blocks copied"), 110},
{"verbose", 'v', NULL, 0,
N_("Verbosely list the files processed"), 110},
#ifdef DEBUG_CPIO
{"debug", DEBUG_OPTION, NULL, 0,
N_("Enable debugging info"), 110},
#endif
{"warning", 'W', N_("FLAG"), 0,
N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), 110 },
/* ********** */
{NULL, 0, NULL, 0,
N_("Operation modifiers valid only in copy-in mode:"), 200},
{"pattern-file", 'E', N_("FILE"), 0,
N_("In copy-in mode, read additional patterns specifying filenames to extract or list from FILE"), 210},
{"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
N_("Create all files relative to the current directory"), 210},
{"only-verify-crc", ONLY_VERIFY_CRC_OPTION, 0, 0,
N_("When reading a CRC format archive in copy-in mode, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
{"rename", 'r', 0, 0,
N_("Interactively rename files"), 210},
{"rename-batch-file", RENAME_BATCH_FILE_OPTION, N_("FILE"), OPTION_HIDDEN,
"", 210},
{"swap", 'b', NULL, 0,
N_("Swap both halfwords of words and bytes of halfwords in the data. Equivalent to -sS"), 210},
{"swap-bytes", 's', NULL, 0,
N_("Swap the bytes of each halfword in the files"), 210},
{"swap-halfwords", 'S', NULL, 0,
N_("Swap the halfwords of each word (4 bytes) in the files"),
210},
{"to-stdout", TO_STDOUT_OPTION, NULL, 0,
N_("Extract files to standard output"), 210},
/* ********** */
{NULL, 0, NULL, 0,
N_("Operation modifiers valid only in copy-out mode:"), 300},
{"append", 'A', 0, 0,
N_("Append to an existing archive."), 310 },
{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"), 310},
/* ********** */
{NULL, 0, NULL, 0,
N_("Operation modifiers valid only in copy-pass mode:"), 400},
{"link", 'l', 0, 0,
N_("Link files instead of copying them, when possible"), 410},
/* ********** */
{NULL, 0, NULL, 0,
N_("Operation modifiers valid for copy-out and copy-pass modes:"), 500},
{"null", '0', 0, 0,
N_("A list of filenames is terminated by a null character instead of a newline"), 510 },
{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"), 510},
{"dereference", 'L', 0, 0,
N_("Dereference symbolic links (copy the files that they point to instead of copying the links)."), 510},
{"owner", 'R', N_("[USER][:.][GROUP]"), 0,
N_("Set the ownership of all files created to the specified USER and/or GROUP"), 510},
{"sparse", SPARSE_OPTION, NULL, 0,
N_("Write files with large blocks of zeros as sparse files"), 510},
{"reset-access-time", 'a', NULL, 0,
N_("Reset the access times of files after reading them"), 510},
/* ********** */
{NULL, 0, NULL, 0,
N_("Operation modifiers valid for copy-in and copy-pass modes:"), 600},
{"preserve-modification-time", 'm', 0, 0,
N_("Retain previous file modification times when creating files"), 610},
{"make-directories", 'd', 0, 0,
N_("Create leading directories where needed"), 610},
{"no-preserve-owner", NO_PRESERVE_OWNER_OPTION, 0, 0,
N_("Do not change the ownership of the files"), 610},
{"unconditional", 'u', NULL, 0,
N_("Replace all files unconditionally"), 610},
{NULL, 0, NULL, 0,
N_("Informative options:"), 700 },
{"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 */
{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\n"
" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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)
{
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)
USAGE_ERROR ((0, 0, _("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)
USAGE_ERROR ((0, 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)
USAGE_ERROR ((0, 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 */
no_abs_paths_flag = true;
break;
case NO_PRESERVE_OWNER_OPTION: /* --no-preserve-owner */
if (set_owner_flag || set_group_flag)
USAGE_ERROR ((0, 0,
_("--no-preserve-owner cannot be used with --owner")));
no_chown_flag = true;
break;
case 'o': /* Copy-out mode. */
if (copy_function != 0)
USAGE_ERROR ((0, 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)
USAGE_ERROR ((0, 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)
USAGE_ERROR ((0, 0,
_("--owner cannot be used with --no-preserve-owner")));
{
char *e, *u, *g;
e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
if (e)
error (2, 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 '?':
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)
USAGE_ERROR ((0, 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
USAGE_ERROR ((0, 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(sparse_flag, "--sparse", "--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)
USAGE_ERROR((0, 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)
USAGE_ERROR ((0, 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(retain_time_flag, "--preserve-modification-time",
"--create");
CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--create");
CHECK_USAGE(set_owner_flag||set_group_flag, "--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))
USAGE_ERROR ((0, 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(no_abs_paths_flag, "--no-absolute-pathnames", "--create");
CHECK_USAGE(input_archive_name, "-I", "--create");
if (archive_name && output_archive_name)
USAGE_ERROR ((0, 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)
USAGE_ERROR ((0, 0, _("Too many arguments")));
if (archive_format != arf_unknown)
USAGE_ERROR((0, 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(no_abs_paths_flag, "--no-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)
USAGE_ERROR ((0, 0,
_("-F can be used only with --create or --extract")));
archive_des = open_archive (archive_name);
if (archive_des < 0)
error (1, errno, "%s", 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;
/* Clear the block of zeros. */
bzero (zeros_512, 512);
}
int
main (int argc, char *argv[])
{
#ifdef HAVE_LOCALE_H
setlocale (LC_ALL, "");
#endif
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
program_name = argv[0];
umask (0);
#ifdef __TURBOC__
_fmode = O_BINARY; /* Put stdin and stdout in binary mode. */
#endif
#ifdef __EMX__ /* gcc on OS/2. */
_response (&argc, &argv);
_wildcard (&argc, &argv);
#endif
process_args (argc, argv);
initialize_buffers ();
(*copy_function) ();
if (archive_des >= 0 && rmtclose (archive_des) == -1)
error (1, errno, _("error closing archive"));
exit (0);
}

301
contrib/cpio/src/makepath.c Normal file
View File

@ -0,0 +1,301 @@
/* makepath.c -- Ensure that a directory path exists.
Copyright (C) 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, 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>
#ifdef __GNUC__
#define alloca __builtin_alloca
#else
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#else
#ifdef _AIX
#pragma alloca
#else
char *alloca ();
#endif
#endif
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if !defined(S_ISDIR) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#include <errno.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#else
extern int errno;
#endif
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
#include <string.h>
#ifndef index
#define index strchr
#endif
#else
#include <strings.h>
#endif
/* 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 = index (slash, '/')))
{
#ifdef HPUX_CDF
int iscdf;
iscdf = 0;
#endif
*slash = '\0';
if (stat (dirpath, &stats))
{
#ifdef HPUX_CDF
/* If this component of the pathname ends in `+' and is
followed by 2 `/'s, then this is a CDF. We remove the
`+' from the name and create the directory. Later
we will "hide" the directory. */
if ( (*(slash +1) == '/') && (*(slash -1) == '+') )
{
iscdf = 1;
*(slash -1) = '\0';
}
#endif
if (mkdir (dirpath, tmp_mode))
{
error (0, errno, _("cannot make directory `%s'"), dirpath);
umask (oldmask);
return 1;
}
else
{
if (verbose_fmt_string != NULL)
error (0, 0, verbose_fmt_string, dirpath);
if (owner != (uid_t) -1 && group != (gid_t) -1
&& chown (dirpath, owner, group)
#ifdef AFS
&& errno != EPERM
#endif
)
{
error (0, errno, "%s", dirpath);
retval = 1;
}
if (re_protect)
{
struct ptr_list *new = (struct ptr_list *)
alloca (sizeof (struct ptr_list));
new->dirname_end = slash;
new->next = leading_dirs;
leading_dirs = new;
}
#ifdef HPUX_CDF
if (iscdf)
{
/* If this is a CDF, "hide" the directory by setting
its hidden/setuid bit. Also add the `+' back to
its name (since once it's "hidden" we must refer
to as `name+' instead of `name'). */
chmod (dirpath, 04700);
*(slash - 1) = '+';
}
#endif
}
}
else if (!S_ISDIR (stats.st_mode))
{
error (0, 0, _("`%s' exists but is not a directory"), dirpath);
umask (oldmask);
return 1;
}
*slash++ = '/';
/* Avoid unnecessary calls to `stat' when given
pathnames containing multiple adjacent slashes. */
while (*slash == '/')
slash++;
}
/* We're done making leading directories.
Make the final component of the path. */
if (mkdir (dirpath, mode))
{
/* In some cases, if the final component in dirpath was `.' then we
just got an EEXIST error from that last mkdir(). If that's
the case, ignore it. */
if ( (errno != EEXIST) ||
(stat (dirpath, &stats) != 0) ||
(!S_ISDIR (stats.st_mode) ) )
{
error (0, errno, _("cannot make directory `%s'"), dirpath);
umask (oldmask);
return 1;
}
}
if (verbose_fmt_string != NULL)
error (0, 0, verbose_fmt_string, dirpath);
if (owner != (uid_t) -1 && group != (gid_t) -1)
{
if (chown (dirpath, owner, group)
#ifdef AFS
&& errno != EPERM
#endif
)
{
error (0, errno, "%s", dirpath);
retval = 1;
}
}
/* chown may have turned off some permission bits we wanted. */
if ((mode & 07000) != 0 && chmod (dirpath, mode))
{
error (0, errno, "%s", dirpath);
retval = 1;
}
/* If the mode for leading directories didn't include owner "wx"
privileges, we have to reset their protections to the correct
value. */
for (p = leading_dirs; p != NULL; p = p->next)
{
*(p->dirname_end) = '\0';
#if 0
/* cpio always calls make_path with parent mode 0700, so
we don't have to do this. If we ever do have to do this,
we have to stat the directory first to get the setuid
bit so we don't break HP CDF's. */
if (chmod (dirpath, parent_mode))
{
error (0, errno, "%s", dirpath);
retval = 1;
}
#endif
}
}
else
{
/* We get here if the entire path already exists. */
if (!S_ISDIR (stats.st_mode))
{
error (0, 0, _("`%s' exists but is not a directory"), dirpath);
umask (oldmask);
return 1;
}
/* chown must precede chmod because on some systems,
chown clears the set[ug]id bits for non-superusers,
resulting in incorrect permissions.
On System V, users can give away files with chown and then not
be able to chmod them. So don't give files away. */
if (owner != (uid_t) -1 && group != (gid_t) -1
&& chown (dirpath, owner, group)
#ifdef AFS
&& errno != EPERM
#endif
)
{
error (0, errno, "%s", dirpath);
retval = 1;
}
if (chmod (dirpath, mode))
{
error (0, errno, "%s", dirpath);
retval = 1;
}
}
umask (oldmask);
return retval;
}

View File

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

500
contrib/cpio/src/tar.c Normal file
View File

@ -0,0 +1,500 @@
/* tar.c - read in write tar headers for cpio
Copyright (C) 1992, 2001, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#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 long
tar_checksum (struct tar_header *tar_hdr)
{
unsigned long sum = 0;
char *p = (char *) tar_hdr;
char *q = p + TARRECORDSIZE;
int i;
while (p < tar_hdr->chksum)
sum += *p++ & 0xff;
for (i = 0; i < 8; ++i)
{
sum += ' ';
++p;
}
while (p < q)
sum += *p++ & 0xff;
return sum;
}
/* Write out header FILE_HDR, including the file name, to file
descriptor OUT_DES. */
void
write_out_tar_header (struct new_cpio_header *file_hdr, int out_des)
{
int name_len;
union tar_record tar_rec;
struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
bzero ((char *) &tar_rec, TARRECORDSIZE);
/* process_copy_out must ensure that file_hdr->c_name is short enough,
or we will lose here. */
name_len = strlen (file_hdr->c_name);
if (name_len <= TARNAMESIZE)
{
strncpy (tar_hdr->name, file_hdr->c_name, name_len);
}
else
{
/* Fit as much as we can into `name', the rest into `prefix'. */
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 new_cpio_header *file_hdr, int in_des)
{
long bytes_skipped = 0;
int warned = false;
union tar_record tar_rec;
struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
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 = "TRAILER!!!";
return;
}
#if 0
bytes_skipped = TARRECORDSIZE;
#endif
}
while (1)
{
otoa (tar_hdr->chksum, &file_hdr->c_chksum);
if (file_hdr->c_chksum != tar_checksum (tar_hdr))
{
/* If the checksum is bad, skip 1 byte and try again. When
we try again we do not look for an EOF record (all zeros),
because when we start skipping bytes in a corrupted archive
the chances are pretty good that we might stumble across
2 blocks of 512 zeros (that probably is not really the last
record) and it is better to miss the EOF and give the user
a "premature EOF" error than to give up too soon on a corrupted
archive. */
if (!warned)
{
error (0, 0, _("invalid header: checksum error"));
warned = true;
}
bcopy (((char *) &tar_rec) + 1, (char *) &tar_rec,
TARRECORDSIZE - 1);
tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
++bytes_skipped;
continue;
}
if (archive_format != arf_ustar)
file_hdr->c_name = stash_tar_filename (NULL, tar_hdr->name);
else
file_hdr->c_name = stash_tar_filename (tar_hdr->prefix, tar_hdr->name);
file_hdr->c_nlink = 1;
otoa (tar_hdr->mode, &file_hdr->c_mode);
file_hdr->c_mode = file_hdr->c_mode & 07777;
/* 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
otoa (tar_hdr->uid, &file_hdr->c_uid);
if (archive_format == arf_ustar && !numeric_uid
&& (gidp = getgidbyname (tar_hdr->gname)))
file_hdr->c_gid = *gidp;
else
otoa (tar_hdr->gid, &file_hdr->c_gid);
otoa (tar_hdr->size, &file_hdr->c_filesize);
otoa (tar_hdr->mtime, &file_hdr->c_mtime);
otoa (tar_hdr->devmajor, (unsigned long *) &file_hdr->c_rdev_maj);
otoa (tar_hdr->devminor, (unsigned long *) &file_hdr->c_rdev_min);
file_hdr->c_tar_linkname = NULL;
switch (tar_hdr->typeflag)
{
case REGTYPE:
case CONTTYPE: /* For now, punt. */
default:
file_hdr->c_mode |= CP_IFREG;
break;
case DIRTYPE:
file_hdr->c_mode |= CP_IFDIR;
break;
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;
}
break;
}
if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped);
}
/* Convert the string of octal digits S into a number and store
it in *N. Return nonzero if the whole string was converted,
zero if there was something after the number.
Skip leading and trailing spaces. */
int
otoa (char *s, unsigned long *n)
{
unsigned long val = 0;
while (*s == ' ')
++s;
while (*s >= '0' && *s <= '7')
val = 8 * val + *s++ - '0';
while (*s == ' ')
++s;
*n = val;
return *s == '\0';
}
/* 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;
otoa (tar_hdr->chksum, &chksum);
if (chksum != tar_checksum (tar_hdr))
return 0;
/* GNU tar 1.10 and previous set the magic field to be "ustar " instead
of "ustar\0". Only look at the first 5 characters of the magic
field so we can recognize old GNU tar ustar archives. */
if (!strncmp (tar_hdr->magic, TMAGIC, TMAGLEN - 1))
return 2;
return 1;
}
/* Return true if the filename is too long to fit in a tar header.
For old tar headers, if the filename's length is less than or equal
to 100 then it will fit, otherwise it will not. For POSIX tar headers,
if the filename's length is less than or equal to 100 then it
will definitely fit, and if it is greater than 256 then it
will definitely not fit. If the length is between 100 and 256,
then the filename will fit only if it is possible to break it
into a 155 character "prefix" and 100 character "name". There
must be a slash between the "prefix" and the "name", although
the slash is not stored or counted in either the "prefix" or
the "name", and there must be at least one character in both
the "prefix" and the "name". If it is not possible to break down
the filename like this then it will not fit. */
int
is_tar_filename_too_long (char *name)
{
int whole_name_len;
int prefix_name_len;
char *p;
whole_name_len = strlen (name);
if (whole_name_len <= TARNAMESIZE)
return false;
if (archive_format != arf_ustar)
return true;
if (whole_name_len > TARNAMESIZE + TARPREFIXSIZE + 1)
return true;
/* See whether we can split up the name into acceptably-sized
`prefix' and `name' (`p') pieces. */
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;
}

112
contrib/cpio/src/tar.h Normal file
View File

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

62
contrib/cpio/src/tarhdr.h Normal file
View File

@ -0,0 +1,62 @@
/* Extended tar header from POSIX.1.
Copyright (C) 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _TARHDR_H
#define _TARHDR_H 1
#include <tar.h>
/* Size of `name' field. */
#define TARNAMESIZE 100
/* Size of `linkname' field. */
#define TARLINKNAMESIZE 100
/* Size of `prefix' field. */
#define TARPREFIXSIZE 155
/* Size of entire tar header. */
#define TARRECORDSIZE 512
struct tar_header
{
char name[TARNAMESIZE];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag;
char linkname[TARLINKNAMESIZE];
char magic[6];
char version[2];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char prefix[TARPREFIXSIZE];
};
union tar_record
{
struct tar_header header;
char buffer[TARRECORDSIZE];
};
#endif /* tarhdr.h */

257
contrib/cpio/src/userspec.c Normal file
View File

@ -0,0 +1,257 @@
/* userspec.c -- Parse a user and group string.
Copyright (C) 1989, 1990, 1991, 1992, 2001, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#include <system.h>
#ifdef __GNUC__
#define alloca __builtin_alloca
#else
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#else
#ifdef _AIX
#pragma alloca
#else
char *alloca ();
#endif
#endif
#endif
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#if !HAVE_DECL_GETPWNAM
extern struct passwd *getpwnam (const char *name);
#endif
#if !HAVE_DECL_GETGRNAM
extern struct group *getgrnam (const char *name);
#endif
#if !HAVE_DECL_GETGRGID
extern struct group *getgrgid (gid_t gid);
#endif
#ifndef HAVE_ENDPWENT
# define endpwent()
#endif
#ifndef HAVE_ENDGRENT
# define endgrent()
#endif
/* Perform the equivalent of the statement `dest = strdup (src);',
but obtaining storage via alloca instead of from the heap. */
#define V_STRDUP(dest, src) \
do \
{ \
int _len = strlen ((src)); \
(dest) = (char *) alloca (_len + 1); \
strcpy (dest, src); \
} \
while (0)
/* Return nonzero if STR represents an unsigned decimal integer,
otherwise return 0. */
static int
isnumber (const char *str)
{
for (; *str; str++)
if (!isdigit (*str))
return 0;
return 1;
}
/* Extract from NAME, which has the form "[user][:.][group]",
a USERNAME, UID U, GROUPNAME, and GID G.
Either user or group, or both, must be present.
If the group is omitted but the ":" or "." separator is given,
use the given user's login group.
USERNAME and GROUPNAME will be in newly malloc'd memory.
Either one might be NULL instead, indicating that it was not
given and the corresponding numeric ID was left unchanged.
Return NULL if successful, a static error message string if not. */
const char *
parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
char **username_arg, char **groupname_arg)
{
static const char *tired = "virtual memory exhausted";
const char *error_msg;
char *spec; /* A copy we can write on. */
struct passwd *pwd;
struct group *grp;
char *g, *u, *separator;
char *groupname;
error_msg = NULL;
*username_arg = *groupname_arg = NULL;
groupname = NULL;
V_STRDUP (spec, spec_arg);
/* Find the separator if there is one. */
separator = index (spec, ':');
if (separator == NULL)
separator = index (spec, '.');
/* Replace separator with a NUL. */
if (separator != NULL)
*separator = '\0';
/* Set U and G to non-zero length strings corresponding to user and
group specifiers or to NULL. */
u = (*spec == '\0' ? NULL : spec);
g = (separator == NULL || *(separator + 1) == '\0'
? NULL
: separator + 1);
if (u == NULL && g == NULL)
return "can not omit both user and group";
if (u != NULL)
{
pwd = getpwnam (u);
if (pwd == NULL)
{
if (!isnumber (u))
error_msg = _("invalid user");
else
{
int use_login_group;
use_login_group = (separator != NULL && g == NULL);
if (use_login_group)
error_msg = _("cannot get the login group of a numeric UID");
else
*uid = atoi (u);
}
}
else
{
*uid = pwd->pw_uid;
if (g == NULL && separator != NULL)
{
/* A separator was given, but a group was not specified,
so get the login group. */
*gid = pwd->pw_gid;
grp = getgrgid (pwd->pw_gid);
if (grp == NULL)
{
/* This is enough room to hold the unsigned decimal
representation of any 32-bit quantity and the trailing
zero byte. */
char uint_buf[21];
sprintf (uint_buf, "%u", (unsigned) (pwd->pw_gid));
V_STRDUP (groupname, uint_buf);
}
else
{
V_STRDUP (groupname, grp->gr_name);
}
endgrent ();
}
}
endpwent ();
}
if (g != NULL && error_msg == NULL)
{
/* Explicit group. */
grp = getgrnam (g);
if (grp == NULL)
{
if (!isnumber (g))
error_msg = _("invalid group");
else
*gid = atoi (g);
}
else
*gid = grp->gr_gid;
endgrent (); /* Save a file descriptor. */
if (error_msg == NULL)
V_STRDUP (groupname, g);
}
if (error_msg == NULL)
{
if (u != NULL)
{
*username_arg = strdup (u);
if (*username_arg == NULL)
error_msg = tired;
}
if (groupname != NULL && error_msg == NULL)
{
*groupname_arg = strdup (groupname);
if (*groupname_arg == NULL)
{
if (*username_arg != NULL)
{
free (*username_arg);
*username_arg = NULL;
}
error_msg = tired;
}
}
}
return error_msg;
}
#ifdef TEST
#define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s))
int
main (int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
{
const char *e;
char *username, *groupname;
uid_t uid;
gid_t gid;
char *tmp;
tmp = strdup (argv[i]);
e = parse_user_spec (tmp, &uid, &gid, &username, &groupname);
free (tmp);
printf ("%s: %u %u %s %s %s\n",
argv[i],
(unsigned int) uid,
(unsigned int) gid,
NULL_CHECK (username),
NULL_CHECK (groupname),
NULL_CHECK (e));
}
exit (0);
}
#endif

1247
contrib/cpio/src/util.c Normal file

File diff suppressed because it is too large Load Diff