aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2008-07-10 00:52:03 +0000
committerPeter Wemm <peter@FreeBSD.org>2008-07-10 00:52:03 +0000
commit5715c7fb3cb3a3cbe3e156e13dee4e864943a72d (patch)
treea79e414d0b5fe7d2b7a8f6b24f1a1d7ed3edbb20
parentbb7e869618a549ab9bde54c3a2cfa3a7fd96a28b (diff)
downloadsrc-vendor/misc-GNU/cpio.tar.gz
src-vendor/misc-GNU/cpio.zip
Import heavily trimmed gnu cpio-2.8.vendor/misc-GNU/cpio/2.8vendor/misc-GNU/cpio
(2.9 switched to gpl3 a few weeks later)
Notes
Notes: svn path=/vendor/cpio/dist/; revision=180400 svn path=/vendor/cpio/2.8/; revision=180401; tag=vendor/misc-GNU/cpio/2.8
-rw-r--r--ABOUT-NLS1454
-rw-r--r--COPYING4
-rw-r--r--ChangeLog384
-rw-r--r--INSTALL65
-rw-r--r--NEWS38
-rw-r--r--THANKS8
-rw-r--r--TODO357
-rw-r--r--doc/cpio.texi319
-rw-r--r--doc/version.texi4
-rw-r--r--lib/alloca_.h40
-rw-r--r--lib/argp-ba.c2
-rw-r--r--lib/argp-eexst.c4
-rw-r--r--lib/argp-fmtstream.c51
-rw-r--r--lib/argp-fmtstream.h28
-rw-r--r--lib/argp-fs-xinl.c4
-rw-r--r--lib/argp-help.c310
-rw-r--r--lib/argp-namefrob.h20
-rw-r--r--lib/argp-parse.c85
-rw-r--r--lib/argp-pin.c28
-rw-r--r--lib/argp-pv.c6
-rw-r--r--lib/argp-pvh.c4
-rw-r--r--lib/argp-xinl.c4
-rw-r--r--lib/argp.h124
-rw-r--r--lib/basename.c112
-rw-r--r--lib/dirname.c136
-rw-r--r--lib/dirname.h41
-rw-r--r--lib/error.c140
-rw-r--r--lib/error.h6
-rw-r--r--lib/exitfail.c11
-rw-r--r--lib/exitfail.h2
-rw-r--r--lib/fatal.c27
-rw-r--r--lib/full-write.c10
-rw-r--r--lib/full-write.h2
-rw-r--r--lib/getopt.c88
-rw-r--r--lib/getopt1.c9
-rw-r--r--lib/getopt_.h23
-rw-r--r--lib/getopt_int.h2
-rw-r--r--lib/gettext.h220
-rw-r--r--lib/hash.c1048
-rw-r--r--lib/hash.h88
-rw-r--r--lib/intprops.h78
-rw-r--r--lib/inttostr.c51
-rw-r--r--lib/inttostr.h (renamed from lib/exit.h)28
-rw-r--r--lib/mempcpy.c8
-rw-r--r--lib/paxerror.c365
-rw-r--r--lib/paxexit.c28
-rw-r--r--lib/paxlib.h115
-rw-r--r--lib/paxnames.c156
-rw-r--r--lib/quote.c41
-rw-r--r--lib/quote.h (renamed from lib/strchrnul.h)20
-rw-r--r--lib/quotearg.c697
-rw-r--r--lib/quotearg.h140
-rw-r--r--lib/rmt-command.h (renamed from lib/localedir.h)0
-rw-r--r--lib/rmt.h2
-rw-r--r--lib/rtapelib.c14
-rw-r--r--lib/safe-read.c14
-rw-r--r--lib/safe-read.h14
-rw-r--r--lib/safe-write.c2
-rw-r--r--lib/safe-write.h2
-rw-r--r--lib/savedir.c96
-rw-r--r--lib/savedir.h7
-rw-r--r--lib/strcase.h47
-rw-r--r--lib/strchrnul.c8
-rw-r--r--lib/stripslash.c36
-rw-r--r--lib/strndup.c32
-rw-r--r--lib/strnlen.c31
-rw-r--r--lib/system-ioctl.h55
-rw-r--r--lib/system.h99
-rw-r--r--lib/umaxtostr.c3
-rw-r--r--lib/unlocked-io.h206
-rw-r--r--lib/utimens.c189
-rw-r--r--lib/utimens.h3
-rw-r--r--lib/xalloc-die.c9
-rw-r--r--lib/xalloc.h202
-rw-r--r--lib/xmalloc.c162
-rw-r--r--lib/xstrndup.c (renamed from lib/mempcpy.h)47
-rw-r--r--lib/xstrndup.h (renamed from lib/strndup.h)20
-rw-r--r--src/copyin.c445
-rw-r--r--src/copyout.c654
-rw-r--r--src/copypass.c149
-rw-r--r--src/cpio.h11
-rw-r--r--src/cpiohdr.h84
-rw-r--r--src/defer.c11
-rw-r--r--src/defer.h15
-rw-r--r--src/dstring.c16
-rw-r--r--src/dstring.h7
-rw-r--r--src/extern.h155
-rw-r--r--src/filemode.c7
-rw-r--r--src/filetypes.h7
-rw-r--r--src/global.c14
-rw-r--r--src/idcache.c7
-rw-r--r--src/main.c301
-rw-r--r--src/makepath.c72
-rw-r--r--src/tar.c63
-rw-r--r--src/tar.h8
-rw-r--r--src/tarhdr.h7
-rw-r--r--src/userspec.c20
-rw-r--r--src/util.c439
98 files changed, 7531 insertions, 3296 deletions
diff --git a/ABOUT-NLS b/ABOUT-NLS
index 8e161528a336..ec20977e060b 100644
--- a/ABOUT-NLS
+++ b/ABOUT-NLS
@@ -1,10 +1,11 @@
-Notes on the Free Translation Project
-*************************************
+1 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.
+together, so that free software 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,
@@ -15,15 +16,15 @@ 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.
+work on translations can 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
-==========================
+1.1 Quick configuration advice
+==============================
If you want to exploit the full power of internationalization, you
should configure it using
@@ -45,8 +46,8 @@ to change to GNU `gettext' as soon as possible.
you have installed a recent copy of the GNU gettext package with the
included `libintl'.
-INSTALL Matters
-===============
+1.2 INSTALL Matters
+===================
Some packages are "localizable" when properly installed; the programs
they contain can be made to speak your own native language. Most such
@@ -55,27 +56,27 @@ 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:
+provides the GNU `gettext' functions. If not, the included GNU
+`gettext' 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
+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
+will decide to use this. This might not be 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
@@ -86,7 +87,7 @@ 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
+ Internationalized packages usually have 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
@@ -95,8 +96,8 @@ 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
-==================
+1.3 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
@@ -117,8 +118,8 @@ country code serves to distinguish the dialects.
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''.
+locales supported by your system for your language 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
@@ -131,14 +132,21 @@ 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'.
+ Special advice for Norwegian users: The language code for Norwegian
+bokma*l changed from `no' to `nb' recently (in 2003). During the
+transition period, while some message catalogs for this language are
+installed under `nb' and some older ones under `no', it's recommended
+for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and
+older translations are used.
+
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
-=================
+1.4 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
@@ -164,509 +172,897 @@ 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.
+the terminology in use. Proven linguistic skills are praised more than
+programming skills, here.
-Available Packages
-==================
+1.5 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
+matrix shows the current state of internationalization, as of October
+2006. 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
+ Ready PO files af am ar az be bg bs ca cs cy da de el en en_GB eo
+ +----------------------------------------------------+
+ GNUnet | [] |
+ a2ps | [] [] [] [] [] |
+ aegis | () |
+ ant-phone | () |
+ anubis | [] |
+ ap-utils | |
+ aspell | [] [] [] [] [] |
+ bash | [] [] [] |
+ batchelor | [] |
+ bfd | |
+ bibshelf | [] |
+ binutils | [] |
+ bison | [] [] |
+ bison-runtime | |
+ bluez-pin | [] [] [] [] [] |
+ cflow | [] |
+ clisp | [] [] |
+ console-tools | [] [] |
+ coreutils | [] [] [] |
+ cpio | |
+ cpplib | [] [] [] |
+ cryptonit | [] |
+ darkstat | [] () [] |
+ dialog | [] [] [] [] [] [] |
+ diffutils | [] [] [] [] [] [] |
+ doodle | [] |
+ e2fsprogs | [] [] |
+ enscript | [] [] [] [] |
+ error | [] [] [] [] |
+ fetchmail | [] [] () [] |
+ fileutils | [] [] |
+ findutils | [] [] [] |
+ flex | [] [] [] |
+ fslint | [] |
+ gas | |
+ gawk | [] [] [] |
+ gbiff | [] |
+ gcal | [] |
+ gcc | [] |
+ gettext-examples | [] [] [] [] [] |
+ gettext-runtime | [] [] [] [] [] |
+ gettext-tools | [] [] |
+ gimp-print | [] [] [] [] |
+ gip | [] |
+ gliv | [] |
+ glunarclock | [] |
+ gmult | [] [] |
+ gnubiff | () |
+ gnucash | () () [] |
+ gnucash-glossary | [] () |
+ gnuedu | |
+ gnulib | [] [] [] [] [] [] |
+ gnunet-gtk | |
+ gnutls | |
+ gpe-aerial | [] [] |
+ gpe-beam | [] [] |
+ gpe-calendar | |
+ gpe-clock | [] [] |
+ gpe-conf | [] [] |
+ gpe-contacts | |
+ gpe-edit | [] |
+ gpe-filemanager | |
+ gpe-go | [] |
+ gpe-login | [] [] |
+ gpe-ownerinfo | [] [] |
+ gpe-package | |
+ gpe-sketchbook | [] [] |
+ gpe-su | [] [] |
+ gpe-taskmanager | [] [] |
+ gpe-timesheet | [] |
+ gpe-today | [] [] |
+ gpe-todo | |
+ gphoto2 | [] [] [] [] |
+ gprof | [] [] |
+ gpsdrive | () () |
+ gramadoir | [] [] |
+ grep | [] [] [] [] [] [] |
+ gretl | |
+ gsasl | |
+ gss | |
+ gst-plugins | [] [] [] [] |
+ gst-plugins-base | [] [] [] |
+ gst-plugins-good | [] [] [] [] [] [] [] |
+ gstreamer | [] [] [] [] [] [] [] |
+ gtick | () |
+ gtkam | [] [] [] |
+ gtkorphan | [] [] |
+ gtkspell | [] [] [] [] |
+ gutenprint | [] |
+ hello | [] [] [] [] [] |
+ id-utils | [] [] |
+ impost | |
+ indent | [] [] [] |
+ iso_3166 | [] [] |
+ iso_3166_2 | |
+ iso_4217 | [] |
+ iso_639 | [] [] |
+ jpilot | [] |
+ jtag | |
+ jwhois | |
+ kbd | [] [] [] [] |
+ keytouch | |
+ keytouch-editor | |
+ keytouch-keyboa... | |
+ latrine | () |
+ ld | [] |
+ leafpad | [] [] [] [] [] |
+ libc | [] [] [] [] [] |
+ libexif | [] |
+ libextractor | [] |
+ libgpewidget | [] [] [] |
+ libgpg-error | [] |
+ libgphoto2 | [] [] |
+ libgphoto2_port | [] [] |
+ libgsasl | |
+ libiconv | [] [] |
+ libidn | [] [] |
+ lifelines | [] () |
+ lilypond | [] |
+ lingoteach | |
+ lynx | [] [] [] [] |
+ m4 | [] [] [] [] |
+ mailutils | [] |
+ make | [] [] |
+ man-db | [] () [] [] |
+ minicom | [] [] [] |
+ mysecretdiary | [] [] |
+ nano | [] [] [] |
+ nano_1_0 | [] () [] [] |
+ opcodes | [] |
+ parted | |
+ pilot-qof | [] |
+ psmisc | [] |
+ pwdutils | |
+ python | |
+ qof | |
+ radius | [] |
+ recode | [] [] [] [] [] [] |
+ rpm | [] [] |
+ screem | |
+ scrollkeeper | [] [] [] [] [] [] [] [] |
+ sed | [] [] [] |
+ sh-utils | [] [] |
+ shared-mime-info | [] [] [] [] |
+ sharutils | [] [] [] [] [] [] |
+ shishi | |
+ silky | |
+ skencil | [] () |
+ sketch | [] () |
+ solfege | |
+ soundtracker | [] [] |
+ sp | [] |
+ stardict | [] |
+ system-tools-ba... | [] [] [] [] [] [] [] [] [] |
+ tar | [] |
+ texinfo | [] [] [] |
+ textutils | [] [] [] |
+ tin | () () |
+ tp-robot | [] |
+ tuxpaint | [] [] [] [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux | [] [] [] [] |
+ vorbis-tools | [] [] [] [] |
+ wastesedge | () |
+ wdiff | [] [] [] [] |
+ wget | [] [] |
+ xchat | [] [] [] [] [] [] |
+ xkeyboard-config | |
+ xpad | [] [] |
+ +----------------------------------------------------+
+ af am ar az be bg bs ca cs cy da de el en en_GB eo
+ 10 0 1 2 9 22 1 42 41 2 60 95 16 1 17 16
+
+ es et eu fa fi fr ga gl gu he hi hr hu id is it
+ +--------------------------------------------------+
+ GNUnet | |
+ a2ps | [] [] [] () |
+ aegis | |
+ ant-phone | [] |
+ anubis | [] |
+ ap-utils | [] [] |
+ aspell | [] [] [] |
+ bash | [] [] [] |
+ batchelor | [] [] |
+ bfd | [] |
+ bibshelf | [] [] [] |
+ binutils | [] [] [] |
+ bison | [] [] [] [] [] [] |
+ bison-runtime | [] [] [] [] [] |
+ bluez-pin | [] [] [] [] [] |
+ cflow | [] |
+ clisp | [] [] |
+ console-tools | |
+ coreutils | [] [] [] [] [] [] |
+ cpio | [] [] [] |
+ cpplib | [] [] |
+ cryptonit | [] |
+ darkstat | [] () [] [] [] |
+ dialog | [] [] [] [] [] [] [] [] |
+ diffutils | [] [] [] [] [] [] [] [] [] |
+ doodle | [] [] |
+ e2fsprogs | [] [] [] |
+ enscript | [] [] [] |
+ error | [] [] [] [] [] |
+ fetchmail | [] |
+ fileutils | [] [] [] [] [] [] |
+ findutils | [] [] [] [] |
+ flex | [] [] [] |
+ fslint | [] |
+ gas | [] [] |
+ gawk | [] [] [] [] |
+ gbiff | [] |
+ gcal | [] [] |
+ gcc | [] |
+ gettext-examples | [] [] [] [] [] [] |
+ gettext-runtime | [] [] [] [] [] [] |
+ gettext-tools | [] [] [] |
+ gimp-print | [] [] |
+ gip | [] [] [] |
+ gliv | () |
+ glunarclock | [] [] [] |
+ gmult | [] [] [] |
+ gnubiff | () () |
+ gnucash | () () () |
+ gnucash-glossary | [] [] |
+ gnuedu | [] |
+ gnulib | [] [] [] [] [] [] [] [] |
+ gnunet-gtk | |
+ gnutls | |
+ gpe-aerial | [] [] |
+ gpe-beam | [] [] |
+ gpe-calendar | |
+ gpe-clock | [] [] [] [] |
+ gpe-conf | [] |
+ gpe-contacts | [] [] |
+ gpe-edit | [] [] [] [] |
+ gpe-filemanager | [] |
+ gpe-go | [] [] [] |
+ gpe-login | [] [] [] |
+ gpe-ownerinfo | [] [] [] [] [] |
+ gpe-package | [] |
+ gpe-sketchbook | [] [] |
+ gpe-su | [] [] [] [] |
+ gpe-taskmanager | [] [] [] |
+ gpe-timesheet | [] [] [] [] |
+ gpe-today | [] [] [] [] |
+ gpe-todo | [] |
+ gphoto2 | [] [] [] [] [] |
+ gprof | [] [] [] [] |
+ gpsdrive | () () [] () |
+ gramadoir | [] [] |
+ grep | [] [] [] [] [] [] [] [] [] [] [] [] |
+ gretl | [] [] [] |
+ gsasl | [] [] |
+ gss | [] |
+ gst-plugins | [] [] [] |
+ gst-plugins-base | [] [] |
+ gst-plugins-good | [] [] [] |
+ gstreamer | [] [] [] |
+ gtick | [] |
+ gtkam | [] [] [] [] |
+ gtkorphan | [] [] |
+ gtkspell | [] [] [] [] [] [] |
+ gutenprint | [] |
+ hello | [] [] [] [] [] [] [] [] [] [] [] [] [] |
+ id-utils | [] [] [] [] [] |
+ impost | [] [] |
+ indent | [] [] [] [] [] [] [] [] [] [] |
+ iso_3166 | [] [] [] |
+ iso_3166_2 | [] |
+ iso_4217 | [] [] [] [] |
+ iso_639 | [] [] [] [] [] |
+ jpilot | [] [] |
+ jtag | [] |
+ jwhois | [] [] [] [] [] |
+ kbd | [] [] |
+ keytouch | [] |
+ keytouch-editor | [] |
+ keytouch-keyboa... | [] |
+ latrine | [] [] [] |
+ ld | [] [] |
+ leafpad | [] [] [] [] [] [] |
+ libc | [] [] [] [] [] |
+ libexif | [] |
+ libextractor | [] |
+ libgpewidget | [] [] [] [] [] |
+ libgpg-error | |
+ libgphoto2 | [] [] [] |
+ libgphoto2_port | [] [] |
+ libgsasl | [] [] |
+ libiconv | [] [] |
+ libidn | [] [] |
+ lifelines | () |
+ lilypond | [] |
+ lingoteach | [] [] [] |
+ lynx | [] [] [] |
+ m4 | [] [] [] [] |
+ mailutils | [] [] |
+ make | [] [] [] [] [] [] [] [] |
+ man-db | () |
+ minicom | [] [] [] [] |
+ mysecretdiary | [] [] [] |
+ nano | [] [] [] [] [] [] |
+ nano_1_0 | [] [] [] [] [] |
+ opcodes | [] [] [] [] |
+ parted | [] [] [] [] |
+ pilot-qof | |
+ psmisc | [] [] [] |
+ pwdutils | |
+ python | |
+ qof | [] |
+ radius | [] [] |
+ recode | [] [] [] [] [] [] [] [] |
+ rpm | [] [] |
+ screem | |
+ scrollkeeper | [] [] [] |
+ sed | [] [] [] [] [] |
+ sh-utils | [] [] [] [] [] [] [] |
+ shared-mime-info | [] [] [] [] [] [] |
+ sharutils | [] [] [] [] [] [] [] [] |
+ shishi | |
+ silky | [] |
+ skencil | [] [] |
+ sketch | [] [] |
+ solfege | [] |
+ soundtracker | [] [] [] |
+ sp | [] |
+ stardict | [] |
+ system-tools-ba... | [] [] [] [] [] [] [] [] |
+ tar | [] [] [] [] [] [] [] |
+ texinfo | [] [] |
+ textutils | [] [] [] [] [] |
+ tin | [] () |
+ tp-robot | [] [] [] [] |
+ tuxpaint | [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | [] [] |
+ util-linux | [] [] [] [] [] [] [] |
+ vorbis-tools | [] [] |
+ wastesedge | () |
+ wdiff | [] [] [] [] [] [] [] [] |
+ wget | [] [] [] [] [] [] [] [] |
+ xchat | [] [] [] [] [] [] [] [] |
+ xkeyboard-config | [] [] [] [] |
+ xpad | [] [] [] |
+ +--------------------------------------------------+
+ es et eu fa fi fr ga gl gu he hi hr hu id is it
+ 88 22 14 2 40 115 61 14 1 8 1 6 59 31 0 52
+
+ ja ko ku ky lg lt lv mk mn ms mt nb ne nl nn no
+ +-------------------------------------------------+
+ GNUnet | |
+ a2ps | () [] [] () |
+ aegis | () |
+ ant-phone | [] |
+ anubis | [] [] [] |
+ ap-utils | [] |
+ aspell | [] [] |
+ bash | [] |
+ batchelor | [] [] |
+ bfd | |
+ bibshelf | [] |
+ binutils | |
+ bison | [] [] [] |
+ bison-runtime | [] [] [] |
+ bluez-pin | [] [] [] |
+ cflow | |
+ clisp | [] |
+ console-tools | |
+ coreutils | [] |
+ cpio | |
+ cpplib | [] |
+ cryptonit | [] |
+ darkstat | [] [] |
+ dialog | [] [] |
+ diffutils | [] [] [] |
+ doodle | |
+ e2fsprogs | [] |
+ enscript | [] |
+ error | [] |
+ fetchmail | [] [] |
+ fileutils | [] [] |
+ findutils | [] |
+ flex | [] [] |
+ fslint | [] [] |
+ gas | |
+ gawk | [] [] |
+ gbiff | [] |
+ gcal | |
+ gcc | |
+ gettext-examples | [] [] |
+ gettext-runtime | [] [] [] |
+ gettext-tools | [] [] |
+ gimp-print | [] [] |
+ gip | [] [] |
+ gliv | [] |
+ glunarclock | [] [] |
+ gmult | [] [] |
+ gnubiff | |
+ gnucash | () () |
+ gnucash-glossary | [] |
+ gnuedu | |
+ gnulib | [] [] [] [] |
+ gnunet-gtk | |
+ gnutls | |
+ gpe-aerial | [] |
+ gpe-beam | [] |
+ gpe-calendar | [] |
+ gpe-clock | [] [] [] |
+ gpe-conf | [] [] |
+ gpe-contacts | [] |
+ gpe-edit | [] [] [] |
+ gpe-filemanager | [] [] |
+ gpe-go | [] [] [] |
+ gpe-login | [] [] [] |
+ gpe-ownerinfo | [] [] |
+ gpe-package | [] [] |
+ gpe-sketchbook | [] [] |
+ gpe-su | [] [] [] |
+ gpe-taskmanager | [] [] [] [] |
+ gpe-timesheet | [] |
+ gpe-today | [] [] |
+ gpe-todo | [] |
+ gphoto2 | [] [] |
+ gprof | |
+ gpsdrive | () () () |
+ gramadoir | () |
+ grep | [] [] [] [] |
+ gretl | |
+ gsasl | [] |
+ gss | |
+ gst-plugins | [] |
+ gst-plugins-base | |
+ gst-plugins-good | [] |
+ gstreamer | [] |
+ gtick | |
+ gtkam | [] |
+ gtkorphan | [] |
+ gtkspell | [] [] |
+ gutenprint | |
+ hello | [] [] [] [] [] [] |
+ id-utils | [] |
+ impost | |
+ indent | [] [] |
+ iso_3166 | [] |
+ iso_3166_2 | [] |
+ iso_4217 | [] [] [] |
+ iso_639 | [] [] |
+ jpilot | () () () |
+ jtag | |
+ jwhois | [] |
+ kbd | [] |
+ keytouch | [] |
+ keytouch-editor | |
+ keytouch-keyboa... | |
+ latrine | [] |
+ ld | |
+ leafpad | [] [] |
+ libc | [] [] [] [] [] |
+ libexif | |
+ libextractor | |
+ libgpewidget | [] |
+ libgpg-error | |
+ libgphoto2 | [] |
+ libgphoto2_port | [] |
+ libgsasl | [] |
+ libiconv | |
+ libidn | [] [] |
+ lifelines | [] |
+ lilypond | |
+ lingoteach | [] |
+ lynx | [] [] |
+ m4 | [] [] |
+ mailutils | |
+ make | [] [] [] |
+ man-db | () |
+ minicom | [] |
+ mysecretdiary | [] |
+ nano | [] [] [] |
+ nano_1_0 | [] [] [] |
+ opcodes | [] |
+ parted | [] [] |
+ pilot-qof | |
+ psmisc | [] [] [] |
+ pwdutils | |
+ python | |
+ qof | |
+ radius | |
+ recode | [] |
+ rpm | [] [] |
+ screem | [] |
+ scrollkeeper | [] [] [] [] |
+ sed | [] [] |
+ sh-utils | [] [] |
+ shared-mime-info | [] [] [] [] [] |
+ sharutils | [] [] |
+ shishi | |
+ silky | [] |
+ skencil | |
+ sketch | |
+ solfege | |
+ soundtracker | |
+ sp | () |
+ stardict | [] [] |
+ system-tools-ba... | [] [] [] [] |
+ tar | [] [] [] |
+ texinfo | [] [] [] |
+ textutils | [] [] [] |
+ tin | |
+ tp-robot | [] |
+ tuxpaint | [] |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux | [] [] |
+ vorbis-tools | [] |
+ wastesedge | [] |
+ wdiff | [] [] |
+ wget | [] [] |
+ xchat | [] [] [] [] |
+ xkeyboard-config | [] |
+ xpad | [] [] [] |
+ +-------------------------------------------------+
+ ja ko ku ky lg lt lv mk mn ms mt nb ne nl nn no
+ 52 24 2 2 1 3 0 2 3 21 0 15 1 97 5 1
+
+ nso or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta
+ +------------------------------------------------------+
+ GNUnet | |
+ a2ps | () [] [] [] [] [] [] |
+ aegis | () () |
+ ant-phone | [] [] |
+ anubis | [] [] [] |
+ ap-utils | () |
+ aspell | [] [] |
+ bash | [] [] [] |
+ batchelor | [] [] |
+ bfd | |
+ bibshelf | [] |
+ binutils | [] [] |
+ bison | [] [] [] [] [] |
+ bison-runtime | [] [] [] [] |
+ bluez-pin | [] [] [] [] [] [] [] [] [] |
+ cflow | [] |
+ clisp | [] |
+ console-tools | [] |
+ coreutils | [] [] [] [] |
+ cpio | [] [] [] |
+ cpplib | [] |
+ cryptonit | [] [] |
+ darkstat | [] [] [] [] [] [] |
+ dialog | [] [] [] [] [] [] [] [] [] |
+ diffutils | [] [] [] [] [] [] |
+ doodle | [] [] |
+ e2fsprogs | [] [] |
+ enscript | [] [] [] [] [] |
+ error | [] [] [] [] |
+ fetchmail | [] [] [] |
+ fileutils | [] [] [] [] [] |
+ findutils | [] [] [] [] [] [] |
+ flex | [] [] [] [] [] |
+ fslint | [] [] [] [] |
+ gas | |
+ gawk | [] [] [] [] |
+ gbiff | [] |
+ gcal | [] |
+ gcc | [] |
+ gettext-examples | [] [] [] [] [] [] [] [] |
+ gettext-runtime | [] [] [] [] [] [] [] [] |
+ gettext-tools | [] [] [] [] [] [] [] |
+ gimp-print | [] [] |
+ gip | [] [] [] [] |
+ gliv | [] [] [] [] |
+ glunarclock | [] [] [] [] [] [] |
+ gmult | [] [] [] [] |
+ gnubiff | () |
+ gnucash | () [] |
+ gnucash-glossary | [] [] [] |
+ gnuedu | |
+ gnulib | [] [] [] [] [] |
+ gnunet-gtk | [] |
+ gnutls | [] [] |
+ gpe-aerial | [] [] [] [] [] [] [] |
+ gpe-beam | [] [] [] [] [] [] [] |
+ gpe-calendar | [] |
+ gpe-clock | [] [] [] [] [] [] [] [] |
+ gpe-conf | [] [] [] [] [] [] [] |
+ gpe-contacts | [] [] [] [] [] |
+ gpe-edit | [] [] [] [] [] [] [] [] |
+ gpe-filemanager | [] [] |
+ gpe-go | [] [] [] [] [] [] |
+ gpe-login | [] [] [] [] [] [] [] [] |
+ gpe-ownerinfo | [] [] [] [] [] [] [] [] |
+ gpe-package | [] [] |
+ gpe-sketchbook | [] [] [] [] [] [] [] [] |
+ gpe-su | [] [] [] [] [] [] [] [] |
+ gpe-taskmanager | [] [] [] [] [] [] [] [] |
+ gpe-timesheet | [] [] [] [] [] [] [] [] |
+ gpe-today | [] [] [] [] [] [] [] [] |
+ gpe-todo | [] [] [] [] |
+ gphoto2 | [] [] [] [] [] |
+ gprof | [] [] [] |
+ gpsdrive | [] [] [] |
+ gramadoir | [] [] |
+ grep | [] [] [] [] [] [] [] [] |
+ gretl | [] |
+ gsasl | [] [] [] |
+ gss | [] [] [] |
+ gst-plugins | [] [] [] [] |
+ gst-plugins-base | [] |
+ gst-plugins-good | [] [] [] [] |
+ gstreamer | [] [] [] |
+ gtick | [] |
+ gtkam | [] [] [] [] |
+ gtkorphan | [] |
+ gtkspell | [] [] [] [] [] [] [] [] |
+ gutenprint | [] |
+ hello | [] [] [] [] [] [] [] [] |
+ id-utils | [] [] [] [] |
+ impost | [] |
+ indent | [] [] [] [] [] [] |
+ iso_3166 | [] [] [] [] [] [] |
+ iso_3166_2 | |
+ iso_4217 | [] [] [] [] |
+ iso_639 | [] [] [] [] |
+ jpilot | |
+ jtag | [] |
+ jwhois | [] [] [] [] |
+ kbd | [] [] [] |
+ keytouch | [] |
+ keytouch-editor | [] |
+ keytouch-keyboa... | [] |
+ latrine | [] [] |
+ ld | [] |
+ leafpad | [] [] [] [] [] [] |
+ libc | [] [] [] [] [] |
+ libexif | [] |
+ libextractor | [] [] |
+ libgpewidget | [] [] [] [] [] [] [] |
+ libgpg-error | [] [] |
+ libgphoto2 | [] |
+ libgphoto2_port | [] [] [] |
+ libgsasl | [] [] [] [] |
+ libiconv | [] [] |
+ libidn | [] [] () |
+ lifelines | [] [] |
+ lilypond | |
+ lingoteach | [] |
+ lynx | [] [] [] |
+ m4 | [] [] [] [] [] |
+ mailutils | [] [] [] [] |
+ make | [] [] [] [] |
+ man-db | [] [] |
+ minicom | [] [] [] [] [] |
+ mysecretdiary | [] [] [] [] |
+ nano | [] [] [] |
+ nano_1_0 | [] [] [] [] |
+ opcodes | [] [] |
+ parted | [] |
+ pilot-qof | [] |
+ psmisc | [] [] |
+ pwdutils | [] [] |
+ python | |
+ qof | [] [] |
+ radius | [] [] |
+ recode | [] [] [] [] [] [] [] |
+ rpm | [] [] [] [] |
+ screem | |
+ scrollkeeper | [] [] [] [] [] [] [] |
+ sed | [] [] [] [] [] [] [] [] [] |
+ sh-utils | [] [] [] |
+ shared-mime-info | [] [] [] [] [] |
+ sharutils | [] [] [] [] |
+ shishi | [] |
+ silky | [] |
+ skencil | [] [] [] |
+ sketch | [] [] [] |
+ solfege | [] |
+ soundtracker | [] [] |
+ sp | |
+ stardict | [] [] [] |
+ system-tools-ba... | [] [] [] [] [] [] [] [] [] |
+ tar | [] [] [] [] [] |
+ texinfo | [] [] [] [] |
+ textutils | [] [] [] |
+ tin | () |
+ tp-robot | [] |
+ tuxpaint | [] [] [] [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux | [] [] [] [] |
+ vorbis-tools | [] [] |
+ wastesedge | |
+ wdiff | [] [] [] [] [] [] |
+ wget | [] [] [] [] |
+ xchat | [] [] [] [] [] [] [] |
+ xkeyboard-config | [] [] |
+ xpad | [] [] [] |
+ +------------------------------------------------------+
+ nso or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta
+ 0 2 3 58 30 54 5 73 72 4 40 46 11 50 128 2
+
+ tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu
+ +---------------------------------------------------+
+ GNUnet | [] | 2
+ a2ps | [] [] [] | 19
+ aegis | | 0
+ ant-phone | [] [] | 6
+ anubis | [] [] [] | 11
+ ap-utils | () [] | 4
+ aspell | [] [] [] | 15
+ bash | [] | 11
+ batchelor | [] [] | 9
+ bfd | | 1
+ bibshelf | [] | 7
+ binutils | [] [] [] | 9
+ bison | [] [] [] | 19
+ bison-runtime | [] [] [] | 15
+ bluez-pin | [] [] [] [] [] [] | 28
+ cflow | [] [] | 5
+ clisp | | 6
+ console-tools | [] [] | 5
+ coreutils | [] [] | 16
+ cpio | [] [] [] | 9
+ cpplib | [] [] [] [] | 11
+ cryptonit | | 5
+ darkstat | [] () () | 15
+ dialog | [] [] [] [] [] | 30
+ diffutils | [] [] [] [] | 28
+ doodle | [] | 6
+ e2fsprogs | [] [] | 10
+ enscript | [] [] [] | 16
+ error | [] [] [] [] | 18
+ fetchmail | [] [] | 12
+ fileutils | [] [] [] | 18
+ findutils | [] [] [] | 17
+ flex | [] [] | 15
+ fslint | [] | 9
+ gas | [] | 3
+ gawk | [] [] | 15
+ gbiff | [] | 5
+ gcal | [] | 5
+ gcc | [] [] [] | 6
+ gettext-examples | [] [] [] [] [] [] | 27
+ gettext-runtime | [] [] [] [] [] [] | 28
+ gettext-tools | [] [] [] [] [] | 19
+ gimp-print | [] [] | 12
+ gip | [] [] | 12
+ gliv | [] [] | 8
+ glunarclock | [] [] [] | 15
+ gmult | [] [] [] [] | 15
+ gnubiff | [] | 1
+ gnucash | () | 2
+ gnucash-glossary | [] [] | 9
+ gnuedu | [] | 2
+ gnulib | [] [] [] [] [] | 28
+ gnunet-gtk | | 1
+ gnutls | | 2
+ gpe-aerial | [] [] | 14
+ gpe-beam | [] [] | 14
+ gpe-calendar | [] | 3
+ gpe-clock | [] [] [] [] | 21
+ gpe-conf | [] [] | 14
+ gpe-contacts | [] [] | 10
+ gpe-edit | [] [] [] [] | 20
+ gpe-filemanager | [] | 6
+ gpe-go | [] [] | 15
+ gpe-login | [] [] [] [] [] | 21
+ gpe-ownerinfo | [] [] [] [] | 21
+ gpe-package | [] | 6
+ gpe-sketchbook | [] [] | 16
+ gpe-su | [] [] [] | 20
+ gpe-taskmanager | [] [] [] | 20
+ gpe-timesheet | [] [] [] [] | 18
+ gpe-today | [] [] [] [] [] | 21
+ gpe-todo | [] | 7
+ gphoto2 | [] [] [] [] | 20
+ gprof | [] [] | 11
+ gpsdrive | | 4
+ gramadoir | [] | 7
+ grep | [] [] [] [] | 34
+ gretl | | 4
+ gsasl | [] [] | 8
+ gss | [] | 5
+ gst-plugins | [] [] [] | 15
+ gst-plugins-base | [] [] [] | 9
+ gst-plugins-good | [] [] [] [] [] | 20
+ gstreamer | [] [] [] | 17
+ gtick | [] | 3
+ gtkam | [] | 13
+ gtkorphan | [] | 7
+ gtkspell | [] [] [] [] [] [] | 26
+ gutenprint | | 3
+ hello | [] [] [] [] [] | 37
+ id-utils | [] [] | 14
+ impost | [] | 4
+ indent | [] [] [] [] | 25
+ iso_3166 | [] [] [] [] | 16
+ iso_3166_2 | | 2
+ iso_4217 | [] [] | 14
+ iso_639 | [] | 14
+ jpilot | [] [] [] [] | 7
+ jtag | [] | 3
+ jwhois | [] [] [] | 13
+ kbd | [] [] | 12
+ keytouch | [] | 4
+ keytouch-editor | | 2
+ keytouch-keyboa... | [] | 3
+ latrine | [] [] | 8
+ ld | [] [] [] [] | 8
+ leafpad | [] [] [] [] | 23
+ libc | [] [] [] | 23
+ libexif | [] | 4
+ libextractor | [] | 5
+ libgpewidget | [] [] [] | 19
+ libgpg-error | [] | 4
+ libgphoto2 | [] | 8
+ libgphoto2_port | [] [] [] | 11
+ libgsasl | [] | 8
+ libiconv | [] | 7
+ libidn | [] [] | 10
+ lifelines | | 4
+ lilypond | | 2
+ lingoteach | [] | 6
+ lynx | [] [] [] | 15
+ m4 | [] [] [] | 18
+ mailutils | [] | 8
+ make | [] [] [] | 20
+ man-db | [] | 6
+ minicom | [] | 14
+ mysecretdiary | [] [] | 12
+ nano | [] [] | 17
+ nano_1_0 | [] [] [] | 18
+ opcodes | [] [] | 10
+ parted | [] [] [] | 10
+ pilot-qof | [] | 3
+ psmisc | [] | 10
+ pwdutils | [] | 3
+ python | | 0
+ qof | [] | 4
+ radius | [] | 6
+ recode | [] [] [] | 25
+ rpm | [] [] [] [] | 14
+ screem | [] | 2
+ scrollkeeper | [] [] [] [] | 26
+ sed | [] [] [] | 22
+ sh-utils | [] | 15
+ shared-mime-info | [] [] [] [] | 24
+ sharutils | [] [] [] | 23
+ shishi | | 1
+ silky | [] | 4
+ skencil | [] | 7
+ sketch | | 6
+ solfege | | 2
+ soundtracker | [] [] | 9
+ sp | [] | 3
+ stardict | [] [] [] [] | 11
+ system-tools-ba... | [] [] [] [] [] [] [] | 37
+ tar | [] [] [] [] | 20
+ texinfo | [] [] [] | 15
+ textutils | [] [] [] | 17
+ tin | | 1
+ tp-robot | [] [] [] | 10
+ tuxpaint | [] [] [] | 16
+ unicode-han-tra... | | 0
+ unicode-transla... | | 2
+ util-linux | [] [] [] | 20
+ vorbis-tools | [] [] | 11
+ wastesedge | | 1
+ wdiff | [] [] | 22
+ wget | [] [] [] | 19
+ xchat | [] [] [] [] | 29
+ xkeyboard-config | [] [] [] [] | 11
+ xpad | [] [] [] | 14
+ +---------------------------------------------------+
+ 77 teams tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu
+ 170 domains 0 1 1 77 39 0 136 10 1 48 5 54 0 2028
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
@@ -679,13 +1075,13 @@ 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
+ If October 2006 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
-===============================
+1.6 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
diff --git a/COPYING b/COPYING
index d60c31a97a54..5c95a60a711a 100644
--- a/COPYING
+++ b/COPYING
@@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -305,7 +305,7 @@ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
diff --git a/ChangeLog b/ChangeLog
index 695be81f75cf..1307353cba84 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,387 @@
+2007-06-08 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * configure.ac, NEWS: Version number 2.8
+ * bootstrap.conf: Update
+
+2007-06-07 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * NEWS: Update
+ * configure.ac: Raise version to 2.7.90
+ * doc/cpio.texi: Update
+ * src/extern.h (set_perms, set_file_times): Take file descriptor
+ as the first argument.
+ * src/util.c (set_perms): Take file descriptor
+ as the first argument and use fchmod/fchown if available. Fixes
+ CAN-2005-1111.
+ * src/copyin.c, src/copyout.c, src/copypass.c: Update calls to
+ set_perms.
+ * src/makepath.c: Remove useless includes.
+
+ * src/util.c (set_perms, stat_to_cpio): Use CPIO_UID and CPIO_GID
+ macros to set uid and gid
+ * src/main.c (process_args): Allow to use --owner in copy-out mode.
+ * THANKS: Add Mike Frysinger
+
+2007-05-18 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * bootstrap: Update from tar repository
+ * doc/cpio.texi: Fix typo
+ * src/copyin.c (from_ascii): Bugfix: allow for empty fields
+ * src/copyout.c (process_copy_out): Fix memory leaks on
+ orig_file_name.
+ * src/copypass.c (process_copy_pass): symlink_error takes two
+ arguments.
+ * src/extern.h: Add missing includes.
+
+2006-12-18 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * README-cvs: New file
+ * lib/Makefile.tmpl, lib/bcopy.c, lib/mkdir.c, lib/strdup.c,
+ lib/strerror.c, lib/.cvsignore, po/.cvsignore,
+ po/Makevars: Removed
+ * lib/Makefile.am: New file
+ * po/POTFILES.in: Update
+ * bootstrap: Synch with tar.
+ * configure.ac: Update
+ * gnulib.modules: Add lchown, strerror
+ * src/Makefile.am: Update
+ * src/main.c, src/mt.c: Include rmt-command.h instead of localedir.h
+ * .cvsignore, doc/.cvsignore: Sort
+
+ * src/util.c (sparse_write): Static. Provide a forward
+ declaration. Define enum sparse_write_states inside the function.
+
+ * src/copyin.c (long_format): Use PRIuMAX for printing file size
+ * src/copyout.c (write_out_binary_header): Fix size conversion
+ * src/extern.h (tape_toss_input, warn_if_file_changed): Last
+ argument is off_t
+ * src/util.c (tape_toss_input, warn_if_file_changed): Last
+ argument is off_t
+ (warn_if_file_changed): Use ngettext
+
+2006-11-15 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * src/copypass.c: Fix setting output file permissions
+
+2006-11-13 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * doc/cpio.texi: Consistently use @option{} for displaying command
+ line options.
+ Fix formatting in "Invoking `cpio'" section
+ * src/main.c (process_args): Fix usage error diagnostics in
+ copy-pass mode.
+
+2006-10-24 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * src/copyout.c (process_copy_out): Add terminating zero to the
+ link_name.
+
+ * tests/symlink.at: New testcase
+ * tests/Makefile.am: New test symlink.at
+ * tests/inout.at: Add keywords
+ * tests/testsuite.at (AT_SKIP_TEST): New macro
+ New test symlink.at
+
+2006-10-21 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * configure.ac, NEWS: Version 2.7
+ * gnulib.modules: Add stdint
+ * src/util.c: Use STRINGIFY_BIGINT to display num_bytes
+
+2006-09-27 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * TODO: Update
+ * README-alpha: Update
+ * bootstrap: Imported from tar
+ * configure.ac: Require autoconf 2.59 and gettext 1.15
+ * gnulib.modules: add inttypes
+ * doc/cpio.texi: Minor fixes
+ * po/Makevars: Remove automatically generated file
+ * po/.cvsignore: Add Makevars
+ * lib/.cvsignore: Update
+ * src/copyin.c, src/copyout.c, src/copypass.c, src/cpio.h,
+ src/cpiohdr.h, src/defer.c, src/defer.h, src/extern.h,
+ src/global.c, src/main.c, src/makepath.c, src/tar.c,
+ src/util.c: Update copyright year.
+
+2006-07-04 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * bootstrap (update_po): Fix single translation update
+ * lib/Makefile.tmpl: Initialize AM_CPPFLAGS
+ (noinst_HEADERS): Add system-ioctl.h
+
+ Start rewriting using a better suited internal representation for
+ the file meta-data.
+
+ * src/cpiohdr.h (struct old_cpio_header): Remove unused fields
+ c_mtime, c_filesize and c_name.
+ (struct old_ascii_header): New data type
+ (struct new_ascii_header): New data type. Describes the header
+ structure, not its internal representation.
+ (struct cpio_file_stat): New data type. Describes internal
+ representation of a file metadata
+
+ * src/copyin.c (from_ascii): New function
+ Use cpio_file_stat for internal header representation.
+ * src/copyout.c: Use cpio_file_stat for internal header
+ representation. Among other things this fixes bug reported by
+ Peter Vrabec on Mar 2, 2006
+ (http://lists.gnu.org/archive/html/bug-cpio/2006-03/msg00000.html)
+ * src/copypass.c: Use cpio_file_stat for internal header
+ representation.
+ * src/tar.c: Likewise
+ * src/util.c: Likewise
+ * src/defer.c: Likewise
+ * src/defer.h: Likewise
+ * src/extern.h: Likewise
+ (from_ascii): New prototype
+ (LG_8,LG_16,FROM_OCTAL,FROM_HEX): New defines
+ * src/main.c: New command line option --HANG (hidden)
+
+2006-03-12 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * tests/Makefile.am (AM_CPPFLAGS): Define LOCALEDIR
+
+2006-02-18 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * gnulib.modules: Add stpcpy. Thanks Benigno B. Junior for
+ reporting.
+ * THANKS: Add Benigno B. Junior
+ * src/makepath.c: Fix indentation.
+
+2005-11-16 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * src/copyout.c (process_copy_out): Fix typo.
+
+2005-11-12 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * bootstrap: Minor fix
+ * src/copyout.c (write_out_header): Rewritten using separate
+ functions for each file format. Use to_ascii to convert numbers to
+ ascii representation. Check for overflows and report them if
+ appropriate. Return 0 if it is OK to proceed with archiving this
+ file, 1 otherwise. All callers updated.
+ * src/extern.h (write_out_header): Return int.
+
+2005-10-28 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * src/util.c: Include paxlib.
+ * bootstrap: If file `.bootstrap' exists in the cwd and is
+ readable, prepend its contents to the command line.
+
+ Fix Debian bug 335580:
+
+ * src/copyout.c (read_for_checksum,write_out_header): CRC is a
+ 32-bit unsigned value. Patch proposed by Jim Castleberry and
+ Peter Vrabec.
+ * src/extern.h (crc): Change declaration
+ * src/global.c: Likewise
+ * src/tar.c (tar_checksum): Return unsigned int
+
+ * THANKS: Add Jim Castleberry
+ * NEWS: Updated
+
+2005-09-30 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * src/copyout.c (process_copy_out): Discern between original and
+ (eventually fixed) file name (in tar terminology, `file name'
+ vs. `member name'.
+
+2005-09-08 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * gnulib.modules: Add utimens
+ * src/util.c (cpio_safer_name_suffix): Preserve ./ no matter what
+ the value of strip_leading_dots is.
+ (set_file_times): New function
+ * src/extern.h (set_file_times): New function
+ * src/copyin.c: Use set_file_times() to update file atime/mtime
+ * src/copyout.c: Likewise.
+ * src/copypass.c: Likewise.
+
+2005-05-25 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * src/copyin.c: Use cpio_safer_name_suffix() and CPIO_TRAILER_NAME
+ define instead of hardcoding the trailer file name.
+ * src/copyout.c: Likewise.
+ * src/cpio.h (CPIO_TRAILER_NAME): New define
+ * src/extern.h (cpio_safer_name_suffix): New proto
+ * src/tar.c: Use CPIO_TRAILER_NAME define instead of hardcoding
+ the trailer file name.
+ * src/util.c (cpio_safer_name_suffix): New function
+ (add_cdf_double_slashes): Add FIXME warning.
+
+ * lib/fatal.c: New file
+ * lib/Makefile.tmpl (libcpio_a_SOURCES): Add fatal.c
+ * src/copyout.c: Use error reporting functions from paxlib
+ * src/makepath.c: Likewise
+ * src/mt.c: Likewise
+ * src/main.c (fatal_exit): Moved to lib/fatal.c
+
+2005-05-24 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * src/copyin.c (process_copy_in): Use safer_name_suffix no matter
+ what the value of no_abs_paths_flag. The function knows better
+ what to do in any case.
+ * src/copyout.c (process_copy_out): Honor no_abs_paths_flag.
+ * src/main.c (options): Minor fixes.
+
+2005-05-23 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * bootstrap (copy_files): Create destination directory if it does
+ not exist.
+ Preserve longlong.m4 as longlong_gl.m4
+ * src/main.c: Include paxlib.h
+
+2005-05-22 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * lib/.cvsignore: Updated
+ * gnulib.modules: Add hash
+ * doc/cpio.texi (Reports): New chapter
+ * lib/Makefile.tmpl: Add new paxutils files.
+ * po/POTFILES.in: Likewise
+ * src/copyin.c [!HAVE_LCHOWN] (lchown): Define to 0 to avoid
+ changing ownership of the target file.
+ (process_copy_in): Use safer_name_suffix()
+ * src/main.c (parse_opt): Handle new --absolute-filenames option.
+ (process_args): Updated
+ * src/util.c: Rewrite inode lookup/insertion functions using hash
+ module.
+
+u2005-05-20 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * configure.ac: Raised version number to 2.6.90
+ * NEWS: Updated
+ * src/copyin.c: Use set_perms.
+ * src/copypass.c: Likewise.
+ * src/copyout.c (process_copy_out): Use stat_to_cpio() to convert
+ struct stat to struct new_cpio_header.
+ * src/defer.h: Remove legacy P_() stuff.
+ * src/dstring.c: Likewise
+ * src/extern.h: Likewise
+ * src/util.c (stat_to_cpio,set_perms): New functions
+ * doc/.cvsignore: Updated
+ * lib/.cvsignore: Updated
+ * tests/.cvsignore: Updated
+ * .cvsignore: Updated
+ * COPYING: Added to the repository
+
+2005-05-19 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * po/POTFILES.in: Add paxerror.c paxexit.c paxconvert.c
+
+ * bootstrap (copy_files): Accept optional third argument: a prefix
+ to be appended to destination file names.
+ Import paxutils/paxlib files.
+ * lib/Makefile.tmpl (libcpio_a_SOURCES): Add paxerror.c paxexit.c
+ paxconvert.c
+ * src/copyin.c: Use paxutils error reporting functions
+ * src/copyout.c: Likewise
+ * src/copypass.c: Likewise
+ * src/util.c: Likewise. Add missing includes
+ * src/main.c (USAGE_ERROR): Removed
+ (CHECK_USAGE,parse_opt,process_args): Use error() instead of USAGE_ERROR
+ (fatal_exit): New function
+ * src/tar.c (is_tar_filename_too_long): Removed unused variable
+
+ * Makefile.am, configure.ac, doc/Makefile.am,
+ doc/cpio.texi, doc/gendocs_template, headers/Makefile.am,
+ headers/fnmatch.h, lib/Makefile.tmpl, lib/mkdir.c,
+ lib/strdup.c, lib/strerror.c, src/Makefile.am,
+ src/copyin.c, src/copyout.c, src/copypass.c, src/cpio.h,
+ src/cpiohdr.h, src/defer.c, src/defer.h, src/dstring.c,
+ src/dstring.h, src/extern.h, src/filemode.c,
+ src/filetypes.h, src/global.c, src/idcache.c,
+ src/main.c, src/makepath.c, src/mt.c, src/tar.c,
+ src/tar.h, src/tarhdr.h, src/userspec.c, src/util.c,
+ tests/Makefile.am, tests/inout.at, tests/testsuite.at,
+ tests/version.at: Updated FSF postal mail address.
+
+ * bootstrap: Port recent changes from tar bootstrap.
+ * gnulib.modules: New file
+ * tests/Makefile.am (genfile_SOURCES,LDADD): Updated
+
+ * THANKS: Updated
+ * configure.ac: Remove check for gethostname, it is never used.
+ Remove check for setsockopt, it is provided by paxutils.
+
+ Fix LFS support issues. Proposed by Peter Vrabec and Dmitry V. Levin
+
+ * src/extern.h (copy_files_tape_to_disk, copy_files_disk_to_tape,
+ copy_files_disk_to_disk): Change num_bytes argument type from
+ long to off_t.
+ * src/util.c (copy_files_tape_to_disk, copy_files_disk_to_tape,
+ copy_files_disk_to_disk, disk_fill_input_buffer,
+ write_nuls_to_file): Likewise.
+ (write_nuls_to_file, copy_files_disk_to_tape,
+ copy_files_disk_to_disk): Handle `off_t num_bytes' properly.
+
+ * src/util.c (find_inode_file): Fix typos causing function to
+ occasionally miss inodes and, therefore, to copy out the same
+ (hard-linked) file several times to archive. Proposed by Brian
+ Mays.
+
+2005-03-24 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * src/main.c (process_args): Fixed discrepancy I have been
+ overlooking so far: cpio still does not handle --sparse option
+ the same way tar is handling it. --sparse is allowed in copy-in
+ and copy-pass modes, just as docs say it. Thanks Dmitry Levin.
+ * THANKS: Updated
+
+2005-03-21 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * src/util.c (disk_buffered_write): Fix typo introduced
+ 2005-01-11.
+ * src/main.c (process_args): Fixed error message
+
+2005-01-31 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * src/main.c (main): Remove umask(0). Fixes CAN-1999-1572.
+ [__TURBOC__,__EMX__]: Removed
+ * src/copypass.c (process_copy_pass): Set umask 0
+ * src/copyin.c (process_copy_in): Likewise
+ * src/util.c (open_archive): Use MODE_RW.
+
+2005-01-11 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * doc/gendocs_template: Template file for gendocs.sh.
+ * doc/Makefile.am: Use gendocs.sh to generate webdocs.
+ * doc/cpio.texi: Updated.
+
+ * src/copyin.c: Use memset instead of bzero, memmove
+ (or memcpy, if appropriate), instead of bcopy, and
+ strchr/strrchr instead of index/rindex.
+ * src/copypass.c: Likewise.
+ * src/main.c: Likewise.
+ * src/makepath.c: Likewise.
+ * src/tar.c: Likewise.
+ * src/util.c: Likewise.
+ (write_nuls_to_file): Made extern. All callers updated
+
+ * src/copyout.c: Likewise. Use write_nuls_to_file instead
+ of explicitely accessing zeros_512
+ * src/userspec.c: Likewise.
+ Rename isnumber to isnumber_p. Proposed by
+ Albert Chin
+ * src/extern.h (zeros_512): Removed
+ (write_nuls_to_file): New function
+ * src/global.c (zeros_512): Removed
+
+2005-01-06 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * bootstrap: Add 'fileblocks' gnulib module
+ Create paxutils.m4
+ * configure.ac: Call cpio_PAXUTILS
+ * src/main.c: Remove ifdef around setlocale
+ * src/mt.c: Likewise
+
+2004-12-21 Sergey Poznyakoff <gray@Mirddin.farlep.net>
+
+ * configure.ac: New option --enable-mt
+ Check for locale.h
+ * doc/cpio.info: Removed
+ * src/mt.c (main): Use argmatch_invalid()
+
2004-12-20 Sergey Poznyakoff <gray@Mirddin.farlep.net>
Released version 2.6. Sources up to this point are tagged
diff --git a/INSTALL b/INSTALL
index 095b1eb40635..5458714e1e2c 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,8 +1,8 @@
Installation Instructions
*************************
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
-Software Foundation, Inc.
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006 Free Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
@@ -10,7 +10,10 @@ unlimited permission to copy, distribute and modify it.
Basic Installation
==================
-These are generic installation instructions.
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
@@ -23,9 +26,9 @@ 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
+the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
-cache files.)
+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
@@ -35,20 +38,17 @@ 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'.
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system. 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.
+ `./configure' to configure the package for your system.
- Running `configure' takes awhile. While running, it prints some
- messages telling which features it is checking for.
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
2. Type `make' to compile the package.
@@ -78,7 +78,7 @@ details on some of the pertinent environment variables.
by setting variables in the command line or in the environment. Here
is an example:
- ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
@@ -87,31 +87,29 @@ 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
+own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
- 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.
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
Installation Names
==================
-By default, `make install' 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'.
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
-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.
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
@@ -159,7 +157,7 @@ where SYSTEM can have one of these forms:
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
+use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
@@ -189,9 +187,14 @@ 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
+causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
`configure' Invocation
======================
diff --git a/NEWS b/NEWS
index b7dc861fe0bd..857ae89ff1ad 100644
--- a/NEWS
+++ b/NEWS
@@ -1,10 +1,36 @@
-GNU cpio NEWS -- history of user-visible changes. 2004-12-20
-Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+GNU cpio NEWS -- history of user-visible changes. 2007-06-08
+Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
See the end of file for copying conditions.
Please send cpio bug reports to <bug-cpio@gnu.org>.
-Version 2.6
+Version 2.8 - Sergey Poznyakoff, 2007-06-08
+
+* Option --owner can be used in copy-out mode, allowing to uniformly override
+ownership of the files being added to the archive.
+
+* Bugfixes:
+
+** Symlinks were handled incorrectly in copy-out mode.
+** Fix handling of large files.
+** Fix setting the file permissions in copy-out mode.
+** Fix CAN-2005-1111
+
+
+Version 2.7 - Sergey Poznyakoff, 2006-10-21
+
+* Improved error checking and diagnostics
+
+* Bugfixes
+** Fixed CAN-1999-1572
+** Allow to use --sparse in both copy-in and copy-pass.
+** Fix bug that eventually caused copying out the same hard-linked
+file several times to archive.
+** Fix several LFS-related issues.
+** Fix Debian bug 335580.
+
+
+Version 2.6 - Sergey Poznyakoff, 2004-12-20
* Added NLS support
@@ -107,7 +133,7 @@ multiple links and of multi-volume archives on floppy disks.
----------------------------------------------------------------------
Copyright information:
-Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
@@ -122,4 +148,8 @@ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
Local variables:
mode: outline
paragraph-separate: "[ ]*$"
+eval: (add-hook 'write-file-hooks 'time-stamp)
+time-stamp-start: "changes. "
+time-stamp-format: "%:y-%02m-%02d"
+time-stamp-end: "\n"
end:
diff --git a/THANKS b/THANKS
index bef85145c65f..393de057c2a1 100644
--- a/THANKS
+++ b/THANKS
@@ -9,6 +9,12 @@ The following is a list of people who contributed to GNU cpio by
reporting problems, suggesting various improvements or submitting actual
code. Help us keep it complete and exempt of errors.
+Benigno B. Junior <bbj@gentux.com.br>
+Brian Mays <brian@debian.org>
+Dmitry V. Levin <ldv@altlinux.org>
+Jim Castleberry <bhg9aha02@sneakemail.com>
+Holger Fleischmann <holger_fleischmann@mra.man.de>
Matthew Braithwaite <mab@cnet.com>
+Mike Frysinger <vapier@gentoo.org>
Mitsuru Chinen <mchinen@yamato.ibm.com>
-Holger Fleischmann <holger_fleischmann@mra.man.de> \ No newline at end of file
+Peter Vrabec <pvrabec@redhat.com>
diff --git a/TODO b/TODO
index 5ba103021908..ffd63d5fd96d 100644
--- a/TODO
+++ b/TODO
@@ -1,54 +1,21 @@
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.
+probably still waiting for being handled. The list is divided
+into two parts, the messages are in somehow arbitrary 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)
+* Bug reports
+--------------
+
+** cpio -d bug (fwd) (score: 47)
+ Author: Christian Smith <csmith@micromuse.com>
+ Date: Wed, 14 Nov 2001 02:06:46 +0000 (GMT)
+ This was bounced from bug-cpio@bogus.example.com I guess that
+ isn't set up yet. -- /"\ \ / ASCII RIBBON CAMPAIGN - AGAINST
+ HTML MAIL X - AGAINST MS ATTACHMENTS / \ $ cpio --version GNU
+ cpio version 2
+ /archive/html/bug-gnu-utils/2001-11/msg00170.html (4,548 bytes)
- 10. bug in cpio with tapechange in copy-in-mode (score: 34)
+** 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
@@ -58,15 +25,7 @@ in reverse chronological order.
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)
+** 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
@@ -75,44 +34,7 @@ in reverse chronological order.
/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)
+** 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:
@@ -120,62 +42,9 @@ in reverse chronological order.
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)
+
+** These two seem to be related:
+*** cpio copy-in and multiply-linked files (score: 35)
Author: Chris Jaeger <cjaeger@ensim.com>
Date: Tue, 07 Aug 2001 23:46:04 -0700
Hi, I was wondering whether it was a bug or a feature that GNU
@@ -184,14 +53,7 @@ in reverse chronological order.
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)
+*** (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
@@ -200,69 +62,24 @@ in reverse chronological order.
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)
+** These too:
+
+*** Re: minor problems with slackware-current (score: 7)
+ Author: Cezary Sliwa <sliwa@cft.edu.pl>
+ Date: Wed, 1 Aug 2001 10:43:37 +0200
+ "cpio --sparse" corrupts data. A fix attached. C.S. Attachment:
+ cpio-2.4.2-sparse.diff Description: Text document
+ /archive/html/bug-gnu-utils/2001-08/msg00000.html (3,989 bytes)
- 47. cpio --sparse (score: 34)
+*** 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)
+
+** And these too
+*** cpio-2.4.2: data corruption bug (score: 35)
Author: Todd Kelley <toddk@oeone.com>
Date: Fri, 09 Feb 2001 17:00:06 -0500
Hello, Recently at OEone we fixed a bug in GNU cpio-2.4.2: When
@@ -271,7 +88,16 @@ in reverse chronological order.
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:
+*** cpio pass-through can corrupt files (score: 36)
+ Author: "Parrott, Jeff" <Jeff.Parrott@sea.siemens.com>
+ Date: Mon, 16 Oct 2000 13:32:57 -0400
+ I have seen corrupted files as a result of using the
+ pass-through option in cpio. The corruption occurs when
+ active/in-use (and growing) files are being copied. The problem
+ is that the file size has
+ /archive/html/bug-gnu-utils/2000-10/msg00087.html (4,974 bytes)
+
+** cpio 2.4.2 unconditionally takes the tape drive offline (score:
39)
Author: Scott Larson <scowl@plaza.ds.adp.com>
Date: Thu, 11 Jan 2001 13:15:52 -0800
@@ -281,7 +107,7 @@ in reverse chronological order.
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
+** 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
@@ -291,66 +117,43 @@ in reverse chronological order.
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)
+* Suggestions
+-------------
+
+** GNU cpio suggestion (score: 42)
+ Author: "H.J.Thomassen" <hjt@ATComputing.nl>
+ Date: Mon, 17 Dec 2001 11:27:11 +0100
+ Re: suggestion for GNU-cpio extension (plus reference
+ implementation) We use cpio for our backup purposes. The backup
+ is started automatically in the middle of the night. To chase
+ away all users we d
+ /archive/html/bug-gnu-utils/2001-12/msg00244.html (7,474 bytes)
- 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)
+** 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)
- 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)
+** [cpio] man page enhancement: a Example section ? (score: 5)
+ Author: Yannick Patois <patois@calvix.org>
+ Date: Wed, 24 Oct 2001 12:48:33 +0200 (CEST)
+ Hello, I seldom use cpio (as I think many people) and only had
+ to use it once or twice. IMHA, would be good to have a small
+ section with an example of most often performed actions
+ (creating an archiv
+ /archive/html/bug-gnu-utils/2001-10/msg00270.html (4,336 bytes)
+
+** Patch to cpio to enable verbose *skipping* of files (score: 40)
+ Author: Tomas Pospisek <tpo@sourcepole.ch>
+ Date: Mon, 8 Oct 2001 13:54:14 +0200 (CEST)
+ This patch enables cpio to be verbose about the files that it
+ does not copy, which is very handy for seeing cpio's progress
+ through a tape or simply for debuging. The patch along with a
+ Debian packag
+ /archive/html/bug-gnu-utils/2001-10/msg00083.html (4,548 bytes)
- 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)
diff --git a/doc/cpio.texi b/doc/cpio.texi
index ae534f4df22f..a82126953b5b 100644
--- a/doc/cpio.texi
+++ b/doc/cpio.texi
@@ -3,94 +3,70 @@
@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.
+@dircategory Archiving
+@direntry
+* Cpio: (cpio). Copy-in-copy-out archiver to tape or disk.
+@end direntry
-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.
+@include version.texi
-@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
+@copying
+This manual documents GNU cpio (version @value{VERSION}, @value{UPDATED}).
+Copyright @copyright{} 1995, 2001, 2002, 2004 Free Software Foundation, Inc.
+@sp 1
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.2 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU Manual'',
+and with the Back-Cover Texts as in (a) below. A copy of the license
+is included in the section entitled ``GNU Free Documentation License''.
-@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
-
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software. Copies published by the Free
+Software Foundation raise funds for GNU development.''
+@end quotation
+@end copying
@titlepage
@title GNU CPIO
-@subtitle @value{VERSION} @value{RELEASEDATE}
+@subtitle @value{VERSION} @value{UPDATED}
@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}.@*
+@insertcopying
@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.
+51 Franklin Street, Fifth Floor, @*
+Boston, MA 02110-1301, USA @*
@end titlepage
-@ifinfo
@node Top, Introduction, (dir), (dir)
@comment node-name, next, previous, up
+
+@ifinfo
@top
GNU cpio is a tool for creating and extracting archives, or copying
files from one place to another. It handles a number of cpio formats as
well as reading and writing tar files. This is the first edition of the
-GNU cpio documentation and is consistant with @value{VERSION}.
+GNU cpio documentation and is consistent with @value{VERSION}.
+
+@end ifinfo
@menu
* Introduction::
* Tutorial:: Getting started.
-* Invoking `cpio':: How to invoke `cpio'.
+* Invoking cpio:: How to invoke @command{cpio}.
* Media:: Using tapes and other archive media.
+* Reports:: Reporting bugs or suggestions
* Concept Index:: Concept index.
+@detailmenu
--- The Detailed Node Listing ---
Invoking cpio
@@ -99,9 +75,9 @@ Invoking cpio
* Copy-in mode::
* Copy-pass mode::
* Options::
-@end menu
-@end ifinfo
+@end detailmenu
+@end menu
@node Introduction, Tutorial, Top, Top
@comment node-name, next, previous, up
@@ -112,13 +88,13 @@ 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
+tar format is provided for compatibility with the tar program. By
default, cpio creates binary format archives, for compatibility with
older cpio programs. When extracting from archives, cpio automatically
recognizes which kind of archive it is reading and can read archives
created on machines with a different byte-order.
-@node Tutorial, Invoking `cpio', Introduction, Top
+@node Tutorial, Invoking cpio, Introduction, Top
@comment node-name, next, previous, up
@chapter Tutorial
@cindex creating a cpio archive
@@ -134,7 +110,7 @@ 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.
+output, or to the device defined by the @option{-F} option.
@xref{Copy-out mode}. Usually find or ls is used to provide this list
to the standard input. In the following example you can see the
possibilities for archiving the contents of a single directory.
@@ -146,9 +122,9 @@ possibilities for archiving the contents of a single directory.
@end cartouche
@end example
-The @samp{-o} option creates the archive, and the @samp{-v} option
+The @option{-o} option creates the archive, and the @option{-v} option
prints the names of the files archived as they are added. Notice that
-the options can be put together after a single @samp{-} or can be placed
+the options can be put together after a single @option{-} or can be placed
separately on the command line. The @samp{>} redirects the cpio output
to the file @samp{directory.cpio}.
@@ -165,12 +141,12 @@ provide the file list to cpio:
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
+below and place them in the archive tree.cpio. Again the @option{-o}
+creates an archive, and the @option{-v} option shows you the name of the
+files as they are archived. @xref{Copy-out mode}. Using the @samp{.} in the
find statement will give you more flexibility when doing restores, as it
will save file names with a relative path vice a hard wired, absolute
-path. The @samp{-depth} option forces @samp{find} to print of the
+path. The @option{-depth} option forces @samp{find} to print of the
entries in a directory before printing the directory itself. This
limits the effects of restrictive directory permissions by printing the
directory entries in a directory before the directory name itself.
@@ -190,10 +166,10 @@ overwrite existing files unless you tell it to.
@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.
+place them in the present directory. The @option{-i} option extracts the
+archive and the @option{-v} shows the file names as they are extracted.
If you are dealing with an archived directory tree, you need to use the
-@samp{-d} option to create directories as necessary, something like:
+@option{-d} option to create directories as necessary, something like:
@example
@cartouche
@@ -223,13 +199,13 @@ argument. @xref{Copy-pass mode}.
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
+the @option{-print0} available with GNU find, combined with the
+@option{--null} option of cpio. These two options act together to send
file names between find and cpio, even if special characters are
-embedded in the file names. Another is @samp{-p}, which tells cpio to
+embedded in the file names. Another is @option{-p}, which tells cpio to
pass the files it finds to the directory @samp{new-dir}.
-@node Invoking `cpio', Media, Tutorial, Top
+@node Invoking cpio, Media, Tutorial, Top
@comment node-name, next, previous, up
@chapter Invoking cpio
@cindex invoking cpio
@@ -242,7 +218,7 @@ pass the files it finds to the directory @samp{new-dir}.
* Options::
@end menu
-@node Copy-out mode, Copy-in mode, Invoking `cpio', Invoking `cpio'
+@node Copy-out mode, Copy-in mode, Invoking cpio, Invoking cpio
@comment node-name, next, previous, up
@section Copy-out mode
@@ -264,7 +240,7 @@ cpio @{-o|--create@} [-0acvABLV] [-C bytes] [-H format]
< name-list [> archive]
@end example
-@node Copy-in mode, Copy-pass mode, Copy-out mode, Invoking `cpio'
+@node Copy-in mode, Copy-pass mode, Copy-out mode, Invoking cpio
@comment node-name, next, previous, up
@section Copy-in mode
@@ -272,8 +248,8 @@ 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
+copied from the archive. Unlike in the shell, an initial @samp{.} in a
+filename does match a wildcard at the start of a pattern, and a @samp{/} in a
filename can match wildcards. If no patterns are given, all files are
extracted. @xref{Options}.
@@ -288,11 +264,11 @@ cpio @{-i|--extract@} [-bcdfmnrtsuvBSV] [-C bytes] [-E file]
[--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]
+[--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'
+@node Copy-pass mode, Options, Copy-in mode, Invoking cpio
@comment node-name, next, previous, up
@section Copy-pass mode
@@ -314,7 +290,7 @@ cpio @{-p|--pass-through@} [-0adlmuvLV] [-R [user][:.][group]]
-@node Options, , Copy-pass mode, Invoking `cpio'
+@node Options, , Copy-pass mode, Invoking cpio
@comment node-name, next, previous, up
@section Options
@@ -322,22 +298,26 @@ cpio @{-p|--pass-through@} [-0adlmuvLV] [-R [user][:.][group]]
@table @code
-@item -0, --null
+@item -0
+@itemx --null
Read a list of filenames terminated by a null character, instead of a
newline, so that files whose names contain newlines can be archived.
GNU find is one way to produce a list of null-terminated filenames.
This option may be used in copy-out and copy-pass modes.
-@item -a, --reset-access-time
+@item -a
+@itemx --reset-access-time
Reset the access times of files after reading them, so
that it does not look like they have just been read.
-@item -A, --append
+@item -A
+@itemx --append
Append to an existing archive. Only works in copy-out
mode. The archive must be a disk file specified with
-the -O or -F (--file) option.
+the @option{-O} or @option{-F} (@option{--file}) option.
-@item -b, --swap
+@item -b
+@itemx --swap
Swap both halfwords of words and bytes of halfwords in the data.
Equivalent to -sS. This option may be used in copy-in mode. Use this
option to convert 32-bit integers between big-endian and little-endian
@@ -347,42 +327,49 @@ machines.
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 --block-size=@var{block-size}
+Set the I/O block size to @var{block-size} * 512 bytes.
@item -c
Use the old portable (ASCII) archive format.
-@item -C IO-SIZE, --io-size=IO-SIZE
-Set the I/O block size to IO-SIZE bytes.
+@item -C @var{io-size}
+@itemx --io-size=@var{io-size}
+Set the I/O block size to @var{io-size} bytes.
-@item -d, --make-directories
+@item -d
+@itemx --make-directories
Create leading directories where needed.
-@item -E FILE, --pattern-file=FILE
+@item -E @var{file}
+@itemx --pattern-file=@var{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
+@var{file}. The lines of @var{file} are treated as if they had been non-option
arguments to cpio. This option is used in copy-in mode,
-@item -f, --nonmatching
+@item -f
+@itemx --nonmatching
Only copy files that do not match any of the given
patterns.
-@item -F, --file=archive
+@item -F @var{archive}
+@itemx --file=@var{archive}
Archive filename to use instead of standard input or output. To use a
tape drive on another machine as the archive, use a filename that starts
-with `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'
+with @samp{@var{hostname}:}, where @var{hostname} is the name or IP
+address of the machine. The hostname can be preceded by a username and an
+@samp{@@} to access the remote tape drive as that user, if you have
+permission to do so (typically an entry in that user's @file{~/.rhosts}
file).
@item --force-local
-With -F, -I, or -O, take the archive file name to be a
+With @option{-F}, @option{-I}, or @option{-O}, take the archive file name to be a
local file even if it contains a colon, which would
ordinarily indicate a remote host name.
-@item -H FORMAT, --format=FORMAT
-Use archive format FORMAT. The valid formats are listed below; the same
+@item -H @var{format}
+@itemx --format=@var{format}
+Use archive format @var{format}. The valid formats are listed below; the same
names are also recognized in all-caps. The default in copy-in mode is
to automatically detect the archive format, and in copy-out mode is
@samp{bin}.
@@ -417,39 +404,46 @@ The portable format used by HPUX's cpio (which stores device files
differently).
@end table
-@item -i, --extract
+@item -i
+@itemx --extract
Run in copy-in mode.
@xref{Copy-in mode}.
-@item -I archive
+@item -I @var{archive}
Archive filename to use instead of standard input. To use a tape drive
on another machine as the archive, use a filename that starts with
-`HOSTNAME:'. The hostname can be preceded by a username and an `@@' to
+@samp{@var{hostname}:}, where @var{hostname} is the name or IP address
+of the remote host. The hostname can be preceded by a username and an @samp{@@} to
access the remote tape drive as that user, if you have permission to do
-so (typically an entry in that user's `~/.rhosts' file).
+so (typically an entry in that user's @file{~/.rhosts} file).
@item -k
Ignored; for compatibility with other versions of cpio.
-@item -l, --link
+@item -l
+@itemx --link
Link files instead of copying them, when possible.
-@item -L, --dereference
+@item -L
+@itemx --dereference
Copy the file that a symbolic link points to, rather than the symbolic
link itself.
-@item -m, --preserve-modification-time
+@item -m
+@itemx --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
+@item -M @var{message}
+@itemx --message=@var{message}
+Print @var{message} when the end of a volume of the backup media (such as a
tape or a floppy disk) is reached, to prompt the user to insert a new
-volume. If MESSAGE contains the string "%d", it is replaced by the
+volume. If @var{message} contains the string @samp{%d}, it is replaced by the
current volume number (starting at 1).
-@item -n, --numeric-uid-gid
+@item -n
+@itemx --numeric-uid-gid
Show numeric UID and GID instead of translating them into names when using the
-@samp{--verbose option}.
+@option{--verbose} option.
@item --no-absolute-filenames
Create all files relative to the current directory in copy-in mode, even
@@ -461,47 +455,72 @@ 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
+@item -o
+@itemx --create
Run in copy-out mode.
@xref{Copy-out mode}.
-@item -O archive
+@item -O @var{archive}
Archive filename to use instead of standard output. To use a tape drive
on another machine as the archive, use a filename that starts with
-`HOSTNAME:'. The hostname can be preceded by a username and an `@@' to
+@samp{@var{hostname}:}, where @var{hostname} is the name or IP address
+of the machine. The hostname can be preceded by a username and an @samp{@@} to
access the remote tape drive as that user, if you have permission to do
-so (typically an entry in that user's `~/.rhosts' file).
+so (typically an entry in that user's @file{~/.rhosts} file).
@item --only-verify-crc
Verify the CRC's of each file in the archive, when reading a CRC format
archive. Don't actually extract the files.
-@item -p, --pass-through
+@item -p
+@itemx --pass-through
Run in copy-pass mode.
@xref{Copy-pass mode}.
@item --quiet
Do not print the number of blocks copied.
-@item -r, --rename
+@item -r
+@itemx --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
+@item -R @var{owner}
+@itemx --owner @var{owner}
+
+In copy-in and copy-pass mode, set the ownership of all files created
+to the specified @var{owner} (this operation is allowed only for the
+super-user). In copy-out mode, store the supplied owner information in
+the archive.
+
+The argument can be either the user name or the user name
+and group name, separated by a dot or a colon, or the group name,
+preceeded by a dot or a colon, as shown in the examples below:
+
+@smallexample
+@group
+cpio --owner smith
+cpio --owner smith:
+cpio --owner smith:users
+cpio --owner :users
+@end group
+@end smallexample
+
+@noindent
+If the group is omitted but the @samp{:} or @samp{.} separator is
+given, as in the second example. the given user's login group will be
+used.
+
+@item --rsh-command=@var{command}
+Notifies cpio that is should use @var{command} to communicate with remote
devices.
-@item -s, --swap-bytes
-Swap the bytes of each halfword (pair of bytes) in the files.This option
+@item -s
+@itemx --swap-bytes
+Swap the bytes of each halfword (pair of bytes) in the files. This option
can be used in copy-in mode.
-@item -S, --swap-halfwords
+@item -S
+@itemx --swap-halfwords
Swap the halfwords of each word (4 bytes) in the files. This option may
be used in copy-in mode.
@@ -509,29 +528,33 @@ be used in copy-in mode.
Write files with large blocks of zeros as sparse files. This option is
used in copy-in and copy-pass modes.
-@item -t, --list
+@item -t
+@itemx --list
Print a table of contents of the input.
-@item -u, --unconditional
+@item -u
+@itemx --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
+@item -v
+@itemx --verbose
+List the files processed, or with @option{-t}, give an @samp{ls -l} style
table of contents listing. In a verbose table of contents of a ustar
archive, user and group names in the archive that do not exist on the
local system are replaced by the names that correspond locally to the
numeric UID and GID stored in the archive.
-@item -V --dot
-Print a @kbd{.} for each file processed.
+@item -V
+@itemx --dot
+Print a @samp{.} for each file processed.
@item --version
Print the cpio program version number and exit.
@end table
-@node Media, Concept Index, Invoking `cpio', Top
+@node Media, Reports, Invoking cpio, Top
@comment node-name, next, previous, up
@chapter Magnetic Media
@cindex magnetic media
@@ -554,8 +577,24 @@ be protected from such fields to avoid damage to stored data. Sticking
a floppy disk to a filing cabinet using a magnet is probably not a good
idea.
+@node Reports, Concept Index, Media, Top
+@chapter Reporting bugs or suggestions
+
+It is possible you will encounter a bug in @command{cpio}.
+If this happens, we would like to hear about it. As the purpose of bug
+reporting is to improve software, please be sure to include maximum
+information when reporting a bug. The information needed is:
+
+@itemize @bullet
+@item Version of the package you are using.
+@item Compilation options used when configuring the package.
+@item Conditions under which the bug appears.
+@end itemize
+
+Send your report to <bug-cpio@@gnu.org>. Allow us a couple of
+days to answer.
-@node Concept Index, , Media, Top
+@node Concept Index, , Reports, Top
@comment node-name, next, previous, up
@unnumbered Concept Index
@printindex cp
diff --git a/doc/version.texi b/doc/version.texi
new file mode 100644
index 000000000000..c20cd8cc39c1
--- /dev/null
+++ b/doc/version.texi
@@ -0,0 +1,4 @@
+@set UPDATED 7 June 2007
+@set UPDATED-MONTH June 2007
+@set EDITION 2.8
+@set VERSION 2.8
diff --git a/lib/alloca_.h b/lib/alloca_.h
index 10995510e252..af274b9e7538 100644
--- a/lib/alloca_.h
+++ b/lib/alloca_.h
@@ -1,6 +1,6 @@
/* Memory allocation on the stack.
- Copyright (C) 1995, 1999, 2001, 2002, 2003, 2004 Free Software
+ Copyright (C) 1995, 1999, 2001-2004, 2006-2007 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
@@ -15,15 +15,13 @@
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,
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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
+/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
+ means there is a real alloca function. */
+#ifndef _GL_ALLOCA_H
+#define _GL_ALLOCA_H
/* alloca (N) returns a pointer to N bytes of memory
allocated on the stack, which will last until the function returns.
@@ -36,19 +34,21 @@
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
+#ifndef alloca
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# elif defined _AIX
+# define alloca __alloca
+# elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# include <stddef.h>
+# ifdef __cplusplus
extern "C"
-# endif
+# endif
void *alloca (size_t);
+# endif
#endif
-#endif /* _ALLOCA_H */
+#endif /* _GL_ALLOCA_H */
diff --git a/lib/argp-ba.c b/lib/argp-ba.c
index c4712284a9b8..8bb7309fdecd 100644
--- a/lib/argp-ba.c
+++ b/lib/argp-ba.c
@@ -15,7 +15,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* If set by the user program, it should point to string that is the
bug-reporting address for the program. It will be printed by argp_help if
diff --git a/lib/argp-eexst.c b/lib/argp-eexst.c
index d5cd28ceae26..bcab1c0c17fa 100644
--- a/lib/argp-eexst.c
+++ b/lib/argp-eexst.c
@@ -15,10 +15,10 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#include <sysexits.h>
diff --git a/lib/argp-fmtstream.c b/lib/argp-fmtstream.c
index c88c3db21471..0dd9256f570a 100644
--- a/lib/argp-fmtstream.c
+++ b/lib/argp-fmtstream.c
@@ -1,5 +1,5 @@
/* Word-wrapping and line-truncating streams
- Copyright (C) 1997,1998,1999,2001,2002,2003 Free Software Foundation, Inc.
+ Copyright (C) 1997-1999,2001,2002,2003,2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
@@ -15,13 +15,13 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* This package emulates glibc `line_wrap_stream' semantics for systems that
don't have that. */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#include <stdlib.h>
@@ -101,11 +101,10 @@ __argp_fmtstream_free (argp_fmtstream_t 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
+ __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
+#else
+ fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
#endif
- fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
}
free (fs->buf);
free (fs);
@@ -247,9 +246,10 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
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)
+ do
+ ++p;
+ while (p < nl && !isblank (*p));
if (p == nl)
{
/* It already ends a line. No fussing required. */
@@ -290,17 +290,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
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
+#ifdef _LIBC
+ __fxprintf (fs->stream, "%.*s\n",
+ (int) (nl - fs->buf), fs->buf);
+#else
+ if (nl > fs->buf)
+ fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
+ putc_unlocked ('\n', fs->stream);
#endif
- {
- 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;
}
@@ -359,15 +357,12 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
/* 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
+#ifdef _LIBC
+ __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
+ wrote = fs->p - fs->buf;
+#else
+ wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
#endif
- wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
if (wrote == fs->p - fs->buf)
{
fs->p = fs->buf;
diff --git a/lib/argp-fmtstream.h b/lib/argp-fmtstream.h
index e71df104ce91..e045a723da4e 100644
--- a/lib/argp-fmtstream.h
+++ b/lib/argp-fmtstream.h
@@ -1,5 +1,5 @@
/* Word-wrapping and line-truncating streams.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
@@ -15,7 +15,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* This package emulates glibc `line_wrap_stream' semantics for systems that
don't have that. If the system does have it, it is just a wrapper for
@@ -25,10 +25,6 @@
#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>
@@ -93,10 +89,6 @@ typedef FILE *argp_fmtstream_t;
#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
/* Guess we have to define our own version. */
-
-#ifndef __const
-#define __const const
-#endif
struct argp_fmtstream
{
@@ -137,22 +129,22 @@ 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, ...)
+ const char *__fmt, ...)
__attribute__ ((__format__ (printf, 2, 3)));
extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
- __const char *__fmt, ...)
+ 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 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);
+ const char *__str, size_t __len);
extern size_t argp_fmtstream_write (argp_fmtstream_t __fs,
- __const char *__str, size_t __len);
+ const char *__str, size_t __len);
/* Access macros for various bits of state. */
#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin)
@@ -211,7 +203,7 @@ extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
ARGP_FS_EI size_t
__argp_fmtstream_write (argp_fmtstream_t __fs,
- __const char *__str, size_t __len)
+ const char *__str, size_t __len)
{
if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
{
@@ -224,7 +216,7 @@ __argp_fmtstream_write (argp_fmtstream_t __fs,
}
ARGP_FS_EI int
-__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str)
+__argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str)
{
size_t __len = strlen (__str);
if (__len)
diff --git a/lib/argp-fs-xinl.c b/lib/argp-fs-xinl.c
index a4d14a2e58c5..3b4c917e020d 100644
--- a/lib/argp-fs-xinl.c
+++ b/lib/argp-fs-xinl.c
@@ -15,10 +15,10 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#define ARGP_FS_EI
diff --git a/lib/argp-help.c b/lib/argp-help.c
index 603576496186..396e73326f9d 100644
--- a/lib/argp-help.c
+++ b/lib/argp-help.c
@@ -1,5 +1,5 @@
/* Hierarchial argument parsing help output
- Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2005, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
@@ -15,14 +15,14 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#include <alloca.h>
@@ -89,15 +89,15 @@ struct uparams
int dup_args_note;
/* Various output columns. */
- int short_opt_col;
- int long_opt_col;
- int doc_opt_col;
- int opt_doc_col;
- int header_col;
- int usage_indent;
- int rmargin;
-
- int valid; /* True when the values in here are valid. */
+ int short_opt_col; /* column in which short options start */
+ int long_opt_col; /* column in which long options start */
+ int doc_opt_col; /* column in which doc options start */
+ int opt_doc_col; /* column in which option text starts */
+ int header_col; /* column in which group headers are printed */
+ int usage_indent; /* indentation of wrapped usage lines */
+ int rmargin; /* right margin used for wrapping */
+
+ int valid; /* True when the values in here are valid. */
};
/* This is a global variable, as user options are only ever read once. */
@@ -131,91 +131,126 @@ static const struct uparam_name uparam_names[] =
{ 0 }
};
-/* Read user options from the environment, and fill in UPARAMS appropiately. */
+static void
+validate_uparams (const struct argp_state *state, struct uparams *upptr)
+{
+ const struct uparam_name *up;
+
+ for (up = uparam_names; up->name; up++)
+ {
+ if (up->is_bool
+ || up->uparams_offs == offsetof (struct uparams, rmargin))
+ continue;
+ if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin)
+ {
+ __argp_failure (state, 0, 0,
+ dgettext (state->root_argp->argp_domain,
+ "\
+ARGP_HELP_FMT: %s value is less than or equal to %s"),
+ "rmargin", up->name);
+ return;
+ }
+ }
+ uparams = *upptr;
+ uparams.valid = 1;
+}
+
+/* Read user options from the environment, and fill in UPARAMS appropiately. */
static void
fill_in_uparams (const struct argp_state *state)
{
const char *var = getenv ("ARGP_HELP_FMT");
-
-#define SKIPWS(p) do { while (isspace (*p)) p++; } while (0);
+ struct uparams new_params = uparams;
+
+#define SKIPWS(p) do { while (isspace ((unsigned char) *p)) p++; } while (0);
if (var)
- /* Parse var. */
- while (*var)
- {
- SKIPWS (var);
-
- if (isalpha (*var))
- {
- size_t var_len;
- const struct uparam_name *un;
- int unspec = 0, val = 0;
- const char *arg = var;
-
- while (isalnum (*arg) || *arg == '-' || *arg == '_')
- arg++;
- var_len = arg - var;
-
- SKIPWS (arg);
+ {
+ /* Parse var. */
+ while (*var)
+ {
+ SKIPWS (var);
+
+ if (isalpha ((unsigned char) *var))
+ {
+ size_t var_len;
+ const struct uparam_name *un;
+ int unspec = 0, val = 0;
+ const char *arg = var;
- if (*arg == '\0' || *arg == ',')
- unspec = 1;
- else if (*arg == '=')
- {
+ while (isalnum ((unsigned char) *arg) || *arg == '-' || *arg == '_')
arg++;
- SKIPWS (arg);
- }
-
- if (unspec)
- {
- if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
- {
- val = 0;
- var += 3;
- var_len -= 3;
- }
- else
- val = 1;
- }
- else if (isdigit (*arg))
- {
- val = atoi (arg);
- while (isdigit (*arg))
+ var_len = arg - var;
+
+ SKIPWS (arg);
+
+ if (*arg == '\0' || *arg == ',')
+ unspec = 1;
+ else if (*arg == '=')
+ {
arg++;
- SKIPWS (arg);
- }
-
- for (un = uparam_names; un->name; un++)
- if (strlen (un->name) == var_len
- && strncmp (var, un->name, var_len) == 0)
+ SKIPWS (arg);
+ }
+
+ if (unspec)
{
- if (unspec && !un->is_bool)
- __argp_failure (state, 0, 0,
- dgettext (state->root_argp->argp_domain, "\
-%.*s: ARGP_HELP_FMT parameter requires a value"),
- (int) var_len, var);
+ if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
+ {
+ val = 0;
+ var += 3;
+ var_len -= 3;
+ }
else
- *(int *)((char *)&uparams + un->uparams_offs) = val;
- break;
+ val = 1;
}
- if (! un->name)
- __argp_failure (state, 0, 0,
- dgettext (state->root_argp->argp_domain, "\
+ else if (isdigit ((unsigned char) *arg))
+ {
+ val = atoi (arg);
+ while (isdigit ((unsigned char) *arg))
+ arg++;
+ SKIPWS (arg);
+ }
+
+ for (un = uparam_names; un->name; un++)
+ if (strlen (un->name) == var_len
+ && strncmp (var, un->name, var_len) == 0)
+ {
+ if (unspec && !un->is_bool)
+ __argp_failure (state, 0, 0,
+ dgettext (state->root_argp->argp_domain,
+ "\
+%.*s: ARGP_HELP_FMT parameter requires a value"),
+ (int) var_len, var);
+ else if (val < 0)
+ __argp_failure (state, 0, 0,
+ dgettext (state->root_argp->argp_domain,
+ "\
+%.*s: ARGP_HELP_FMT parameter must be positive"),
+ (int) var_len, var);
+ else
+ *(int *)((char *)&new_params + un->uparams_offs) = val;
+ break;
+ }
+ if (! un->name)
+ __argp_failure (state, 0, 0,
+ dgettext (state->root_argp->argp_domain, "\
%.*s: Unknown ARGP_HELP_FMT parameter"),
- (int) var_len, var);
+ (int) var_len, var);
- var = arg;
- if (*var == ',')
- var++;
- }
- else if (*var)
- {
- __argp_failure (state, 0, 0,
- dgettext (state->root_argp->argp_domain,
- "Garbage in ARGP_HELP_FMT: %s"), var);
- break;
- }
- }
+ var = arg;
+ if (*var == ',')
+ var++;
+ }
+ else if (*var)
+ {
+ __argp_failure (state, 0, 0,
+ dgettext (state->root_argp->argp_domain,
+ "Garbage in ARGP_HELP_FMT: %s"), var);
+ break;
+ }
+ }
+ validate_uparams (state, &new_params);
+ }
}
/* Returns true if OPT hasn't been marked invisible. Visibility only affects
@@ -340,6 +375,9 @@ struct hol_entry
/* The argp from which this option came. */
const struct argp *argp;
+
+ /* Position in the array */
+ unsigned ord;
};
/* A cluster of entries to reflect the argp tree structure. */
@@ -638,10 +676,12 @@ static int
hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
{
/* If one cluster is deeper than the other, use its ancestor at the same
- level, so that finding the common ancestor is straightforward. */
- while (cl1->depth < cl2->depth)
+ level, so that finding the common ancestor is straightforward.
+
+ clN->depth > 0 means that clN->parent != NULL (see hol_add_cluster) */
+ while (cl1->depth > cl2->depth)
cl1 = cl1->parent;
- while (cl2->depth < cl1->depth)
+ while (cl2->depth > cl1->depth)
cl2 = cl2->parent;
/* Now reduce both clusters to their ancestors at the point where both have
@@ -685,17 +725,19 @@ canon_doc_option (const char **name)
else
{
/* Skip initial whitespace. */
- while (isspace (**name))
+ while (isspace ((unsigned char) **name))
(*name)++;
/* Decide whether this looks like an option (leading `-') or not. */
non_opt = (**name != '-');
/* Skip until part of name used for sorting. */
- while (**name && !isalnum (**name))
+ while (**name && !isalnum ((unsigned char) **name))
(*name)++;
}
return non_opt;
}
+#define HOL_ENTRY_PTRCMP(a,b) ((a)->ord < (b)->ord ? -1 : 1)
+
/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help
listing. */
static int
@@ -705,6 +747,7 @@ hol_entry_cmp (const struct hol_entry *entry1,
/* The group numbers by which the entries should be ordered; if either is
in a cluster, then this is just the group within the cluster. */
int group1 = entry1->group, group2 = entry2->group;
+ int rc;
if (entry1->cluster != entry2->cluster)
{
@@ -721,7 +764,8 @@ hol_entry_cmp (const struct hol_entry *entry1,
return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
else
/* Both entries are in clusters, we can just compare the clusters. */
- return hol_cluster_cmp (entry1->cluster, entry2->cluster);
+ return (rc = hol_cluster_cmp (entry1->cluster, entry2->cluster)) ?
+ rc : HOL_ENTRY_PTRCMP(entry1, entry2);
}
else if (group1 == group2)
/* The entries are both in the same cluster and group, so compare them
@@ -745,7 +789,8 @@ hol_entry_cmp (const struct hol_entry *entry1,
return doc1 - doc2;
else if (!short1 && !short2 && long1 && long2)
/* Only long options. */
- return __strcasecmp (long1, long2);
+ return (rc = __strcasecmp (long1, long2)) ?
+ rc : HOL_ENTRY_PTRCMP(entry1, entry2);
else
/* Compare short/short, long/short, short/long, using the first
character of long options. Entries without *any* valid
@@ -762,13 +807,15 @@ hol_entry_cmp (const struct hol_entry *entry1,
#endif
/* Compare ignoring case, except when the options are both the
same letter, in which case lower-case always comes first. */
- return lower_cmp ? lower_cmp : first2 - first1;
+ return lower_cmp ? lower_cmp :
+ (rc = first2 - first1) ?
+ rc : HOL_ENTRY_PTRCMP(entry1, entry2);
}
}
else
/* Within the same cluster, but not the same group, so just compare
groups. */
- return group_cmp (group1, group2, 0);
+ return group_cmp (group1, group2, HOL_ENTRY_PTRCMP(entry1, entry2));
}
/* Version of hol_entry_cmp with correct signature for qsort. */
@@ -785,8 +832,14 @@ static void
hol_sort (struct hol *hol)
{
if (hol->num_entries > 0)
- qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
- hol_entry_qcmp);
+ {
+ unsigned i;
+ struct hol_entry *e;
+ for (i = 0, e = hol->entries; i < hol->num_entries; i++, e++)
+ e->ord = i;
+ qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
+ hol_entry_qcmp);
+ }
}
/* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow
@@ -1055,7 +1108,13 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
int old_wm = __argp_fmtstream_wmargin (stream);
/* PEST is a state block holding some of our variables that we'd like to
share with helper functions. */
- struct pentry_state pest = { entry, stream, hhstate, 1, state };
+ struct pentry_state pest;
+
+ pest.entry = entry;
+ pest.stream = stream;
+ pest.hhstate = hhstate;
+ pest.first = 1;
+ pest.state = state;
if (! odoc (real))
for (opt = real, num = entry->num; num > 0; opt++, num--)
@@ -1263,7 +1322,7 @@ usage_long_opt (const struct argp_option *opt,
if (! arg)
arg = real->arg;
- if (! (flags & OPTION_NO_USAGE))
+ if (! (flags & OPTION_NO_USAGE) && !odoc (opt))
{
if (arg)
{
@@ -1434,46 +1493,51 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
{
const char *text;
const char *inp_text;
+ size_t inp_text_len = 0;
+ const char *trans_text;
void *input = 0;
int anything = 0;
- size_t inp_text_limit = 0;
- const char *doc = dgettext (argp->argp_domain, argp->doc);
const struct argp_child *child = argp->children;
- if (doc)
+ if (argp->doc)
{
- char *vt = strchr (doc, '\v');
- inp_text = post ? (vt ? vt + 1 : 0) : doc;
- inp_text_limit = (!post && vt) ? (vt - doc) : 0;
+ char *vt = strchr (argp->doc, '\v');
+ if (vt)
+ {
+ if (post)
+ inp_text = vt + 1;
+ else
+ {
+ inp_text_len = vt - argp->doc;
+ inp_text = __strndup (argp->doc, inp_text_len);
+ }
+ }
+ else
+ inp_text = post ? 0 : argp->doc;
+ trans_text = inp_text ? dgettext (argp->argp_domain, inp_text) : NULL;
}
else
- inp_text = 0;
+ trans_text = inp_text = 0;
if (argp->help_filter)
/* We have to filter the doc strings. */
{
- if (inp_text_limit)
- /* Copy INP_TEXT so that it's nul-terminated. */
- inp_text = __strndup (inp_text, inp_text_limit);
input = __argp_input (argp, state);
text =
(*argp->help_filter) (post
? ARGP_KEY_HELP_POST_DOC
: ARGP_KEY_HELP_PRE_DOC,
- inp_text, input);
+ trans_text, input);
}
else
- text = (const char *) inp_text;
+ text = (const char *) trans_text;
if (text)
{
if (pre_blank)
__argp_fmtstream_putc (stream, '\n');
- if (text == inp_text && inp_text_limit)
- __argp_fmtstream_write (stream, inp_text, inp_text_limit);
- else
- __argp_fmtstream_puts (stream, text);
+ __argp_fmtstream_puts (stream, text);
if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
__argp_fmtstream_putc (stream, '\n');
@@ -1481,9 +1545,10 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
anything = 1;
}
- if (text && text != inp_text)
+ if (text && text != trans_text)
free ((char *) text); /* Free TEXT returned from the help filter. */
- if (inp_text && inp_text_limit && argp->help_filter)
+
+ if (inp_text && inp_text_len)
free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */
if (post && argp->help_filter)
@@ -1663,7 +1728,10 @@ Try `%s --help' or `%s --usage' for more information.\n"),
void __argp_help (const struct argp *argp, FILE *stream,
unsigned flags, char *name)
{
- _help (argp, 0, stream, flags, name);
+ struct argp_state state;
+ memset (&state, 0, sizeof state);
+ state.root_argp = argp;
+ _help (argp, &state, stream, flags, name);
}
#ifdef weak_alias
weak_alias (__argp_help, argp_help)
@@ -1674,8 +1742,7 @@ char *
__argp_short_program_name (void)
{
# if HAVE_DECL_PROGRAM_INVOCATION_NAME
- char *name = strrchr (program_invocation_name, '/');
- return name ? name + 1 : program_invocation_name;
+ return __argp_base_name (program_invocation_name);
# else
/* FIXME: What now? Miles suggests that it is better to use NULL,
but currently the value is passed on directly to fputs_unlocked,
@@ -1739,7 +1806,8 @@ __argp_error (const struct argp_state *state, const char *fmt, ...)
{
char *buf;
- __asprintf (&buf, fmt, ap);
+ if (__asprintf (&buf, fmt, ap) < 0)
+ buf = NULL;
__fwprintf (stream, L"%s: %s\n",
state ? state->name : __argp_short_program_name (),
@@ -1817,7 +1885,8 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
{
char *buf;
- __asprintf (&buf, fmt, ap);
+ if (__asprintf (&buf, fmt, ap) < 0)
+ buf = NULL;
__fwprintf (stream, L": %s", buf);
@@ -1857,7 +1926,8 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
#endif
#if !_LIBC
if (! s && ! (s = strerror (errnum)))
- s = "Unknown system error"; /* FIXME: translate this */
+ s = dgettext (state->root_argp->argp_domain,
+ "Unknown system error");
#endif
fputs (s, stream);
}
diff --git a/lib/argp-namefrob.h b/lib/argp-namefrob.h
index 09cafd083531..6fe99cd7aaf1 100644
--- a/lib/argp-namefrob.h
+++ b/lib/argp-namefrob.h
@@ -1,5 +1,5 @@
/* Name frobnication for compiling argp outside of glibc
- Copyright (C) 1997, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2003, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
@@ -15,7 +15,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#if !_LIBC
/* This code is written for inclusion in gnu-libc, and uses names in the
@@ -76,11 +76,6 @@
#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
@@ -141,14 +136,21 @@
# 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 GNULIB_ARGP_DISABLE_DIRNAME
+# define __argp_base_name(arg) arg
+#elif defined GNULIB_ARGP_EXTERN_BASENAME
+extern char *__argp_base_name(const char *arg);
+#else
+# include "dirname.h"
+# define __argp_base_name base_name
+#endif
+
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
# define __argp_short_program_name() (program_invocation_short_name)
#else
diff --git a/lib/argp-parse.c b/lib/argp-parse.c
index 9195b87a7709..a7de72902aae 100644
--- a/lib/argp-parse.c
+++ b/lib/argp-parse.c
@@ -15,13 +15,14 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#include <alloca.h>
+#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -37,11 +38,14 @@
#else
# include "gettext.h"
#endif
-#define N_(msgid) (msgid)
+#define N_(msgid) msgid
#include "argp.h"
#include "argp-namefrob.h"
+#define alignof(type) offsetof (struct { char c; type x; }, x)
+#define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d))
+
/* Getopt return values. */
#define KEY_END (-1) /* The end of the options. */
#define KEY_ARG 1 /* A non-option argument. */
@@ -75,11 +79,11 @@ static volatile int _argp_hang;
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},
+ {"help", '?', 0, 0, N_("give this help list"), -1},
+ {"usage", OPT_USAGE, 0, 0, N_("give a short usage message"), 0},
+ {"program-name",OPT_PROGNAME,N_("NAME"), OPTION_HIDDEN, N_("set the program name"), 0},
+ {"HANG", OPT_HANG, N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
+ N_("hang for SECS seconds (default 3600)"), 0},
{NULL, 0, 0, 0, NULL, 0}
};
@@ -93,7 +97,7 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
break;
case OPT_USAGE:
__argp_state_help (state, state->out_stream,
- ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
+ ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
break;
case OPT_PROGNAME: /* Set the program name. */
@@ -105,11 +109,7 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
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;
+ state->name = __argp_base_name (arg);
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
program_invocation_short_name = state->name;
@@ -140,7 +140,7 @@ static const struct argp argp_default_argp =
static const struct argp_option argp_version_options[] =
{
- {"version", 'V', 0, 0, N_("Print program version"), -1},
+ {"version", 'V', 0, 0, N_("print program version"), -1},
{NULL, 0, 0, 0, NULL, 0}
};
@@ -462,6 +462,11 @@ parser_init (struct parser *parser, const struct argp *argp,
struct group *group;
struct parser_sizes szs;
struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
+ char *storage;
+ size_t glen, gsum;
+ size_t clen, csum;
+ size_t llen, lsum;
+ size_t slen, ssum;
szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
szs.long_len = 0;
@@ -472,22 +477,33 @@ parser_init (struct parser *parser, const struct argp *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);
+ glen = (szs.num_groups + 1) * sizeof (struct group);
+ clen = szs.num_child_inputs * sizeof (void *);
+ llen = (szs.long_len + 1) * sizeof (struct option);
+ slen = szs.short_len + 1;
+
+ /* Sums of previous lengths, properly aligned. There's no need to
+ align gsum, since struct group is aligned at least as strictly as
+ void * (since it contains a void * member). And there's no need
+ to align lsum, since struct option is aligned at least as
+ strictly as char. */
+ gsum = glen;
+ csum = alignto (gsum + clen, alignof (struct option));
+ lsum = csum + llen;
+ ssum = lsum + slen;
+
+ parser->storage = malloc (ssum);
if (! parser->storage)
return ENOMEM;
+ storage = parser->storage;
parser->groups = parser->storage;
- parser->child_inputs = parser->storage + GLEN;
- parser->long_opts = parser->storage + GLEN + CLEN;
- parser->short_opts = parser->storage + GLEN + CLEN + LLEN;
+ parser->child_inputs = (void **) (storage + gsum);
+ parser->long_opts = (struct option *) (storage + csum);
+ parser->short_opts = storage + lsum;
parser->opt_data = opt_data;
- memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *));
+ memset (parser->child_inputs, 0, clen);
parser_convert (parser, argp, flags);
memset (&parser->state, 0, sizeof (struct argp_state));
@@ -542,10 +558,7 @@ parser_init (struct parser *parser, const struct argp *argp,
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];
- }
+ parser->state.name = __argp_base_name (argv[0]);
else
parser->state.name = __argp_short_program_name ();
@@ -864,6 +877,20 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
to be parsed (which in some cases isn't actually an error). */
int arg_ebadkey = 0;
+#ifndef _LIBC
+ if (!(flags & ARGP_PARSE_ARGV0))
+ {
+#ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME
+ if (!program_invocation_name)
+ program_invocation_name = argv[0];
+#endif
+#ifdef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+ if (!program_invocation_short_name)
+ program_invocation_short_name = __argp_base_name (argv[0]);
+#endif
+ }
+#endif
+
if (! (flags & ARGP_NO_HELP))
/* Add our own options. */
{
diff --git a/lib/argp-pin.c b/lib/argp-pin.c
new file mode 100644
index 000000000000..852c6d6d9388
--- /dev/null
+++ b/lib/argp-pin.c
@@ -0,0 +1,28 @@
+/* Full and short program names for argp module
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
+char *program_invocation_short_name = 0;
+#endif
+#ifndef HAVE_PROGRAM_INVOCATION_NAME
+char *program_invocation_name = 0;
+#endif
+
diff --git a/lib/argp-pv.c b/lib/argp-pv.c
index f93a22eda8fb..a11298bfabd8 100644
--- a/lib/argp-pv.c
+++ b/lib/argp-pv.c
@@ -1,5 +1,5 @@
/* Default definition for ARGP_PROGRAM_VERSION.
- Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1999, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
@@ -15,10 +15,10 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* If set by the user program to a non-zero value, then a default option
--version is added (unless the ARGP_NO_HELP flag is used), which will
- print this this string followed by a newline and exit (unless the
+ print this string followed by a newline and exit (unless the
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
const char *argp_program_version;
diff --git a/lib/argp-pvh.c b/lib/argp-pvh.c
index 5474251bb711..6bf7c49b814a 100644
--- a/lib/argp-pvh.c
+++ b/lib/argp-pvh.c
@@ -15,10 +15,10 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#include "argp.h"
diff --git a/lib/argp-xinl.c b/lib/argp-xinl.c
index 51d3e20c8237..a6afb1f739a3 100644
--- a/lib/argp-xinl.c
+++ b/lib/argp-xinl.c
@@ -15,10 +15,10 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#if defined _LIBC || defined HAVE_FEATURES_H
diff --git a/lib/argp.h b/lib/argp.h
index 0c65a4cbd309..1c4e06f8fe56 100644
--- a/lib/argp.h
+++ b/lib/argp.h
@@ -1,5 +1,5 @@
/* Hierarchial argument parsing, layered over getopt.
- Copyright (C) 1995-1999,2003,2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-1999,2003-2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
@@ -15,7 +15,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef _ARGP_H
#define _ARGP_H
@@ -23,14 +23,11 @@
#include <stdio.h>
#include <ctype.h>
#include <getopt.h>
+#include <limits.h>
#define __need_error_t
#include <errno.h>
-#ifndef __const
-# define __const const
-#endif
-
#ifndef __THROW
# define __THROW
#endif
@@ -52,10 +49,12 @@
#endif
/* GCC 2.95 and later have "__restrict"; C99 compilers have
- "restrict", and "configure" may have defined "restrict". */
+ "restrict", and "configure" may have defined "restrict".
+ Other compilers use __restrict, __restrict__, and _Restrict, and
+ 'configure' might #define 'restrict' to those words. */
#ifndef __restrict
# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
-# if defined restrict || 199901L <= __STDC_VERSION__
+# if 199901L <= __STDC_VERSION__
# define __restrict restrict
# else
# define __restrict
@@ -81,7 +80,7 @@ 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;
+ const char *name;
/* What key is returned for this option. If > 0 and printable, then it's
also accepted as a short option. */
@@ -89,7 +88,7 @@ struct argp_option
/* 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;
+ const char *arg;
/* OPTION_ flags. */
int flags;
@@ -97,8 +96,11 @@ struct argp_option
/* 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;
+ group); in this usage, it's conventional to end the string with a `:'.
+
+ Write the initial value as N_("TEXT") if you want xgettext to collect
+ it into a POT file. */
+ const char *doc;
/* The group this option is in. In a long help message, options are sorted
alphabetically within each group, and the groups presented in the order
@@ -226,7 +228,7 @@ 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;
+ 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
@@ -242,12 +244,14 @@ struct argp
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;
+ 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;
+ `\v' character).
+ Write the initial value as N_("BEFORE-TEXT") "\v" N_("AFTER-TEXT") if
+ you want xgettext to collect the two pieces of text into a POT file. */
+ const char *doc;
/* A vector of argp_children structures, terminated by a member with a 0
argp field, pointing to child argps should be parsed with this one. Any
@@ -255,7 +259,7 @@ struct argp
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;
+ 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
@@ -267,7 +271,7 @@ struct argp
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);
+ 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
@@ -291,7 +295,7 @@ struct argp
struct argp_child
{
/* The child parser. */
- __const struct argp *argp;
+ const struct argp *argp;
/* Flags for this child. */
int flags;
@@ -300,7 +304,7 @@ struct argp_child
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;
+ 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
@@ -316,7 +320,7 @@ struct argp_child
struct argp_state
{
/* The top level ARGP being parsed. */
- __const struct argp *root_argp;
+ const struct argp *root_argp;
/* The argument vector being parsed. May be modified. */
int argc;
@@ -410,22 +414,36 @@ struct argp_state
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,
+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,
+extern error_t __argp_parse (const struct argp *__restrict __argp,
+ int /*argc*/, char **__restrict /*argv*/,
unsigned __flags, int *__restrict __arg_index,
void *__restrict __input);
/* Global variables. */
+/* GNULIB makes sure both program_invocation_name and
+ program_invocation_short_name are available */
+#ifdef GNULIB_PROGRAM_INVOCATION_NAME
+extern char *program_invocation_name;
+# undef HAVE_DECL_PROGRAM_INVOCATION_NAME
+# define HAVE_DECL_PROGRAM_INVOCATION_NAME 1
+#endif
+
+#ifdef GNULIB_PROGRAM_INVOCATION_SHORT_NAME
+extern char *program_invocation_short_name;
+# undef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+# define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 1
+#endif
+
/* If defined or set by the user program to a non-zero value, then a default
option --version is added (unless the ARGP_NO_HELP flag is used), which
will print this string followed by a newline and exit (unless the
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
-extern __const char *argp_program_version;
+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
@@ -441,7 +459,7 @@ extern void (*argp_program_version_hook) (FILE *__restrict __stream,
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;
+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
@@ -479,10 +497,10 @@ extern error_t argp_err_exit_status;
/* Output a usage message for ARGP to STREAM. FLAGS are from the set
ARGP_HELP_*. */
-extern void argp_help (__const struct argp *__restrict __argp,
+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,
+extern void __argp_help (const struct argp *__restrict __argp,
FILE *__restrict __stream, unsigned __flags,
char *__name);
@@ -496,25 +514,25 @@ extern void __argp_help (__const struct argp *__restrict __argp,
/* 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,
+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,
+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);
+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, ...)
+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, ...)
+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
@@ -525,31 +543,31 @@ extern void __argp_error (__const struct argp_state *__restrict __state,
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,
+extern void argp_failure (const struct argp_state *__restrict __state,
int __status, int __errnum,
- __const char *__restrict __fmt, ...)
+ const char *__restrict __fmt, ...)
__attribute__ ((__format__ (__printf__, 4, 5)));
-extern void __argp_failure (__const struct argp_state *__restrict __state,
+extern void __argp_failure (const struct argp_state *__restrict __state,
int __status, int __errnum,
- __const char *__restrict __fmt, ...)
+ 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;
+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;
+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)
+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)
+extern void *__argp_input (const struct argp *__restrict __argp,
+ const struct argp_state *__restrict __state)
__THROW;
#ifdef __USE_EXTERN_INLINES
@@ -566,25 +584,25 @@ extern void *__argp_input (__const struct argp *__restrict __argp,
# endif
ARGP_EI void
-__NTH (__argp_usage (__const struct argp_state *__state))
+__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))
+__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);
+ return __key > 0 && __key <= UCHAR_MAX && isprint (__key);
}
}
ARGP_EI int
-__NTH (__option_is_end (__const struct argp_option *__opt))
+__NTH (__option_is_end (const struct argp_option *__opt))
{
return !__opt->key && !__opt->name && !__opt->doc && !__opt->group;
}
diff --git a/lib/basename.c b/lib/basename.c
index adb9f02ff008..fbe17ff910c8 100644
--- a/lib/basename.c
+++ b/lib/basename.c
@@ -1,6 +1,6 @@
-/* basename.c -- return the last element in a path
+/* basename.c -- return the last element in a file name
- Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004 Free
+ Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 Free
Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -15,65 +15,115 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
#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.
+#include <string.h>
+#include "xalloc.h"
+#include "xstrndup.h"
- 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. */
+/* Return the address of the last file name component of NAME. If
+ NAME has no relative file name components because it is a file
+ system root, return the empty string. */
char *
-base_name (char const *name)
+last_component (char const *name)
{
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
char const *p;
+ bool saw_slash = false;
+
+ while (ISSLASH (*base))
+ base++;
for (p = base; *p; p++)
{
if (ISSLASH (*p))
+ saw_slash = true;
+ else if (saw_slash)
{
- /* 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;
+ saw_slash = false;
}
}
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. */
+
+/* In general, we can't use the builtin `basename' function if available,
+ since it has different meanings in different environments.
+ In some environments the builtin `basename' modifies its argument.
+
+ Return the last file name component of NAME, allocated with
+ xmalloc. On systems with drive letters, a leading "./"
+ distinguishes relative names that would otherwise look like a drive
+ letter. Unlike POSIX basename(), NAME cannot be NULL,
+ base_name("") returns "", and the first trailing slash is not
+ stripped.
+
+ If lstat (NAME) would succeed, then { chdir (dir_name (NAME));
+ lstat (base_name (NAME)); } will access the same file. Likewise,
+ if the sequence { chdir (dir_name (NAME));
+ rename (base_name (NAME), "foo"); } succeeds, you have renamed NAME
+ to "foo" in the same directory NAME was in. */
+
+char *
+base_name (char const *name)
+{
+ char const *base = last_component (name);
+ size_t length;
+
+ /* If there is no last component, then name is a file system root or the
+ empty string. */
+ if (! *base)
+ return xstrndup (name, base_len (name));
+
+ /* Collapse a sequence of trailing slashes into one. */
+ length = base_len (base);
+ if (ISSLASH (base[length]))
+ length++;
+
+ /* On systems with drive letters, `a/b:c' must return `./b:c' rather
+ than `b:c' to avoid confusion with a drive letter. On systems
+ with pure POSIX semantics, this is not an issue. */
+ if (FILE_SYSTEM_PREFIX_LEN (base))
+ {
+ char *p = xmalloc (length + 3);
+ p[0] = '.';
+ p[1] = '/';
+ memcpy (p + 2, base, length);
+ p[length + 2] = '\0';
+ return p;
+ }
+
+ /* Finally, copy the basename. */
+ return xstrndup (base, length);
+}
+
+/* Return the length of the basename NAME. Typically NAME is the
+ value returned by base_name or last_component. Act like strlen
+ (NAME), except omit all trailing slashes. */
size_t
base_len (char const *name)
{
size_t len;
+ size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
continue;
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
+ && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
+ return 2;
+
+ if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
+ && len == prefix_len && ISSLASH (name[prefix_len]))
+ return prefix_len + 1;
+
return len;
}
diff --git a/lib/dirname.c b/lib/dirname.c
index 7671a0d62e43..16552c64d2a3 100644
--- a/lib/dirname.c
+++ b/lib/dirname.c
@@ -1,6 +1,6 @@
-/* dirname.c -- return all but the last element in a path
+/* dirname.c -- return all but the last element in a file name
- Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004 Free Software
+ Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -15,107 +15,71 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
#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). */
+/* Return the length of the prefix of FILE that will be used by
+ dir_name. If FILE is in the working directory, this returns zero
+ even though `dir_name (FILE)' will return ".". Works properly even
+ if there are trailing slashes (by effectively ignoring them). */
+
size_t
-dir_len (char const *path)
+dir_len (char const *file)
{
- size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (path);
+ size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
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). */
+ /* Advance prefix_length beyond important leading slashes. */
+ prefix_length += (prefix_length != 0
+ ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+ && ISSLASH (file[prefix_length]))
+ : (ISSLASH (file[0])
+ ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
+ && ISSLASH (file[1]) && ! ISSLASH (file[2])
+ ? 2 : 1))
+ : 0));
-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;
+ /* Strip the basename and any redundant slashes before it. */
+ for (length = last_component (file) - file;
+ prefix_length < length; length--)
+ if (! ISSLASH (file[length - 1]))
+ break;
+ return length;
}
-#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
+/* In general, we can't use the builtin `dirname' function if available,
+ since it has different meanings in different environments.
+ In some environments the builtin `dirname' modifies its argument.
-*/
+ Return the leading directories part of FILE, allocated with xmalloc.
+ Works properly even if there are trailing slashes (by effectively
+ ignoring them). Unlike POSIX dirname(), FILE cannot be NULL.
-# define MAX_BUFF_LEN 1024
-# include <stdio.h>
+ If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
+ lstat (base_name (FILE)); } will access the same file. Likewise,
+ if the sequence { chdir (dir_name (FILE));
+ rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
+ to "foo" in the same directory FILE was in. */
-char *program_name;
-
-int
-main (int argc, char *argv[])
+char *
+dir_name (char const *file)
{
- 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;
+ size_t length = dir_len (file);
+ bool append_dot = (length == 0
+ || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+ && length == FILE_SYSTEM_PREFIX_LEN (file)
+ && file[2] != '\0' && ! ISSLASH (file[2])));
+ char *dir = xmalloc (length + append_dot + 1);
+ memcpy (dir, file, length);
+ if (append_dot)
+ dir[length++] = '.';
+ dir[length] = '\0';
+ return dir;
}
-#endif
diff --git a/lib/dirname.h b/lib/dirname.h
index bc2400a7d0a8..91e7ed33666f 100644
--- a/lib/dirname.h
+++ b/lib/dirname.h
@@ -1,6 +1,6 @@
/* Take file names apart into directory and base names.
- Copyright (C) 1998, 2001, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2003-2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef DIRNAME_H_
# define DIRNAME_H_ 1
@@ -31,17 +31,40 @@
# endif
# ifndef FILE_SYSTEM_PREFIX_LEN
-# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
+# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
+ /* This internal macro assumes ASCII, but all hosts that support drive
+ letters use ASCII. */
+# define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \
+ <= 'z' - 'a')
+# define FILE_SYSTEM_PREFIX_LEN(Filename) \
+ (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
+# else
+# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
+# endif
# endif
-# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
+# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
+# endif
+
+# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
+# endif
+
+# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
+# else
+# define IS_ABSOLUTE_FILE_NAME(F) \
+ (ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F))
+# endif
# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
-char *base_name (char const *path);
-char *dir_name (char const *path);
-size_t base_len (char const *path);
-size_t dir_len (char const *path);
+char *base_name (char const *file);
+char *dir_name (char const *file);
+size_t base_len (char const *file);
+size_t dir_len (char const *file);
+char *last_component (char const *file);
-bool strip_trailing_slashes (char *path);
+bool strip_trailing_slashes (char *file);
#endif /* not DIRNAME_H_ */
diff --git a/lib/error.c b/lib/error.c
index 9bb3e558cb8b..cf8634332020 100644
--- a/lib/error.c
+++ b/lib/error.c
@@ -1,5 +1,5 @@
/* Error handler for noninteractive utilities
- Copyright (C) 1990-1998, 2000-2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1990-1998, 2000-2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify
@@ -14,11 +14,11 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
-#ifdef HAVE_CONFIG_H
+#if !_LIBC
# include <config.h>
#endif
@@ -29,13 +29,14 @@
#include <stdlib.h>
#include <string.h>
-#ifdef _LIBC
-# include <libintl.h>
-#else
+#if !_LIBC && ENABLE_NLS
# include "gettext.h"
#endif
#ifdef _LIBC
+# include <libintl.h>
+# include <stdbool.h>
+# include <stdint.h>
# include <wchar.h>
# define mbsrtowcs __mbsrtowcs
#endif
@@ -61,6 +62,7 @@ unsigned int error_message_count;
# define program_name program_invocation_name
# include <errno.h>
+# include <limits.h>
# include <libio/libioP.h>
/* In GNU libc we want do not want to use the common name `error' directly.
@@ -90,23 +92,19 @@ extern void __error_at_line (int status, int errnum, const char *file_name,
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 /* HAVE_STRERROR_R || defined strerror_r */
#endif /* not _LIBC */
static void
print_errno_message (int errnum)
{
- char const *s = NULL;
+ char const *s;
#if defined HAVE_STRERROR_R || _LIBC
char errbuf[1024];
@@ -115,23 +113,23 @@ print_errno_message (int errnum)
# else
if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
s = errbuf;
+ else
+ s = 0;
# endif
+#else
+ s = strerror (errnum);
#endif
#if !_LIBC
- if (! s && ! (s = strerror (errnum)))
+ if (! s)
s = _("Unknown system error");
#endif
#if _LIBC
- if (_IO_fwide (stderr, 0) > 0)
- {
- __fwprintf (stderr, L": %s", s);
- return;
- }
-#endif
-
+ __fxprintf (NULL, ": %s", s);
+#else
fprintf (stderr, ": %s", s);
+#endif
}
static void
@@ -142,26 +140,65 @@ error_tail (int status, int errnum, const char *message, va_list args)
{
# 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)
+ wchar_t *wmessage = NULL;
+ mbstate_t st;
+ size_t res;
+ const char *tmp;
+ bool use_malloc = false;
+
+ while (1)
{
- size_t res;
- mbstate_t st;
- const char *tmp = message;
+ if (__libc_use_alloca (len * sizeof (wchar_t)))
+ wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
+ else
+ {
+ if (!use_malloc)
+ wmessage = NULL;
+
+ wchar_t *p = (wchar_t *) realloc (wmessage,
+ len * sizeof (wchar_t));
+ if (p == NULL)
+ {
+ free (wmessage);
+ fputws_unlocked (L"out of memory\n", stderr);
+ return;
+ }
+ wmessage = p;
+ use_malloc = true;
+ }
+
memset (&st, '\0', sizeof (st));
- res = mbsrtowcs (wbuf, &tmp, len, &st);
- wmessage = res == (size_t) -1 ? L"???" : wbuf;
+ tmp = message;
+
+ res = mbsrtowcs (wmessage, &tmp, len, &st);
+ if (res != len)
+ break;
+
+ if (__builtin_expect (len >= SIZE_MAX / 2, 0))
+ {
+ /* This really should not happen if everything is fine. */
+ res = (size_t) -1;
+ break;
+ }
+
+ len *= 2;
+ }
+
+ if (res == (size_t) -1)
+ {
+ /* The string cannot be converted. */
+ if (use_malloc)
+ {
+ free (wmessage);
+ use_malloc = false;
+ }
+ wmessage = (wchar_t *) L"???";
}
__vfwprintf (stderr, wmessage, args);
- if (! (len < ALLOCA_LIMIT))
- free (wbuf);
+
+ if (use_malloc)
+ free (wmessage);
}
else
#endif
@@ -172,11 +209,10 @@ error_tail (int status, int errnum, const char *message, va_list args)
if (errnum)
print_errno_message (errnum);
#if _LIBC
- if (_IO_fwide (stderr, 0) > 0)
- putwc (L'\n', stderr);
- else
+ __fxprintf (NULL, "\n");
+#else
+ putc ('\n', stderr);
#endif
- putc ('\n', stderr);
fflush (stderr);
if (status)
exit (status);
@@ -209,11 +245,10 @@ error (int status, int errnum, const char *message, ...)
else
{
#if _LIBC
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s: ", program_name);
- else
+ __fxprintf (NULL, "%s: ", program_name);
+#else
+ fprintf (stderr, "%s: ", program_name);
#endif
- fprintf (stderr, "%s: ", program_name);
}
va_start (args, message);
@@ -269,22 +304,19 @@ error_at_line (int status, int errnum, const char *file_name,
else
{
#if _LIBC
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s: ", program_name);
- else
+ __fxprintf (NULL, "%s:", program_name);
+#else
+ fprintf (stderr, "%s:", program_name);
#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
+ __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
+ file_name, line_number);
+#else
+ fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
+ file_name, line_number);
#endif
- fprintf (stderr, "%s:%d: ", file_name, line_number);
- }
va_start (args, message);
error_tail (status, errnum, message, args);
diff --git a/lib/error.h b/lib/error.h
index 8ed63595f24f..5a5f2476583d 100644
--- a/lib/error.h
+++ b/lib/error.h
@@ -1,5 +1,5 @@
/* Declaration for error-reporting function
- Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify
@@ -14,14 +14,14 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef _ERROR_H
#define _ERROR_H 1
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
# define __attribute__(Spec) /* empty */
# endif
/* The __-protected variants of `format' and `printf' attributes
diff --git a/lib/exitfail.c b/lib/exitfail.c
index 2ae5f69555f4..373d325c5ad7 100644
--- a/lib/exitfail.c
+++ b/lib/exitfail.c
@@ -1,6 +1,6 @@
/* Failure exit status
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,13 +15,12 @@
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. */
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
#include "exitfail.h"
-#include "exit.h"
+
+#include <stdlib.h>
int volatile exit_failure = EXIT_FAILURE;
diff --git a/lib/exitfail.h b/lib/exitfail.h
index cf5ab719586e..e46cf9c16656 100644
--- a/lib/exitfail.h
+++ b/lib/exitfail.h
@@ -15,6 +15,6 @@
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. */
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
extern int volatile exit_failure;
diff --git a/lib/fatal.c b/lib/fatal.c
new file mode 100644
index 000000000000..bcce42c090aa
--- /dev/null
+++ b/lib/fatal.c
@@ -0,0 +1,27 @@
+/* This file is part of GNU cpio.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
+
+#include <system.h>
+#include <paxlib.h>
+
+void
+fatal_exit ()
+{
+ exit (PAXEXIT_FAILURE);
+}
+
diff --git a/lib/full-write.c b/lib/full-write.c
index d119977e79d1..cc168720eae9 100644
--- a/lib/full-write.c
+++ b/lib/full-write.c
@@ -1,7 +1,7 @@
/* 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.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,11 +15,9 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
/* Specification. */
#ifdef FULL_READ
@@ -62,7 +60,7 @@ size_t
full_rw (int fd, const void *buf, size_t count)
{
size_t total = 0;
- const char *ptr = buf;
+ const char *ptr = (const char *) buf;
while (count > 0)
{
diff --git a/lib/full-write.h b/lib/full-write.h
index 2637903ecda4..d20d2fe4abdf 100644
--- a/lib/full-write.h
+++ b/lib/full-write.h
@@ -14,7 +14,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <stddef.h>
diff --git a/lib/getopt.c b/lib/getopt.c
index ef790b79e07a..3580ad825c64 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -2,7 +2,7 @@
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to drepper@gnu.org
before changing it!
- Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004
+ Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -18,32 +18,20 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
- Ditto for AIX 3.2 and <stdlib.h>. */
-#ifndef _NO_PROTO
-# define _NO_PROTO
-#endif
-
-#ifdef HAVE_CONFIG_H
+#ifndef _LIBC
# include <config.h>
#endif
-#include <stdio.h>
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
- contain conflicting prototypes for getopt. */
-# include <stdlib.h>
-# include <unistd.h>
-#endif /* GNU C library. */
+#include "getopt.h"
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
-#ifdef VMS
+#ifdef __VMS
# include <unixlib.h>
#endif
@@ -76,7 +64,6 @@
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
-#include "getopt.h"
#include "getopt_int.h"
/* For communication from `getopt' to the caller.
@@ -118,16 +105,9 @@ int optopt = '?';
static struct _getopt_data getopt_data;
-#ifndef __GNU_LIBRARY__
-
-/* Avoid depending on library functions or files
- whose names are inconsistent. */
-
-#ifndef getenv
+#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV
extern char *getenv ();
#endif
-
-#endif /* not __GNU_LIBRARY__ */
#ifdef _LIBC
/* Stored original parameters.
@@ -556,10 +536,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s", buf);
- else
- fputs (buf, stderr);
+ __fxprintf (NULL, "%s", buf);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
@@ -634,10 +611,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL;
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s", buf);
- else
- fputs (buf, stderr);
+ __fxprintf (NULL, "%s", buf);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
@@ -674,10 +648,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL;
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s", buf);
- else
- fputs (buf, stderr);
+ __fxprintf (NULL, "%s", buf);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
@@ -751,10 +722,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s", buf);
- else
- fputs (buf, stderr);
+ __fxprintf (NULL, "%s", buf);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
@@ -817,10 +785,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s", buf);
- else
- fputs (buf, stderr);
+ __fxprintf (NULL, "%s", buf);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
@@ -868,10 +833,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s", buf);
- else
- fputs (buf, stderr);
+ __fxprintf (NULL, "%s", buf);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
@@ -940,10 +902,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s", buf);
- else
- fputs (buf, stderr);
+ __fxprintf (NULL, "%s", buf);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
@@ -985,10 +944,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL;
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s", buf);
- else
- fputs (buf, stderr);
+ __fxprintf (NULL, "%s", buf);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
@@ -1027,10 +983,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL;
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s", buf);
- else
- fputs (buf, stderr);
+ __fxprintf (NULL, "%s", buf);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
@@ -1101,10 +1054,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
- if (_IO_fwide (stderr, 0) > 0)
- __fwprintf (stderr, L"%s", buf);
- else
- fputs (buf, stderr);
+ __fxprintf (NULL, "%s", buf);
((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr);
diff --git a/lib/getopt1.c b/lib/getopt1.c
index a7472371fa20..cc0746ea43ce 100644
--- a/lib/getopt1.c
+++ b/lib/getopt1.c
@@ -1,5 +1,5 @@
/* 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
+ Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004,2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -15,15 +15,12 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#ifdef _LIBC
# include <getopt.h>
#else
+# include <config.h>
# include "getopt.h"
#endif
#include "getopt_int.h"
diff --git a/lib/getopt_.h b/lib/getopt_.h
index 83ac8b12844b..615ef9a3b6fe 100644
--- a/lib/getopt_.h
+++ b/lib/getopt_.h
@@ -1,5 +1,5 @@
/* Declarations for getopt.
- Copyright (C) 1989-1994,1996-1999,2001,2003,2004
+ Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005,2006,2007
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -15,7 +15,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef _GETOPT_H
@@ -34,9 +34,7 @@
#if defined __GETOPT_PREFIX && !defined __need_getopt
# include <stdlib.h>
# include <stdio.h>
-# if HAVE_UNISTD_H
-# include <unistd.h>
-# endif
+# include <unistd.h>
# undef __need_getopt
# undef getopt
# undef getopt_long
@@ -67,14 +65,14 @@
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
+# if defined __GETOPT_PREFIX
# define __getopt_argv_const /* empty */
# else
# define __getopt_argv_const const
@@ -103,7 +101,7 @@
# endif
#endif
-#ifdef __cplusplus
+#ifdef __cplusplus
extern "C" {
#endif
@@ -198,9 +196,10 @@ struct option
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'. */
+ If OPTS begins with `-', then non-option arguments are treated as
+ arguments to the option '\1'. This behavior is specific to the GNU
+ `getopt'. If OPTS begins with `+', or POSIXLY_CORRECT is set in
+ the environment, then do not permute arguments. */
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
__THROW;
@@ -217,7 +216,7 @@ extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
#endif
-#ifdef __cplusplus
+#ifdef __cplusplus
}
#endif
diff --git a/lib/getopt_int.h b/lib/getopt_int.h
index e5bc3f2fd517..401579fd2898 100644
--- a/lib/getopt_int.h
+++ b/lib/getopt_int.h
@@ -15,7 +15,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1
diff --git a/lib/gettext.h b/lib/gettext.h
index 835732e01fe5..9d76ec9afccf 100644
--- a/lib/gettext.h
+++ b/lib/gettext.h
@@ -1,5 +1,5 @@
/* Convenience header for conditional use of GNU <libintl.h>.
- Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,7 +13,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef _LIBGETTEXT_H
#define _LIBGETTEXT_H 1
@@ -24,6 +24,18 @@
/* Get declarations of GNU message catalog functions. */
# include <libintl.h>
+/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
+ the gettext() and ngettext() macros. This is an alternative to calling
+ textdomain(), and is useful for libraries. */
+# ifdef DEFAULT_TEXT_DOMAIN
+# undef gettext
+# define gettext(Msgid) \
+ dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
+# undef ngettext
+# define ngettext(Msgid1, Msgid2, N) \
+ dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
+# endif
+
#else
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
@@ -36,23 +48,38 @@
# include <locale.h>
#endif
+/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
+ <libintl.h>, which chokes if dcgettext is defined as a macro. So include
+ it now, to make later inclusions of <libintl.h> a NOP. */
+#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
+# include <cstdlib>
+# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
+# include <libintl.h>
+# endif
+#endif
+
/* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings
for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */
# define gettext(Msgid) ((const char *) (Msgid))
-# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
-# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
+# define dcgettext(Domainname, Msgid, Category) \
+ ((void) (Category), dgettext (Domainname, Msgid))
# define ngettext(Msgid1, Msgid2, N) \
- ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+ ((N) == 1 \
+ ? ((void) (Msgid2), (const char *) (Msgid1)) \
+ : ((void) (Msgid1), (const char *) (Msgid2)))
# define dngettext(Domainname, Msgid1, Msgid2, N) \
- ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+ ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
- ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+ ((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
# define textdomain(Domainname) ((const char *) (Domainname))
-# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
-# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+# define bindtextdomain(Domainname, Dirname) \
+ ((void) (Domainname), (const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) \
+ ((void) (Domainname), (const char *) (Codeset))
#endif
@@ -65,4 +92,179 @@
initializer for static 'char[]' or 'const char[]' variables. */
#define gettext_noop(String) String
+/* The separator between msgctxt and msgid in a .mo file. */
+#define GETTEXT_CONTEXT_GLUE "\004"
+
+/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
+ MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
+ short and rarely need to change.
+ The letter 'p' stands for 'particular' or 'special'. */
+#ifdef DEFAULT_TEXT_DOMAIN
+# define pgettext(Msgctxt, Msgid) \
+ pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#else
+# define pgettext(Msgctxt, Msgid) \
+ pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#endif
+#define dpgettext(Domainname, Msgctxt, Msgid) \
+ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
+ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
+#ifdef DEFAULT_TEXT_DOMAIN
+# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#else
+# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#endif
+#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
+ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+pgettext_aux (const char *domain,
+ const char *msg_ctxt_id, const char *msgid,
+ int category)
+{
+ const char *translation = dcgettext (domain, msg_ctxt_id, category);
+ if (translation == msg_ctxt_id)
+ return msgid;
+ else
+ return translation;
+}
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+npgettext_aux (const char *domain,
+ const char *msg_ctxt_id, const char *msgid,
+ const char *msgid_plural, unsigned long int n,
+ int category)
+{
+ const char *translation =
+ dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
+ if (translation == msg_ctxt_id || translation == msgid_plural)
+ return (n == 1 ? msgid : msgid_plural);
+ else
+ return translation;
+}
+
+/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
+ can be arbitrary expressions. But for string literals these macros are
+ less efficient than those above. */
+
+#include <string.h>
+
+#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
+ (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
+ /* || __STDC_VERSION__ >= 199901L */ )
+
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+#include <stdlib.h>
+#endif
+
+#define pgettext_expr(Msgctxt, Msgid) \
+ dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
+#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
+ dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+dcpgettext_expr (const char *domain,
+ const char *msgctxt, const char *msgid,
+ int category)
+{
+ size_t msgctxt_len = strlen (msgctxt) + 1;
+ size_t msgid_len = strlen (msgid) + 1;
+ const char *translation;
+#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ char msg_ctxt_id[msgctxt_len + msgid_len];
+#else
+ char buf[1024];
+ char *msg_ctxt_id =
+ (msgctxt_len + msgid_len <= sizeof (buf)
+ ? buf
+ : (char *) malloc (msgctxt_len + msgid_len));
+ if (msg_ctxt_id != NULL)
+#endif
+ {
+ memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
+ msg_ctxt_id[msgctxt_len - 1] = '\004';
+ memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
+ translation = dcgettext (domain, msg_ctxt_id, category);
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ if (msg_ctxt_id != buf)
+ free (msg_ctxt_id);
+#endif
+ if (translation != msg_ctxt_id)
+ return translation;
+ }
+ return msgid;
+}
+
+#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
+ dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
+#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
+ dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+dcnpgettext_expr (const char *domain,
+ const char *msgctxt, const char *msgid,
+ const char *msgid_plural, unsigned long int n,
+ int category)
+{
+ size_t msgctxt_len = strlen (msgctxt) + 1;
+ size_t msgid_len = strlen (msgid) + 1;
+ const char *translation;
+#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ char msg_ctxt_id[msgctxt_len + msgid_len];
+#else
+ char buf[1024];
+ char *msg_ctxt_id =
+ (msgctxt_len + msgid_len <= sizeof (buf)
+ ? buf
+ : (char *) malloc (msgctxt_len + msgid_len));
+ if (msg_ctxt_id != NULL)
+#endif
+ {
+ memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
+ msg_ctxt_id[msgctxt_len - 1] = '\004';
+ memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
+ translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ if (msg_ctxt_id != buf)
+ free (msg_ctxt_id);
+#endif
+ if (!(translation == msg_ctxt_id || translation == msgid_plural))
+ return translation;
+ }
+ return (n == 1 ? msgid : msgid_plural);
+}
+
#endif /* _LIBGETTEXT_H */
diff --git a/lib/hash.c b/lib/hash.c
new file mode 100644
index 000000000000..f4ab12f487de
--- /dev/null
+++ b/lib/hash.c
@@ -0,0 +1,1048 @@
+/* hash - hashing table processing.
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 Free
+ Software Foundation, Inc.
+
+ Written by Jim Meyering, 1992.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* A generic hash table package. */
+
+/* Define USE_OBSTACK to 1 if you want the allocator to use obstacks instead
+ of malloc. If you change USE_OBSTACK, you have to recompile! */
+
+#include <config.h>
+
+#include "hash.h"
+#include "xalloc.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if USE_OBSTACK
+# include "obstack.h"
+# ifndef obstack_chunk_alloc
+# define obstack_chunk_alloc malloc
+# endif
+# ifndef obstack_chunk_free
+# define obstack_chunk_free free
+# endif
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+struct hash_table
+ {
+ /* The array of buckets starts at BUCKET and extends to BUCKET_LIMIT-1,
+ for a possibility of N_BUCKETS. Among those, N_BUCKETS_USED buckets
+ are not empty, there are N_ENTRIES active entries in the table. */
+ struct hash_entry *bucket;
+ struct hash_entry const *bucket_limit;
+ size_t n_buckets;
+ size_t n_buckets_used;
+ size_t n_entries;
+
+ /* Tuning arguments, kept in a physicaly separate structure. */
+ const Hash_tuning *tuning;
+
+ /* Three functions are given to `hash_initialize', see the documentation
+ block for this function. In a word, HASHER randomizes a user entry
+ into a number up from 0 up to some maximum minus 1; COMPARATOR returns
+ true if two user entries compare equally; and DATA_FREER is the cleanup
+ function for a user entry. */
+ Hash_hasher hasher;
+ Hash_comparator comparator;
+ Hash_data_freer data_freer;
+
+ /* A linked list of freed struct hash_entry structs. */
+ struct hash_entry *free_entry_list;
+
+#if USE_OBSTACK
+ /* Whenever obstacks are used, it is possible to allocate all overflowed
+ entries into a single stack, so they all can be freed in a single
+ operation. It is not clear if the speedup is worth the trouble. */
+ struct obstack entry_stack;
+#endif
+ };
+
+/* A hash table contains many internal entries, each holding a pointer to
+ some user provided data (also called a user entry). An entry indistinctly
+ refers to both the internal entry and its associated user entry. A user
+ entry contents may be hashed by a randomization function (the hashing
+ function, or just `hasher' for short) into a number (or `slot') between 0
+ and the current table size. At each slot position in the hash table,
+ starts a linked chain of entries for which the user data all hash to this
+ slot. A bucket is the collection of all entries hashing to the same slot.
+
+ A good `hasher' function will distribute entries rather evenly in buckets.
+ In the ideal case, the length of each bucket is roughly the number of
+ entries divided by the table size. Finding the slot for a data is usually
+ done in constant time by the `hasher', and the later finding of a precise
+ entry is linear in time with the size of the bucket. Consequently, a
+ larger hash table size (that is, a larger number of buckets) is prone to
+ yielding shorter chains, *given* the `hasher' function behaves properly.
+
+ Long buckets slow down the lookup algorithm. One might use big hash table
+ sizes in hope to reduce the average length of buckets, but this might
+ become inordinate, as unused slots in the hash table take some space. The
+ best bet is to make sure you are using a good `hasher' function (beware
+ that those are not that easy to write! :-), and to use a table size
+ larger than the actual number of entries. */
+
+/* If an insertion makes the ratio of nonempty buckets to table size larger
+ than the growth threshold (a number between 0.0 and 1.0), then increase
+ the table size by multiplying by the growth factor (a number greater than
+ 1.0). The growth threshold defaults to 0.8, and the growth factor
+ defaults to 1.414, meaning that the table will have doubled its size
+ every second time 80% of the buckets get used. */
+#define DEFAULT_GROWTH_THRESHOLD 0.8
+#define DEFAULT_GROWTH_FACTOR 1.414
+
+/* If a deletion empties a bucket and causes the ratio of used buckets to
+ table size to become smaller than the shrink threshold (a number between
+ 0.0 and 1.0), then shrink the table by multiplying by the shrink factor (a
+ number greater than the shrink threshold but smaller than 1.0). The shrink
+ threshold and factor default to 0.0 and 1.0, meaning that the table never
+ shrinks. */
+#define DEFAULT_SHRINK_THRESHOLD 0.0
+#define DEFAULT_SHRINK_FACTOR 1.0
+
+/* Use this to initialize or reset a TUNING structure to
+ some sensible values. */
+static const Hash_tuning default_tuning =
+ {
+ DEFAULT_SHRINK_THRESHOLD,
+ DEFAULT_SHRINK_FACTOR,
+ DEFAULT_GROWTH_THRESHOLD,
+ DEFAULT_GROWTH_FACTOR,
+ false
+ };
+
+/* Information and lookup. */
+
+/* The following few functions provide information about the overall hash
+ table organization: the number of entries, number of buckets and maximum
+ length of buckets. */
+
+/* Return the number of buckets in the hash table. The table size, the total
+ number of buckets (used plus unused), or the maximum number of slots, are
+ the same quantity. */
+
+size_t
+hash_get_n_buckets (const Hash_table *table)
+{
+ return table->n_buckets;
+}
+
+/* Return the number of slots in use (non-empty buckets). */
+
+size_t
+hash_get_n_buckets_used (const Hash_table *table)
+{
+ return table->n_buckets_used;
+}
+
+/* Return the number of active entries. */
+
+size_t
+hash_get_n_entries (const Hash_table *table)
+{
+ return table->n_entries;
+}
+
+/* Return the length of the longest chain (bucket). */
+
+size_t
+hash_get_max_bucket_length (const Hash_table *table)
+{
+ struct hash_entry const *bucket;
+ size_t max_bucket_length = 0;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ struct hash_entry const *cursor = bucket;
+ size_t bucket_length = 1;
+
+ while (cursor = cursor->next, cursor)
+ bucket_length++;
+
+ if (bucket_length > max_bucket_length)
+ max_bucket_length = bucket_length;
+ }
+ }
+
+ return max_bucket_length;
+}
+
+/* Do a mild validation of a hash table, by traversing it and checking two
+ statistics. */
+
+bool
+hash_table_ok (const Hash_table *table)
+{
+ struct hash_entry const *bucket;
+ size_t n_buckets_used = 0;
+ size_t n_entries = 0;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ struct hash_entry const *cursor = bucket;
+
+ /* Count bucket head. */
+ n_buckets_used++;
+ n_entries++;
+
+ /* Count bucket overflow. */
+ while (cursor = cursor->next, cursor)
+ n_entries++;
+ }
+ }
+
+ if (n_buckets_used == table->n_buckets_used && n_entries == table->n_entries)
+ return true;
+
+ return false;
+}
+
+void
+hash_print_statistics (const Hash_table *table, FILE *stream)
+{
+ size_t n_entries = hash_get_n_entries (table);
+ size_t n_buckets = hash_get_n_buckets (table);
+ size_t n_buckets_used = hash_get_n_buckets_used (table);
+ size_t max_bucket_length = hash_get_max_bucket_length (table);
+
+ fprintf (stream, "# entries: %lu\n", (unsigned long int) n_entries);
+ fprintf (stream, "# buckets: %lu\n", (unsigned long int) n_buckets);
+ fprintf (stream, "# buckets used: %lu (%.2f%%)\n",
+ (unsigned long int) n_buckets_used,
+ (100.0 * n_buckets_used) / n_buckets);
+ fprintf (stream, "max bucket length: %lu\n",
+ (unsigned long int) max_bucket_length);
+}
+
+/* If ENTRY matches an entry already in the hash table, return the
+ entry from the table. Otherwise, return NULL. */
+
+void *
+hash_lookup (const Hash_table *table, const void *entry)
+{
+ struct hash_entry const *bucket
+ = table->bucket + table->hasher (entry, table->n_buckets);
+ struct hash_entry const *cursor;
+
+ if (! (bucket < table->bucket_limit))
+ abort ();
+
+ if (bucket->data == NULL)
+ return NULL;
+
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ if (table->comparator (entry, cursor->data))
+ return cursor->data;
+
+ return NULL;
+}
+
+/* Walking. */
+
+/* The functions in this page traverse the hash table and process the
+ contained entries. For the traversal to work properly, the hash table
+ should not be resized nor modified while any particular entry is being
+ processed. In particular, entries should not be added or removed. */
+
+/* Return the first data in the table, or NULL if the table is empty. */
+
+void *
+hash_get_first (const Hash_table *table)
+{
+ struct hash_entry const *bucket;
+
+ if (table->n_entries == 0)
+ return NULL;
+
+ for (bucket = table->bucket; ; bucket++)
+ if (! (bucket < table->bucket_limit))
+ abort ();
+ else if (bucket->data)
+ return bucket->data;
+}
+
+/* Return the user data for the entry following ENTRY, where ENTRY has been
+ returned by a previous call to either `hash_get_first' or `hash_get_next'.
+ Return NULL if there are no more entries. */
+
+void *
+hash_get_next (const Hash_table *table, const void *entry)
+{
+ struct hash_entry const *bucket
+ = table->bucket + table->hasher (entry, table->n_buckets);
+ struct hash_entry const *cursor;
+
+ if (! (bucket < table->bucket_limit))
+ abort ();
+
+ /* Find next entry in the same bucket. */
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ if (cursor->data == entry && cursor->next)
+ return cursor->next->data;
+
+ /* Find first entry in any subsequent bucket. */
+ while (++bucket < table->bucket_limit)
+ if (bucket->data)
+ return bucket->data;
+
+ /* None found. */
+ return NULL;
+}
+
+/* Fill BUFFER with pointers to active user entries in the hash table, then
+ return the number of pointers copied. Do not copy more than BUFFER_SIZE
+ pointers. */
+
+size_t
+hash_get_entries (const Hash_table *table, void **buffer,
+ size_t buffer_size)
+{
+ size_t counter = 0;
+ struct hash_entry const *bucket;
+ struct hash_entry const *cursor;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ {
+ if (counter >= buffer_size)
+ return counter;
+ buffer[counter++] = cursor->data;
+ }
+ }
+ }
+
+ return counter;
+}
+
+/* Call a PROCESSOR function for each entry of a hash table, and return the
+ number of entries for which the processor function returned success. A
+ pointer to some PROCESSOR_DATA which will be made available to each call to
+ the processor function. The PROCESSOR accepts two arguments: the first is
+ the user entry being walked into, the second is the value of PROCESSOR_DATA
+ as received. The walking continue for as long as the PROCESSOR function
+ returns nonzero. When it returns zero, the walking is interrupted. */
+
+size_t
+hash_do_for_each (const Hash_table *table, Hash_processor processor,
+ void *processor_data)
+{
+ size_t counter = 0;
+ struct hash_entry const *bucket;
+ struct hash_entry const *cursor;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ {
+ if (!(*processor) (cursor->data, processor_data))
+ return counter;
+ counter++;
+ }
+ }
+ }
+
+ return counter;
+}
+
+/* Allocation and clean-up. */
+
+/* Return a hash index for a NUL-terminated STRING between 0 and N_BUCKETS-1.
+ This is a convenience routine for constructing other hashing functions. */
+
+#if USE_DIFF_HASH
+
+/* About hashings, Paul Eggert writes to me (FP), on 1994-01-01: "Please see
+ B. J. McKenzie, R. Harries & T. Bell, Selecting a hashing algorithm,
+ Software--practice & experience 20, 2 (Feb 1990), 209-224. Good hash
+ algorithms tend to be domain-specific, so what's good for [diffutils'] io.c
+ may not be good for your application." */
+
+size_t
+hash_string (const char *string, size_t n_buckets)
+{
+# define ROTATE_LEFT(Value, Shift) \
+ ((Value) << (Shift) | (Value) >> ((sizeof (size_t) * CHAR_BIT) - (Shift)))
+# define HASH_ONE_CHAR(Value, Byte) \
+ ((Byte) + ROTATE_LEFT (Value, 7))
+
+ size_t value = 0;
+ unsigned char ch;
+
+ for (; (ch = *string); string++)
+ value = HASH_ONE_CHAR (value, ch);
+ return value % n_buckets;
+
+# undef ROTATE_LEFT
+# undef HASH_ONE_CHAR
+}
+
+#else /* not USE_DIFF_HASH */
+
+/* This one comes from `recode', and performs a bit better than the above as
+ per a few experiments. It is inspired from a hashing routine found in the
+ very old Cyber `snoop', itself written in typical Greg Mansfield style.
+ (By the way, what happened to this excellent man? Is he still alive?) */
+
+size_t
+hash_string (const char *string, size_t n_buckets)
+{
+ size_t value = 0;
+ unsigned char ch;
+
+ for (; (ch = *string); string++)
+ value = (value * 31 + ch) % n_buckets;
+ return value;
+}
+
+#endif /* not USE_DIFF_HASH */
+
+/* Return true if CANDIDATE is a prime number. CANDIDATE should be an odd
+ number at least equal to 11. */
+
+static bool
+is_prime (size_t candidate)
+{
+ size_t divisor = 3;
+ size_t square = divisor * divisor;
+
+ while (square < candidate && (candidate % divisor))
+ {
+ divisor++;
+ square += 4 * divisor;
+ divisor++;
+ }
+
+ return (candidate % divisor ? true : false);
+}
+
+/* Round a given CANDIDATE number up to the nearest prime, and return that
+ prime. Primes lower than 10 are merely skipped. */
+
+static size_t
+next_prime (size_t candidate)
+{
+ /* Skip small primes. */
+ if (candidate < 10)
+ candidate = 10;
+
+ /* Make it definitely odd. */
+ candidate |= 1;
+
+ while (!is_prime (candidate))
+ candidate += 2;
+
+ return candidate;
+}
+
+void
+hash_reset_tuning (Hash_tuning *tuning)
+{
+ *tuning = default_tuning;
+}
+
+/* For the given hash TABLE, check the user supplied tuning structure for
+ reasonable values, and return true if there is no gross error with it.
+ Otherwise, definitively reset the TUNING field to some acceptable default
+ in the hash table (that is, the user loses the right of further modifying
+ tuning arguments), and return false. */
+
+static bool
+check_tuning (Hash_table *table)
+{
+ const Hash_tuning *tuning = table->tuning;
+
+ /* Be a bit stricter than mathematics would require, so that
+ rounding errors in size calculations do not cause allocations to
+ fail to grow or shrink as they should. The smallest allocation
+ is 11 (due to next_prime's algorithm), so an epsilon of 0.1
+ should be good enough. */
+ float epsilon = 0.1f;
+
+ if (epsilon < tuning->growth_threshold
+ && tuning->growth_threshold < 1 - epsilon
+ && 1 + epsilon < tuning->growth_factor
+ && 0 <= tuning->shrink_threshold
+ && tuning->shrink_threshold + epsilon < tuning->shrink_factor
+ && tuning->shrink_factor <= 1
+ && tuning->shrink_threshold + epsilon < tuning->growth_threshold)
+ return true;
+
+ table->tuning = &default_tuning;
+ return false;
+}
+
+/* Allocate and return a new hash table, or NULL upon failure. The initial
+ number of buckets is automatically selected so as to _guarantee_ that you
+ may insert at least CANDIDATE different user entries before any growth of
+ the hash table size occurs. So, if have a reasonably tight a-priori upper
+ bound on the number of entries you intend to insert in the hash table, you
+ may save some table memory and insertion time, by specifying it here. If
+ the IS_N_BUCKETS field of the TUNING structure is true, the CANDIDATE
+ argument has its meaning changed to the wanted number of buckets.
+
+ TUNING points to a structure of user-supplied values, in case some fine
+ tuning is wanted over the default behavior of the hasher. If TUNING is
+ NULL, the default tuning parameters are used instead.
+
+ The user-supplied HASHER function should be provided. It accepts two
+ arguments ENTRY and TABLE_SIZE. It computes, by hashing ENTRY contents, a
+ slot number for that entry which should be in the range 0..TABLE_SIZE-1.
+ This slot number is then returned.
+
+ The user-supplied COMPARATOR function should be provided. It accepts two
+ arguments pointing to user data, it then returns true for a pair of entries
+ that compare equal, or false otherwise. This function is internally called
+ on entries which are already known to hash to the same bucket index.
+
+ The user-supplied DATA_FREER function, when not NULL, may be later called
+ with the user data as an argument, just before the entry containing the
+ data gets freed. This happens from within `hash_free' or `hash_clear'.
+ You should specify this function only if you want these functions to free
+ all of your `data' data. This is typically the case when your data is
+ simply an auxiliary struct that you have malloc'd to aggregate several
+ values. */
+
+Hash_table *
+hash_initialize (size_t candidate, const Hash_tuning *tuning,
+ Hash_hasher hasher, Hash_comparator comparator,
+ Hash_data_freer data_freer)
+{
+ Hash_table *table;
+
+ if (hasher == NULL || comparator == NULL)
+ return NULL;
+
+ table = malloc (sizeof *table);
+ if (table == NULL)
+ return NULL;
+
+ if (!tuning)
+ tuning = &default_tuning;
+ table->tuning = tuning;
+ if (!check_tuning (table))
+ {
+ /* Fail if the tuning options are invalid. This is the only occasion
+ when the user gets some feedback about it. Once the table is created,
+ if the user provides invalid tuning options, we silently revert to
+ using the defaults, and ignore further request to change the tuning
+ options. */
+ goto fail;
+ }
+
+ if (!tuning->is_n_buckets)
+ {
+ float new_candidate = candidate / tuning->growth_threshold;
+ if (SIZE_MAX <= new_candidate)
+ goto fail;
+ candidate = new_candidate;
+ }
+
+ if (xalloc_oversized (candidate, sizeof *table->bucket))
+ goto fail;
+ table->n_buckets = next_prime (candidate);
+ if (xalloc_oversized (table->n_buckets, sizeof *table->bucket))
+ goto fail;
+
+ table->bucket = calloc (table->n_buckets, sizeof *table->bucket);
+ table->bucket_limit = table->bucket + table->n_buckets;
+ table->n_buckets_used = 0;
+ table->n_entries = 0;
+
+ table->hasher = hasher;
+ table->comparator = comparator;
+ table->data_freer = data_freer;
+
+ table->free_entry_list = NULL;
+#if USE_OBSTACK
+ obstack_init (&table->entry_stack);
+#endif
+ return table;
+
+ fail:
+ free (table);
+ return NULL;
+}
+
+/* Make all buckets empty, placing any chained entries on the free list.
+ Apply the user-specified function data_freer (if any) to the datas of any
+ affected entries. */
+
+void
+hash_clear (Hash_table *table)
+{
+ struct hash_entry *bucket;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ struct hash_entry *cursor;
+ struct hash_entry *next;
+
+ /* Free the bucket overflow. */
+ for (cursor = bucket->next; cursor; cursor = next)
+ {
+ if (table->data_freer)
+ (*table->data_freer) (cursor->data);
+ cursor->data = NULL;
+
+ next = cursor->next;
+ /* Relinking is done one entry at a time, as it is to be expected
+ that overflows are either rare or short. */
+ cursor->next = table->free_entry_list;
+ table->free_entry_list = cursor;
+ }
+
+ /* Free the bucket head. */
+ if (table->data_freer)
+ (*table->data_freer) (bucket->data);
+ bucket->data = NULL;
+ bucket->next = NULL;
+ }
+ }
+
+ table->n_buckets_used = 0;
+ table->n_entries = 0;
+}
+
+/* Reclaim all storage associated with a hash table. If a data_freer
+ function has been supplied by the user when the hash table was created,
+ this function applies it to the data of each entry before freeing that
+ entry. */
+
+void
+hash_free (Hash_table *table)
+{
+ struct hash_entry *bucket;
+ struct hash_entry *cursor;
+ struct hash_entry *next;
+
+ /* Call the user data_freer function. */
+ if (table->data_freer && table->n_entries)
+ {
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ {
+ (*table->data_freer) (cursor->data);
+ }
+ }
+ }
+ }
+
+#if USE_OBSTACK
+
+ obstack_free (&table->entry_stack, NULL);
+
+#else
+
+ /* Free all bucket overflowed entries. */
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ for (cursor = bucket->next; cursor; cursor = next)
+ {
+ next = cursor->next;
+ free (cursor);
+ }
+ }
+
+ /* Also reclaim the internal list of previously freed entries. */
+ for (cursor = table->free_entry_list; cursor; cursor = next)
+ {
+ next = cursor->next;
+ free (cursor);
+ }
+
+#endif
+
+ /* Free the remainder of the hash table structure. */
+ free (table->bucket);
+ free (table);
+}
+
+/* Insertion and deletion. */
+
+/* Get a new hash entry for a bucket overflow, possibly by reclying a
+ previously freed one. If this is not possible, allocate a new one. */
+
+static struct hash_entry *
+allocate_entry (Hash_table *table)
+{
+ struct hash_entry *new;
+
+ if (table->free_entry_list)
+ {
+ new = table->free_entry_list;
+ table->free_entry_list = new->next;
+ }
+ else
+ {
+#if USE_OBSTACK
+ new = obstack_alloc (&table->entry_stack, sizeof *new);
+#else
+ new = malloc (sizeof *new);
+#endif
+ }
+
+ return new;
+}
+
+/* Free a hash entry which was part of some bucket overflow,
+ saving it for later recycling. */
+
+static void
+free_entry (Hash_table *table, struct hash_entry *entry)
+{
+ entry->data = NULL;
+ entry->next = table->free_entry_list;
+ table->free_entry_list = entry;
+}
+
+/* This private function is used to help with insertion and deletion. When
+ ENTRY matches an entry in the table, return a pointer to the corresponding
+ user data and set *BUCKET_HEAD to the head of the selected bucket.
+ Otherwise, return NULL. When DELETE is true and ENTRY matches an entry in
+ the table, unlink the matching entry. */
+
+static void *
+hash_find_entry (Hash_table *table, const void *entry,
+ struct hash_entry **bucket_head, bool delete)
+{
+ struct hash_entry *bucket
+ = table->bucket + table->hasher (entry, table->n_buckets);
+ struct hash_entry *cursor;
+
+ if (! (bucket < table->bucket_limit))
+ abort ();
+
+ *bucket_head = bucket;
+
+ /* Test for empty bucket. */
+ if (bucket->data == NULL)
+ return NULL;
+
+ /* See if the entry is the first in the bucket. */
+ if ((*table->comparator) (entry, bucket->data))
+ {
+ void *data = bucket->data;
+
+ if (delete)
+ {
+ if (bucket->next)
+ {
+ struct hash_entry *next = bucket->next;
+
+ /* Bump the first overflow entry into the bucket head, then save
+ the previous first overflow entry for later recycling. */
+ *bucket = *next;
+ free_entry (table, next);
+ }
+ else
+ {
+ bucket->data = NULL;
+ }
+ }
+
+ return data;
+ }
+
+ /* Scan the bucket overflow. */
+ for (cursor = bucket; cursor->next; cursor = cursor->next)
+ {
+ if ((*table->comparator) (entry, cursor->next->data))
+ {
+ void *data = cursor->next->data;
+
+ if (delete)
+ {
+ struct hash_entry *next = cursor->next;
+
+ /* Unlink the entry to delete, then save the freed entry for later
+ recycling. */
+ cursor->next = next->next;
+ free_entry (table, next);
+ }
+
+ return data;
+ }
+ }
+
+ /* No entry found. */
+ return NULL;
+}
+
+/* For an already existing hash table, change the number of buckets through
+ specifying CANDIDATE. The contents of the hash table are preserved. The
+ new number of buckets is automatically selected so as to _guarantee_ that
+ the table may receive at least CANDIDATE different user entries, including
+ those already in the table, before any other growth of the hash table size
+ occurs. If TUNING->IS_N_BUCKETS is true, then CANDIDATE specifies the
+ exact number of buckets desired. */
+
+bool
+hash_rehash (Hash_table *table, size_t candidate)
+{
+ Hash_table *new_table;
+ struct hash_entry *bucket;
+ struct hash_entry *cursor;
+ struct hash_entry *next;
+
+ new_table = hash_initialize (candidate, table->tuning, table->hasher,
+ table->comparator, table->data_freer);
+ if (new_table == NULL)
+ return false;
+
+ /* Merely reuse the extra old space into the new table. */
+#if USE_OBSTACK
+ obstack_free (&new_table->entry_stack, NULL);
+ new_table->entry_stack = table->entry_stack;
+#endif
+ new_table->free_entry_list = table->free_entry_list;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ if (bucket->data)
+ for (cursor = bucket; cursor; cursor = next)
+ {
+ void *data = cursor->data;
+ struct hash_entry *new_bucket
+ = (new_table->bucket
+ + new_table->hasher (data, new_table->n_buckets));
+
+ if (! (new_bucket < new_table->bucket_limit))
+ abort ();
+
+ next = cursor->next;
+
+ if (new_bucket->data)
+ {
+ if (cursor == bucket)
+ {
+ /* Allocate or recycle an entry, when moving from a bucket
+ header into a bucket overflow. */
+ struct hash_entry *new_entry = allocate_entry (new_table);
+
+ if (new_entry == NULL)
+ return false;
+
+ new_entry->data = data;
+ new_entry->next = new_bucket->next;
+ new_bucket->next = new_entry;
+ }
+ else
+ {
+ /* Merely relink an existing entry, when moving from a
+ bucket overflow into a bucket overflow. */
+ cursor->next = new_bucket->next;
+ new_bucket->next = cursor;
+ }
+ }
+ else
+ {
+ /* Free an existing entry, when moving from a bucket
+ overflow into a bucket header. Also take care of the
+ simple case of moving from a bucket header into a bucket
+ header. */
+ new_bucket->data = data;
+ new_table->n_buckets_used++;
+ if (cursor != bucket)
+ free_entry (new_table, cursor);
+ }
+ }
+
+ free (table->bucket);
+ table->bucket = new_table->bucket;
+ table->bucket_limit = new_table->bucket_limit;
+ table->n_buckets = new_table->n_buckets;
+ table->n_buckets_used = new_table->n_buckets_used;
+ table->free_entry_list = new_table->free_entry_list;
+ /* table->n_entries already holds its value. */
+#if USE_OBSTACK
+ table->entry_stack = new_table->entry_stack;
+#endif
+ free (new_table);
+
+ return true;
+}
+
+/* If ENTRY matches an entry already in the hash table, return the pointer
+ to the entry from the table. Otherwise, insert ENTRY and return ENTRY.
+ Return NULL if the storage required for insertion cannot be allocated. */
+
+void *
+hash_insert (Hash_table *table, const void *entry)
+{
+ void *data;
+ struct hash_entry *bucket;
+
+ /* The caller cannot insert a NULL entry. */
+ if (! entry)
+ abort ();
+
+ /* If there's a matching entry already in the table, return that. */
+ if ((data = hash_find_entry (table, entry, &bucket, false)) != NULL)
+ return data;
+
+ /* ENTRY is not matched, it should be inserted. */
+
+ if (bucket->data)
+ {
+ struct hash_entry *new_entry = allocate_entry (table);
+
+ if (new_entry == NULL)
+ return NULL;
+
+ /* Add ENTRY in the overflow of the bucket. */
+
+ new_entry->data = (void *) entry;
+ new_entry->next = bucket->next;
+ bucket->next = new_entry;
+ table->n_entries++;
+ return (void *) entry;
+ }
+
+ /* Add ENTRY right in the bucket head. */
+
+ bucket->data = (void *) entry;
+ table->n_entries++;
+ table->n_buckets_used++;
+
+ /* If the growth threshold of the buckets in use has been reached, increase
+ the table size and rehash. There's no point in checking the number of
+ entries: if the hashing function is ill-conditioned, rehashing is not
+ likely to improve it. */
+
+ if (table->n_buckets_used
+ > table->tuning->growth_threshold * table->n_buckets)
+ {
+ /* Check more fully, before starting real work. If tuning arguments
+ became invalid, the second check will rely on proper defaults. */
+ check_tuning (table);
+ if (table->n_buckets_used
+ > table->tuning->growth_threshold * table->n_buckets)
+ {
+ const Hash_tuning *tuning = table->tuning;
+ float candidate =
+ (tuning->is_n_buckets
+ ? (table->n_buckets * tuning->growth_factor)
+ : (table->n_buckets * tuning->growth_factor
+ * tuning->growth_threshold));
+
+ if (SIZE_MAX <= candidate)
+ return NULL;
+
+ /* If the rehash fails, arrange to return NULL. */
+ if (!hash_rehash (table, candidate))
+ entry = NULL;
+ }
+ }
+
+ return (void *) entry;
+}
+
+/* If ENTRY is already in the table, remove it and return the just-deleted
+ data (the user may want to deallocate its storage). If ENTRY is not in the
+ table, don't modify the table and return NULL. */
+
+void *
+hash_delete (Hash_table *table, const void *entry)
+{
+ void *data;
+ struct hash_entry *bucket;
+
+ data = hash_find_entry (table, entry, &bucket, true);
+ if (!data)
+ return NULL;
+
+ table->n_entries--;
+ if (!bucket->data)
+ {
+ table->n_buckets_used--;
+
+ /* If the shrink threshold of the buckets in use has been reached,
+ rehash into a smaller table. */
+
+ if (table->n_buckets_used
+ < table->tuning->shrink_threshold * table->n_buckets)
+ {
+ /* Check more fully, before starting real work. If tuning arguments
+ became invalid, the second check will rely on proper defaults. */
+ check_tuning (table);
+ if (table->n_buckets_used
+ < table->tuning->shrink_threshold * table->n_buckets)
+ {
+ const Hash_tuning *tuning = table->tuning;
+ size_t candidate =
+ (tuning->is_n_buckets
+ ? table->n_buckets * tuning->shrink_factor
+ : (table->n_buckets * tuning->shrink_factor
+ * tuning->growth_threshold));
+
+ hash_rehash (table, candidate);
+ }
+ }
+ }
+
+ return data;
+}
+
+/* Testing. */
+
+#if TESTING
+
+void
+hash_print (const Hash_table *table)
+{
+ struct hash_entry const *bucket;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ struct hash_entry *cursor;
+
+ if (bucket)
+ printf ("%lu:\n", (unsigned long int) (bucket - table->bucket));
+
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ {
+ char const *s = cursor->data;
+ /* FIXME */
+ if (s)
+ printf (" %s\n", s);
+ }
+ }
+}
+
+#endif /* TESTING */
diff --git a/lib/hash.h b/lib/hash.h
new file mode 100644
index 000000000000..ab63a863fd0c
--- /dev/null
+++ b/lib/hash.h
@@ -0,0 +1,88 @@
+/* hash - hashing table processing.
+ Copyright (C) 1998, 1999, 2001, 2003 Free Software Foundation, Inc.
+ Written by Jim Meyering <meyering@ascend.com>, 1998.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* A generic hash table package. */
+
+/* Make sure USE_OBSTACK is defined to 1 if you want the allocator to use
+ obstacks instead of malloc, and recompile `hash.c' with same setting. */
+
+#ifndef HASH_H_
+# define HASH_H_
+
+# include <stdio.h>
+# include <stdbool.h>
+
+typedef size_t (*Hash_hasher) (const void *, size_t);
+typedef bool (*Hash_comparator) (const void *, const void *);
+typedef void (*Hash_data_freer) (void *);
+typedef bool (*Hash_processor) (void *, void *);
+
+struct hash_entry
+ {
+ void *data;
+ struct hash_entry *next;
+ };
+
+struct hash_tuning
+ {
+ /* This structure is mainly used for `hash_initialize', see the block
+ documentation of `hash_reset_tuning' for more complete comments. */
+
+ float shrink_threshold; /* ratio of used buckets to trigger a shrink */
+ float shrink_factor; /* ratio of new smaller size to original size */
+ float growth_threshold; /* ratio of used buckets to trigger a growth */
+ float growth_factor; /* ratio of new bigger size to original size */
+ bool is_n_buckets; /* if CANDIDATE really means table size */
+ };
+
+typedef struct hash_tuning Hash_tuning;
+
+struct hash_table;
+
+typedef struct hash_table Hash_table;
+
+/* Information and lookup. */
+size_t hash_get_n_buckets (const Hash_table *);
+size_t hash_get_n_buckets_used (const Hash_table *);
+size_t hash_get_n_entries (const Hash_table *);
+size_t hash_get_max_bucket_length (const Hash_table *);
+bool hash_table_ok (const Hash_table *);
+void hash_print_statistics (const Hash_table *, FILE *);
+void *hash_lookup (const Hash_table *, const void *);
+
+/* Walking. */
+void *hash_get_first (const Hash_table *);
+void *hash_get_next (const Hash_table *, const void *);
+size_t hash_get_entries (const Hash_table *, void **, size_t);
+size_t hash_do_for_each (const Hash_table *, Hash_processor, void *);
+
+/* Allocation and clean-up. */
+size_t hash_string (const char *, size_t);
+void hash_reset_tuning (Hash_tuning *);
+Hash_table *hash_initialize (size_t, const Hash_tuning *,
+ Hash_hasher, Hash_comparator,
+ Hash_data_freer);
+void hash_clear (Hash_table *);
+void hash_free (Hash_table *);
+
+/* Insertion and deletion. */
+bool hash_rehash (Hash_table *, size_t);
+void *hash_insert (Hash_table *, const void *);
+void *hash_delete (Hash_table *, const void *);
+
+#endif
diff --git a/lib/intprops.h b/lib/intprops.h
new file mode 100644
index 000000000000..34f971cbaad8
--- /dev/null
+++ b/lib/intprops.h
@@ -0,0 +1,78 @@
+/* intprops.h -- properties of integer types
+
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+#include <limits.h>
+
+/* The extra casts in the following macros work around compiler bugs,
+ e.g., in Cray C 5.0.3.0. */
+
+/* True if the arithmetic type T is an integer type. bool counts as
+ an integer. */
+#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
+
+/* True if negative values of the signed integer type T use two's
+ complement, ones' complement, or signed magnitude representation,
+ respectively. Much GNU code assumes two's complement, but some
+ people like to be portable to all possible C hosts. */
+#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
+#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
+#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
+
+/* True if the arithmetic type T is signed. */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* The maximum and minimum values for the integer type T. These
+ macros have undefined behavior if T is signed and has padding bits.
+ If this is a problem for you, please let us know how to fix it for
+ your host. */
+#define TYPE_MINIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) 0 \
+ : TYPE_SIGNED_MAGNITUDE (t) \
+ ? ~ (t) 0 \
+ : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+#define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+
+/* Return zero if T can be determined to be an unsigned type.
+ Otherwise, return 1.
+ When compiling with GCC, INT_STRLEN_BOUND uses this macro to obtain a
+ tighter bound. Otherwise, it overestimates the true bound by one byte
+ when applied to unsigned types of size 2, 4, 16, ... bytes.
+ The symbol signed_type_or_expr__ is private to this header file. */
+#if __GNUC__ >= 2
+# define signed_type_or_expr__(t) TYPE_SIGNED (__typeof__ (t))
+#else
+# define signed_type_or_expr__(t) 1
+#endif
+
+/* Bound on length of the string representing an integer type or expression T.
+ Subtract 1 for the sign bit if T is signed; log10 (2.0) < 146/485;
+ add 1 for integer division truncation; add 1 more for a minus sign
+ if needed. */
+#define INT_STRLEN_BOUND(t) \
+ ((sizeof (t) * CHAR_BIT - signed_type_or_expr__ (t)) * 146 / 485 \
+ + signed_type_or_expr__ (t) + 1)
+
+/* Bound on buffer size needed to represent an integer type or expression T,
+ including the terminating null. */
+#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
diff --git a/lib/inttostr.c b/lib/inttostr.c
new file mode 100644
index 000000000000..246d65835073
--- /dev/null
+++ b/lib/inttostr.c
@@ -0,0 +1,51 @@
+/* inttostr.c -- convert integers to printable strings
+
+ Copyright (C) 2001, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert */
+
+#include <config.h>
+
+#include "inttostr.h"
+
+/* Convert I to a printable string in BUF, which must be at least
+ INT_BUFSIZE_BOUND (INTTYPE) bytes long. Return the address of the
+ printable string, which need not start at BUF. */
+
+char *
+inttostr (inttype i, char *buf)
+{
+ char *p = buf + INT_STRLEN_BOUND (inttype);
+ *p = 0;
+
+ if (i < 0)
+ {
+ do
+ *--p = '0' - i % 10;
+ while ((i /= 10) != 0);
+
+ *--p = '-';
+ }
+ else
+ {
+ do
+ *--p = '0' + i % 10;
+ while ((i /= 10) != 0);
+ }
+
+ return p;
+}
diff --git a/lib/exit.h b/lib/inttostr.h
index 4e8d46516546..31258cad35bc 100644
--- a/lib/exit.h
+++ b/lib/inttostr.h
@@ -1,5 +1,7 @@
-/* exit() function.
- Copyright (C) 1995, 2001 Free Software Foundation, Inc.
+/* inttostr.h -- convert integers to printable strings
+
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+ Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,20 +15,16 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#ifndef _EXIT_H
-#define _EXIT_H
+/* Written by Paul Eggert */
-/* Get exit() declaration. */
-#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.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
+#include "intprops.h"
-#endif /* _EXIT_H */
+char *offtostr (off_t, char *);
+char *imaxtostr (intmax_t, char *);
+char *umaxtostr (uintmax_t, char *);
+char *uinttostr (unsigned int, char *);
diff --git a/lib/mempcpy.c b/lib/mempcpy.c
index 3ac42af288a5..1c702c7f4cb7 100644
--- a/lib/mempcpy.c
+++ b/lib/mempcpy.c
@@ -1,5 +1,5 @@
/* Copy memory area and return pointer after last written byte.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,11 +13,11 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-/* Specification. */
-#include "mempcpy.h"
+#include <config.h>
+/* Specification. */
#include <string.h>
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
diff --git a/lib/paxerror.c b/lib/paxerror.c
new file mode 100644
index 000000000000..000d9e44981f
--- /dev/null
+++ b/lib/paxerror.c
@@ -0,0 +1,365 @@
+/* Miscellaneous error functions
+
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <system.h>
+#include <paxlib.h>
+#include <quote.h>
+#include <quotearg.h>
+
+/* Decode MODE from its binary form in a stat structure, and encode it
+ into a 9-byte string STRING, terminated with a NUL. */
+
+void
+pax_decode_mode (mode_t mode, char *string)
+{
+ *string++ = mode & S_IRUSR ? 'r' : '-';
+ *string++ = mode & S_IWUSR ? 'w' : '-';
+ *string++ = (mode & S_ISUID
+ ? (mode & S_IXUSR ? 's' : 'S')
+ : (mode & S_IXUSR ? 'x' : '-'));
+ *string++ = mode & S_IRGRP ? 'r' : '-';
+ *string++ = mode & S_IWGRP ? 'w' : '-';
+ *string++ = (mode & S_ISGID
+ ? (mode & S_IXGRP ? 's' : 'S')
+ : (mode & S_IXGRP ? 'x' : '-'));
+ *string++ = mode & S_IROTH ? 'r' : '-';
+ *string++ = mode & S_IWOTH ? 'w' : '-';
+ *string++ = (mode & S_ISVTX
+ ? (mode & S_IXOTH ? 't' : 'T')
+ : (mode & S_IXOTH ? 'x' : '-'));
+ *string = '\0';
+}
+
+/* Report an error associated with the system call CALL and the
+ optional name NAME. */
+void
+call_arg_error (char const *call, char const *name)
+{
+ int e = errno;
+ /* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
+ Directly translating this to another language will not work, first because
+ %s itself is not translated.
+ Translate it as `%s: Function %s failed'. */
+ ERROR ((0, e, _("%s: Cannot %s"), quotearg_colon (name), call));
+}
+
+/* Report a fatal error associated with the system call CALL and
+ the optional file name NAME. */
+void
+call_arg_fatal (char const *call, char const *name)
+{
+ int e = errno;
+ /* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
+ Directly translating this to another language will not work, first because
+ %s itself is not translated.
+ Translate it as `%s: Function %s failed'. */
+ FATAL_ERROR ((0, e, _("%s: Cannot %s"), quotearg_colon (name), call));
+}
+
+/* Report a warning associated with the system call CALL and
+ the optional file name NAME. */
+void
+call_arg_warn (char const *call, char const *name)
+{
+ int e = errno;
+ /* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
+ Directly translating this to another language will not work, first because
+ %s itself is not translated.
+ Translate it as `%s: Function %s failed'. */
+ WARN ((0, e, _("%s: Warning: Cannot %s"), quotearg_colon (name), call));
+}
+
+void
+chmod_error_details (char const *name, mode_t mode)
+{
+ int e = errno;
+ char buf[10];
+ pax_decode_mode (mode, buf);
+ ERROR ((0, e, _("%s: Cannot change mode to %s"),
+ quotearg_colon (name), buf));
+}
+
+void
+chown_error_details (char const *name, uid_t uid, gid_t gid)
+{
+ int e = errno;
+ ERROR ((0, e, _("%s: Cannot change ownership to uid %lu, gid %lu"),
+ quotearg_colon (name), (unsigned long) uid, (unsigned long) gid));
+}
+
+void
+close_error (char const *name)
+{
+ call_arg_error ("close", name);
+}
+
+void
+close_warn (char const *name)
+{
+ call_arg_warn ("close", name);
+}
+
+void
+exec_fatal (char const *name)
+{
+ call_arg_fatal ("exec", name);
+}
+
+void
+link_error (char const *target, char const *source)
+{
+ int e = errno;
+ ERROR ((0, e, _("%s: Cannot hard link to %s"),
+ quotearg_colon (source), quote_n (1, target)));
+}
+
+void
+mkdir_error (char const *name)
+{
+ call_arg_error ("mkdir", name);
+}
+
+void
+mkfifo_error (char const *name)
+{
+ call_arg_error ("mkfifo", name);
+}
+
+void
+mknod_error (char const *name)
+{
+ call_arg_error ("mknod", name);
+}
+
+void
+open_error (char const *name)
+{
+ call_arg_error ("open", name);
+}
+
+void
+open_fatal (char const *name)
+{
+ call_arg_fatal ("open", name);
+}
+
+void
+open_warn (char const *name)
+{
+ call_arg_warn ("open", name);
+}
+
+void
+read_error (char const *name)
+{
+ call_arg_error ("read", name);
+}
+
+void
+read_error_details (char const *name, off_t offset, size_t size)
+{
+ char buf[UINTMAX_STRSIZE_BOUND];
+ int e = errno;
+ ERROR ((0, e,
+ ngettext ("%s: Read error at byte %s, while reading %lu byte",
+ "%s: Read error at byte %s, while reading %lu bytes",
+ size),
+ quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
+ (unsigned long) size));
+}
+
+void
+read_warn_details (char const *name, off_t offset, size_t size)
+{
+ char buf[UINTMAX_STRSIZE_BOUND];
+ int e = errno;
+ WARN ((0, e,
+ ngettext ("%s: Warning: Read error at byte %s, while reading %lu byte",
+ "%s: Warning: Read error at byte %s, while reading %lu bytes",
+ size),
+ quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
+ (unsigned long) size));
+}
+
+void
+read_fatal (char const *name)
+{
+ call_arg_fatal ("read", name);
+}
+
+void
+read_fatal_details (char const *name, off_t offset, size_t size)
+{
+ char buf[UINTMAX_STRSIZE_BOUND];
+ int e = errno;
+ FATAL_ERROR ((0, e,
+ ngettext ("%s: Read error at byte %s, while reading %lu byte",
+ "%s: Read error at byte %s, while reading %lu bytes",
+ size),
+ quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
+ (unsigned long) size));
+}
+
+void
+readlink_error (char const *name)
+{
+ call_arg_error ("readlink", name);
+}
+
+void
+readlink_warn (char const *name)
+{
+ call_arg_warn ("readlink", name);
+}
+
+void
+rmdir_error (char const *name)
+{
+ call_arg_error ("rmdir", name);
+}
+
+void
+savedir_error (char const *name)
+{
+ call_arg_error ("savedir", name);
+}
+
+void
+savedir_warn (char const *name)
+{
+ call_arg_warn ("savedir", name);
+}
+
+void
+seek_error (char const *name)
+{
+ call_arg_error ("seek", name);
+}
+
+void
+seek_error_details (char const *name, off_t offset)
+{
+ char buf[UINTMAX_STRSIZE_BOUND];
+ int e = errno;
+ ERROR ((0, e, _("%s: Cannot seek to %s"),
+ quotearg_colon (name),
+ STRINGIFY_BIGINT (offset, buf)));
+}
+
+void
+seek_warn (char const *name)
+{
+ call_arg_warn ("seek", name);
+}
+
+void
+seek_warn_details (char const *name, off_t offset)
+{
+ char buf[UINTMAX_STRSIZE_BOUND];
+ int e = errno;
+ WARN ((0, e, _("%s: Warning: Cannot seek to %s"),
+ quotearg_colon (name),
+ STRINGIFY_BIGINT (offset, buf)));
+}
+
+void
+symlink_error (char const *contents, char const *name)
+{
+ int e = errno;
+ ERROR ((0, e, _("%s: Cannot create symlink to %s"),
+ quotearg_colon (name), quote_n (1, contents)));
+}
+
+void
+stat_fatal (char const *name)
+{
+ call_arg_fatal ("stat", name);
+}
+
+void
+stat_error (char const *name)
+{
+ call_arg_error ("stat", name);
+}
+
+void
+stat_warn (char const *name)
+{
+ call_arg_warn ("stat", name);
+}
+
+void
+truncate_error (char const *name)
+{
+ call_arg_error ("truncate", name);
+}
+
+void
+truncate_warn (char const *name)
+{
+ call_arg_warn ("truncate", name);
+}
+
+void
+unlink_error (char const *name)
+{
+ call_arg_error ("unlink", name);
+}
+
+void
+utime_error (char const *name)
+{
+ call_arg_error ("utime", name);
+}
+
+void
+waitpid_error (char const *name)
+{
+ call_arg_error ("waitpid", name);
+}
+
+void
+write_error (char const *name)
+{
+ call_arg_error ("write", name);
+}
+
+void
+write_error_details (char const *name, size_t status, size_t size)
+{
+ if (status == 0)
+ write_error (name);
+ else
+ ERROR ((0, 0,
+ ngettext ("%s: Wrote only %lu of %lu byte",
+ "%s: Wrote only %lu of %lu bytes",
+ size),
+ name, (unsigned long int) status, (unsigned long int) size));
+}
+
+void
+write_fatal (char const *name)
+{
+ call_arg_fatal ("write", name);
+}
+
+void
+chdir_fatal (char const *name)
+{
+ call_arg_fatal ("chdir", name);
+}
diff --git a/lib/paxexit.c b/lib/paxexit.c
new file mode 100644
index 000000000000..a511f79cf171
--- /dev/null
+++ b/lib/paxexit.c
@@ -0,0 +1,28 @@
+/* Miscellaneous error functions
+
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <system.h>
+#include <paxlib.h>
+
+int exit_status = PAXEXIT_SUCCESS;
+
+void
+pax_exit ()
+{
+ exit (exit_status);
+}
diff --git a/lib/paxlib.h b/lib/paxlib.h
new file mode 100644
index 000000000000..381c4c702998
--- /dev/null
+++ b/lib/paxlib.h
@@ -0,0 +1,115 @@
+/* This file is part of GNU paxutils
+
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
+ 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _paxlib_h_
+#define _paxlib_h_
+
+#include <hash.h>
+#include <inttostr.h>
+
+/* Error reporting functions and definitions */
+
+/* Exit status for paxutils app. Let's try to keep this list as simple as
+ possible. tar -d option strongly invites a status different for unequal
+ comparison and other errors. */
+#define PAXEXIT_SUCCESS 0
+#define PAXEXIT_DIFFERS 1
+#define PAXEXIT_FAILURE 2
+
+/* Both WARN and ERROR write a message on stderr and continue processing,
+ however ERROR manages so tar will exit unsuccessfully. FATAL_ERROR
+ writes a message on stderr and aborts immediately, with another message
+ line telling so. USAGE_ERROR works like FATAL_ERROR except that the
+ other message line suggests trying --help. All four macros accept a
+ single argument of the form ((0, errno, _("FORMAT"), Args...)). errno
+ is zero when the error is not being detected by the system. */
+
+#define WARN(Args) \
+ error Args
+#define ERROR(Args) \
+ (error Args, exit_status = PAXEXIT_FAILURE)
+#define FATAL_ERROR(Args) \
+ (error Args, fatal_exit ())
+#define USAGE_ERROR(Args) \
+ (error Args, usage (PAXEXIT_FAILURE))
+
+extern int exit_status;
+
+void pax_decode_mode (mode_t mode, char *string);
+void call_arg_error (char const *call, char const *name);
+void call_arg_fatal (char const *call, char const *name) __attribute__ ((noreturn));
+void call_arg_warn (char const *call, char const *name);
+void chmod_error_details (char const *name, mode_t mode);
+void chown_error_details (char const *name, uid_t uid, gid_t gid);
+
+void decode_mode (mode_t, char *);
+
+void chdir_fatal (char const *) __attribute__ ((noreturn));
+void chmod_error_details (char const *, mode_t);
+void chown_error_details (char const *, uid_t, gid_t);
+void close_error (char const *);
+void close_warn (char const *);
+void exec_fatal (char const *) __attribute__ ((noreturn));
+void link_error (char const *, char const *);
+void mkdir_error (char const *);
+void mkfifo_error (char const *);
+void mknod_error (char const *);
+void open_error (char const *);
+void open_fatal (char const *) __attribute__ ((noreturn));
+void open_warn (char const *);
+void read_error (char const *);
+void read_error_details (char const *, off_t, size_t);
+void read_fatal (char const *) __attribute__ ((noreturn));
+void read_fatal_details (char const *, off_t, size_t) __attribute__ ((noreturn));
+void read_warn_details (char const *, off_t, size_t);
+void readlink_error (char const *);
+void readlink_warn (char const *);
+void rmdir_error (char const *);
+void savedir_error (char const *);
+void savedir_warn (char const *);
+void seek_error (char const *);
+void seek_error_details (char const *, off_t);
+void seek_warn (char const *);
+void seek_warn_details (char const *, off_t);
+void stat_fatal (char const *);
+void stat_error (char const *);
+void stat_warn (char const *);
+void symlink_error (char const *, char const *);
+void truncate_error (char const *);
+void truncate_warn (char const *);
+void unlink_error (char const *);
+void utime_error (char const *);
+void waitpid_error (char const *);
+void write_error (char const *);
+
+void pax_exit (void);
+void fatal_exit (void) __attribute__ ((noreturn));
+
+#define STRINGIFY_BIGINT(i, b) umaxtostr (i, b)
+
+
+/* Name-related functions */
+bool hash_string_insert (Hash_table **table, char const *string);
+bool hash_string_lookup (Hash_table const *table, char const *string);
+
+bool removed_prefixes_p (void);
+char *safer_name_suffix (char const *file_name, bool link_target, bool absolute_names);
+
+#endif
diff --git a/lib/paxnames.c b/lib/paxnames.c
new file mode 100644
index 000000000000..3ca8bfaa7f96
--- /dev/null
+++ b/lib/paxnames.c
@@ -0,0 +1,156 @@
+/* This file is part of GNU paxutils
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <system.h>
+#include <hash.h>
+#include <paxlib.h>
+
+
+/* Hash tables of strings. */
+
+/* Calculate the hash of a string. */
+static size_t
+hash_string_hasher (void const *name, size_t n_buckets)
+{
+ return hash_string (name, n_buckets);
+}
+
+/* Compare two strings for equality. */
+static bool
+hash_string_compare (void const *name1, void const *name2)
+{
+ return strcmp (name1, name2) == 0;
+}
+
+/* Return zero if TABLE contains a copy of STRING; otherwise, insert a
+ copy of STRING to TABLE and return 1. */
+bool
+hash_string_insert (Hash_table **table, char const *string)
+{
+ Hash_table *t = *table;
+ char *s = xstrdup (string);
+ char *e;
+
+ if (! ((t
+ || (*table = t = hash_initialize (0, 0, hash_string_hasher,
+ hash_string_compare, 0)))
+ && (e = hash_insert (t, s))))
+ xalloc_die ();
+
+ if (e == s)
+ return 1;
+ else
+ {
+ free (s);
+ return 0;
+ }
+}
+
+/* Return 1 if TABLE contains STRING. */
+bool
+hash_string_lookup (Hash_table const *table, char const *string)
+{
+ return table && hash_lookup (table, string);
+}
+
+
+static Hash_table *prefix_table[2];
+
+/* Return true if file names of some members in the archive were stripped off
+ their leading components. We could have used
+ return prefix_table[0] || prefix_table[1]
+ but the following seems to be safer: */
+bool
+removed_prefixes_p (void)
+{
+ return (prefix_table[0] && hash_get_n_entries (prefix_table[0]) != 0)
+ || (prefix_table[1] && hash_get_n_entries (prefix_table[1]) != 0);
+}
+
+/* Return a safer suffix of FILE_NAME, or "." if it has no safer
+ suffix. Check for fully specified file names and other atrocities.
+ Warn the user if we do not return NAME. If LINK_TARGET is 1,
+ FILE_NAME is the target of a hard link, not a member name.
+ If ABSOLUTE_NAMES is 0, strip filesystem prefix from the file name. */
+
+char *
+safer_name_suffix (char const *file_name, bool link_target, bool absolute_names)
+{
+ char const *p;
+
+ if (absolute_names)
+ p = file_name;
+ else
+ {
+ /* Skip file system prefixes, leading file name components that contain
+ "..", and leading slashes. */
+
+ size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (file_name);
+
+ for (p = file_name + prefix_len; *p; )
+ {
+ if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
+ prefix_len = p + 2 - file_name;
+
+ do
+ {
+ char c = *p++;
+ if (ISSLASH (c))
+ break;
+ }
+ while (*p);
+ }
+
+ for (p = file_name + prefix_len; ISSLASH (*p); p++)
+ continue;
+ prefix_len = p - file_name;
+
+ if (prefix_len)
+ {
+ char *prefix = alloca (prefix_len + 1);
+ memcpy (prefix, file_name, prefix_len);
+ prefix[prefix_len] = '\0';
+
+ if (hash_string_insert (&prefix_table[link_target], prefix))
+ {
+ static char const *const diagnostic[] =
+ {
+ N_("Removing leading `%s' from member names"),
+ N_("Removing leading `%s' from hard link targets")
+ };
+ WARN ((0, 0, _(diagnostic[link_target]), prefix));
+ }
+ }
+ }
+
+ if (! *p)
+ {
+ if (p == file_name)
+ {
+ static char const *const diagnostic[] =
+ {
+ N_("Substituting `.' for empty member name"),
+ N_("Substituting `.' for empty hard link target")
+ };
+ WARN ((0, 0, "%s", _(diagnostic[link_target])));
+ }
+
+ p = ".";
+ }
+
+ return (char *) p;
+}
diff --git a/lib/quote.c b/lib/quote.c
new file mode 100644
index 000000000000..119be72ae0ab
--- /dev/null
+++ b/lib/quote.c
@@ -0,0 +1,41 @@
+/* quote.c - quote arguments for output
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#include <config.h>
+
+#include "quotearg.h"
+#include "quote.h"
+
+/* Return an unambiguous printable representation of NAME,
+ allocated in slot N, suitable for diagnostics. */
+char const *
+quote_n (int n, char const *name)
+{
+ return quotearg_n_style (n, locale_quoting_style, name);
+}
+
+/* Return an unambiguous printable representation of NAME,
+ suitable for diagnostics. */
+char const *
+quote (char const *name)
+{
+ return quote_n (0, name);
+}
diff --git a/lib/strchrnul.h b/lib/quote.h
index f7589e990b14..5400eadb6573 100644
--- a/lib/strchrnul.h
+++ b/lib/quote.h
@@ -1,5 +1,7 @@
-/* Searching in a string.
- Copyright (C) 2003 Free Software Foundation, Inc.
+/* quote.h - prototypes for quote.c
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software
+ Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,16 +15,8 @@
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
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-/* Find the first occurrence of C in S or the final NUL byte. */
-extern char *strchrnul (const char *s, int c_in);
-#endif
+char const *quote_n (int n, char const *name);
+char const *quote (char const *name);
diff --git a/lib/quotearg.c b/lib/quotearg.c
new file mode 100644
index 000000000000..f7f326ac5017
--- /dev/null
+++ b/lib/quotearg.c
@@ -0,0 +1,697 @@
+/* quotearg.c - quote arguments for output
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#include <config.h>
+
+#include "quotearg.h"
+
+#include "xalloc.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+#if !HAVE_MBRTOWC
+/* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the
+ other macros are defined only for documentation and to satisfy C
+ syntax. */
+# undef MB_CUR_MAX
+# define MB_CUR_MAX 1
+# undef mbstate_t
+# define mbstate_t int
+# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
+# define iswprint(wc) isprint ((unsigned char) (wc))
+# undef HAVE_MBSINIT
+#endif
+
+#if !defined mbsinit && !HAVE_MBSINIT
+# define mbsinit(ps) 1
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+#define INT_BITS (sizeof (int) * CHAR_BIT)
+
+struct quoting_options
+{
+ /* Basic quoting style. */
+ enum quoting_style style;
+
+ /* Quote the characters indicated by this bit vector even if the
+ quoting style would not normally require them to be quoted. */
+ unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
+};
+
+/* Names of quoting styles. */
+char const *const quoting_style_args[] =
+{
+ "literal",
+ "shell",
+ "shell-always",
+ "c",
+ "escape",
+ "locale",
+ "clocale",
+ 0
+};
+
+/* Correspondences to quoting style names. */
+enum quoting_style const quoting_style_vals[] =
+{
+ literal_quoting_style,
+ shell_quoting_style,
+ shell_always_quoting_style,
+ c_quoting_style,
+ escape_quoting_style,
+ locale_quoting_style,
+ clocale_quoting_style
+};
+
+/* The default quoting options. */
+static struct quoting_options default_quoting_options;
+
+/* Allocate a new set of quoting options, with contents initially identical
+ to O if O is not null, or to the default if O is null.
+ It is the caller's responsibility to free the result. */
+struct quoting_options *
+clone_quoting_options (struct quoting_options *o)
+{
+ int e = errno;
+ struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
+ sizeof *o);
+ errno = e;
+ return p;
+}
+
+/* Get the value of O's quoting style. If O is null, use the default. */
+enum quoting_style
+get_quoting_style (struct quoting_options *o)
+{
+ return (o ? o : &default_quoting_options)->style;
+}
+
+/* In O (or in the default if O is null),
+ set the value of the quoting style to S. */
+void
+set_quoting_style (struct quoting_options *o, enum quoting_style s)
+{
+ (o ? o : &default_quoting_options)->style = s;
+}
+
+/* In O (or in the default if O is null),
+ set the value of the quoting options for character C to I.
+ Return the old value. Currently, the only values defined for I are
+ 0 (the default) and 1 (which means to quote the character even if
+ it would not otherwise be quoted). */
+int
+set_char_quoting (struct quoting_options *o, char c, int i)
+{
+ unsigned char uc = c;
+ unsigned int *p =
+ (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
+ int shift = uc % INT_BITS;
+ int r = (*p >> shift) & 1;
+ *p ^= ((i & 1) ^ r) << shift;
+ return r;
+}
+
+/* MSGID approximates a quotation mark. Return its translation if it
+ has one; otherwise, return either it or "\"", depending on S. */
+static char const *
+gettext_quote (char const *msgid, enum quoting_style s)
+{
+ char const *translation = _(msgid);
+ if (translation == msgid && s == clocale_quoting_style)
+ translation = "\"";
+ return translation;
+}
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+ argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
+ non-quoting-style part of O to control quoting.
+ Terminate the output with a null character, and return the written
+ size of the output, not counting the terminating null.
+ If BUFFERSIZE is too small to store the output string, return the
+ value that would have been returned had BUFFERSIZE been large enough.
+ If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
+
+ This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
+ ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
+ style specified by O, and O may not be null. */
+
+static size_t
+quotearg_buffer_restyled (char *buffer, size_t buffersize,
+ char const *arg, size_t argsize,
+ enum quoting_style quoting_style,
+ struct quoting_options const *o)
+{
+ size_t i;
+ size_t len = 0;
+ char const *quote_string = 0;
+ size_t quote_string_len = 0;
+ bool backslash_escapes = false;
+ bool unibyte_locale = MB_CUR_MAX == 1;
+
+#define STORE(c) \
+ do \
+ { \
+ if (len < buffersize) \
+ buffer[len] = (c); \
+ len++; \
+ } \
+ while (0)
+
+ switch (quoting_style)
+ {
+ case c_quoting_style:
+ STORE ('"');
+ backslash_escapes = true;
+ quote_string = "\"";
+ quote_string_len = 1;
+ break;
+
+ case escape_quoting_style:
+ backslash_escapes = true;
+ break;
+
+ case locale_quoting_style:
+ case clocale_quoting_style:
+ {
+ /* TRANSLATORS:
+ Get translations for open and closing quotation marks.
+
+ The message catalog should translate "`" to a left
+ quotation mark suitable for the locale, and similarly for
+ "'". If the catalog has no translation,
+ locale_quoting_style quotes `like this', and
+ clocale_quoting_style quotes "like this".
+
+ For example, an American English Unicode locale should
+ translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
+ should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
+ MARK). A British English Unicode locale should instead
+ translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
+ U+2019 (RIGHT SINGLE QUOTATION MARK), respectively.
+
+ If you don't know what to put here, please see
+ <http://en.wikipedia.org/wiki/Quotation_mark#Glyphs>
+ and use glyphs suitable for your language. */
+
+ char const *left = gettext_quote (N_("`"), quoting_style);
+ char const *right = gettext_quote (N_("'"), quoting_style);
+ for (quote_string = left; *quote_string; quote_string++)
+ STORE (*quote_string);
+ backslash_escapes = true;
+ quote_string = right;
+ quote_string_len = strlen (quote_string);
+ }
+ break;
+
+ case shell_always_quoting_style:
+ STORE ('\'');
+ quote_string = "'";
+ quote_string_len = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++)
+ {
+ unsigned char c;
+ unsigned char esc;
+
+ if (backslash_escapes
+ && quote_string_len
+ && i + quote_string_len <= argsize
+ && memcmp (arg + i, quote_string, quote_string_len) == 0)
+ STORE ('\\');
+
+ c = arg[i];
+ switch (c)
+ {
+ case '\0':
+ if (backslash_escapes)
+ {
+ STORE ('\\');
+ STORE ('0');
+ STORE ('0');
+ c = '0';
+ }
+ break;
+
+ case '?':
+ switch (quoting_style)
+ {
+ case shell_quoting_style:
+ goto use_shell_always_quoting_style;
+
+ case c_quoting_style:
+ if (i + 2 < argsize && arg[i + 1] == '?')
+ switch (arg[i + 2])
+ {
+ case '!': case '\'':
+ case '(': case ')': case '-': case '/':
+ case '<': case '=': case '>':
+ /* Escape the second '?' in what would otherwise be
+ a trigraph. */
+ c = arg[i + 2];
+ i += 2;
+ STORE ('?');
+ STORE ('\\');
+ STORE ('?');
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case '\a': esc = 'a'; goto c_escape;
+ case '\b': esc = 'b'; goto c_escape;
+ case '\f': esc = 'f'; goto c_escape;
+ case '\n': esc = 'n'; goto c_and_shell_escape;
+ case '\r': esc = 'r'; goto c_and_shell_escape;
+ case '\t': esc = 't'; goto c_and_shell_escape;
+ case '\v': esc = 'v'; goto c_escape;
+ case '\\': esc = c; goto c_and_shell_escape;
+
+ c_and_shell_escape:
+ if (quoting_style == shell_quoting_style)
+ goto use_shell_always_quoting_style;
+ c_escape:
+ if (backslash_escapes)
+ {
+ c = esc;
+ goto store_escape;
+ }
+ break;
+
+ case '{': case '}': /* sometimes special if isolated */
+ if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
+ break;
+ /* Fall through. */
+ case '#': case '~':
+ if (i != 0)
+ break;
+ /* Fall through. */
+ case ' ':
+ case '!': /* special in bash */
+ case '"': case '$': case '&':
+ case '(': case ')': case '*': case ';':
+ case '<':
+ case '=': /* sometimes special in 0th or (with "set -k") later args */
+ case '>': case '[':
+ case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
+ case '`': case '|':
+ /* A shell special character. In theory, '$' and '`' could
+ be the first bytes of multibyte characters, which means
+ we should check them with mbrtowc, but in practice this
+ doesn't happen so it's not worth worrying about. */
+ if (quoting_style == shell_quoting_style)
+ goto use_shell_always_quoting_style;
+ break;
+
+ case '\'':
+ switch (quoting_style)
+ {
+ case shell_quoting_style:
+ goto use_shell_always_quoting_style;
+
+ case shell_always_quoting_style:
+ STORE ('\'');
+ STORE ('\\');
+ STORE ('\'');
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case '%': case '+': case ',': case '-': case '.': case '/':
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': case ':':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+ case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
+ case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
+ case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+ case 'o': case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+ /* These characters don't cause problems, no matter what the
+ quoting style is. They cannot start multibyte sequences. */
+ break;
+
+ default:
+ /* If we have a multibyte sequence, copy it until we reach
+ its end, find an error, or come back to the initial shift
+ state. For C-like styles, if the sequence has
+ unprintable characters, escape the whole sequence, since
+ we can't easily escape single characters within it. */
+ {
+ /* Length of multibyte sequence found so far. */
+ size_t m;
+
+ bool printable;
+
+ if (unibyte_locale)
+ {
+ m = 1;
+ printable = isprint (c) != 0;
+ }
+ else
+ {
+ mbstate_t mbstate;
+ memset (&mbstate, 0, sizeof mbstate);
+
+ m = 0;
+ printable = true;
+ if (argsize == SIZE_MAX)
+ argsize = strlen (arg);
+
+ do
+ {
+ wchar_t w;
+ size_t bytes = mbrtowc (&w, &arg[i + m],
+ argsize - (i + m), &mbstate);
+ if (bytes == 0)
+ break;
+ else if (bytes == (size_t) -1)
+ {
+ printable = false;
+ break;
+ }
+ else if (bytes == (size_t) -2)
+ {
+ printable = false;
+ while (i + m < argsize && arg[i + m])
+ m++;
+ break;
+ }
+ else
+ {
+ /* Work around a bug with older shells that "see" a '\'
+ that is really the 2nd byte of a multibyte character.
+ In practice the problem is limited to ASCII
+ chars >= '@' that are shell special chars. */
+ if ('[' == 0x5b && quoting_style == shell_quoting_style)
+ {
+ size_t j;
+ for (j = 1; j < bytes; j++)
+ switch (arg[i + m + j])
+ {
+ case '[': case '\\': case '^':
+ case '`': case '|':
+ goto use_shell_always_quoting_style;
+
+ default:
+ break;
+ }
+ }
+
+ if (! iswprint (w))
+ printable = false;
+ m += bytes;
+ }
+ }
+ while (! mbsinit (&mbstate));
+ }
+
+ if (1 < m || (backslash_escapes && ! printable))
+ {
+ /* Output a multibyte sequence, or an escaped
+ unprintable unibyte character. */
+ size_t ilim = i + m;
+
+ for (;;)
+ {
+ if (backslash_escapes && ! printable)
+ {
+ STORE ('\\');
+ STORE ('0' + (c >> 6));
+ STORE ('0' + ((c >> 3) & 7));
+ c = '0' + (c & 7);
+ }
+ if (ilim <= i + 1)
+ break;
+ STORE (c);
+ c = arg[++i];
+ }
+
+ goto store_c;
+ }
+ }
+ }
+
+ if (! (backslash_escapes
+ && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
+ goto store_c;
+
+ store_escape:
+ STORE ('\\');
+
+ store_c:
+ STORE (c);
+ }
+
+ if (i == 0 && quoting_style == shell_quoting_style)
+ goto use_shell_always_quoting_style;
+
+ if (quote_string)
+ for (; *quote_string; quote_string++)
+ STORE (*quote_string);
+
+ if (len < buffersize)
+ buffer[len] = '\0';
+ return len;
+
+ use_shell_always_quoting_style:
+ return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
+ shell_always_quoting_style, o);
+}
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+ argument ARG (of size ARGSIZE), using O to control quoting.
+ If O is null, use the default.
+ Terminate the output with a null character, and return the written
+ size of the output, not counting the terminating null.
+ If BUFFERSIZE is too small to store the output string, return the
+ value that would have been returned had BUFFERSIZE been large enough.
+ If ARGSIZE is SIZE_MAX, use the string length of the argument for
+ ARGSIZE. */
+size_t
+quotearg_buffer (char *buffer, size_t buffersize,
+ char const *arg, size_t argsize,
+ struct quoting_options const *o)
+{
+ struct quoting_options const *p = o ? o : &default_quoting_options;
+ int e = errno;
+ size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
+ p->style, p);
+ errno = e;
+ return r;
+}
+
+/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
+ allocated storage containing the quoted string. */
+char *
+quotearg_alloc (char const *arg, size_t argsize,
+ struct quoting_options const *o)
+{
+ int e = errno;
+ size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1;
+ char *buf = xcharalloc (bufsize);
+ quotearg_buffer (buf, bufsize, arg, argsize, o);
+ errno = e;
+ return buf;
+}
+
+/* A storage slot with size and pointer to a value. */
+struct slotvec
+{
+ size_t size;
+ char *val;
+};
+
+/* Preallocate a slot 0 buffer, so that the caller can always quote
+ one small component of a "memory exhausted" message in slot 0. */
+static char slot0[256];
+static unsigned int nslots = 1;
+static struct slotvec slotvec0 = {sizeof slot0, slot0};
+static struct slotvec *slotvec = &slotvec0;
+
+void
+quotearg_free (void)
+{
+ struct slotvec *sv = slotvec;
+ unsigned int i;
+ for (i = 1; i < nslots; i++)
+ free (sv[i].val);
+ if (sv[0].val != slot0)
+ {
+ free (sv[0].val);
+ slotvec0.size = sizeof slot0;
+ slotvec0.val = slot0;
+ }
+ if (sv != &slotvec0)
+ {
+ free (sv);
+ slotvec = &slotvec0;
+ }
+ nslots = 1;
+}
+
+/* Use storage slot N to return a quoted version of argument ARG.
+ ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
+ null-terminated string.
+ OPTIONS specifies the quoting options.
+ The returned value points to static storage that can be
+ reused by the next call to this function with the same value of N.
+ N must be nonnegative. N is deliberately declared with type "int"
+ to allow for future extensions (using negative values). */
+static char *
+quotearg_n_options (int n, char const *arg, size_t argsize,
+ struct quoting_options const *options)
+{
+ int e = errno;
+
+ unsigned int n0 = n;
+ struct slotvec *sv = slotvec;
+
+ if (n < 0)
+ abort ();
+
+ if (nslots <= n0)
+ {
+ /* FIXME: technically, the type of n1 should be `unsigned int',
+ but that evokes an unsuppressible warning from gcc-4.0.1 and
+ older. If gcc ever provides an option to suppress that warning,
+ revert to the original type, so that the test in xalloc_oversized
+ is once again performed only at compile time. */
+ size_t n1 = n0 + 1;
+ bool preallocated = (sv == &slotvec0);
+
+ if (xalloc_oversized (n1, sizeof *sv))
+ xalloc_die ();
+
+ slotvec = sv = xrealloc (preallocated ? NULL : sv, n1 * sizeof *sv);
+ if (preallocated)
+ *sv = slotvec0;
+ memset (sv + nslots, 0, (n1 - nslots) * sizeof *sv);
+ nslots = n1;
+ }
+
+ {
+ size_t size = sv[n].size;
+ char *val = sv[n].val;
+ size_t qsize = quotearg_buffer (val, size, arg, argsize, options);
+
+ if (size <= qsize)
+ {
+ sv[n].size = size = qsize + 1;
+ if (val != slot0)
+ free (val);
+ sv[n].val = val = xcharalloc (size);
+ quotearg_buffer (val, size, arg, argsize, options);
+ }
+
+ errno = e;
+ return val;
+ }
+}
+
+char *
+quotearg_n (int n, char const *arg)
+{
+ return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
+}
+
+char *
+quotearg (char const *arg)
+{
+ return quotearg_n (0, arg);
+}
+
+/* Return quoting options for STYLE, with no extra quoting. */
+static struct quoting_options
+quoting_options_from_style (enum quoting_style style)
+{
+ struct quoting_options o;
+ o.style = style;
+ memset (o.quote_these_too, 0, sizeof o.quote_these_too);
+ return o;
+}
+
+char *
+quotearg_n_style (int n, enum quoting_style s, char const *arg)
+{
+ struct quoting_options const o = quoting_options_from_style (s);
+ return quotearg_n_options (n, arg, SIZE_MAX, &o);
+}
+
+char *
+quotearg_n_style_mem (int n, enum quoting_style s,
+ char const *arg, size_t argsize)
+{
+ struct quoting_options const o = quoting_options_from_style (s);
+ return quotearg_n_options (n, arg, argsize, &o);
+}
+
+char *
+quotearg_style (enum quoting_style s, char const *arg)
+{
+ return quotearg_n_style (0, s, arg);
+}
+
+char *
+quotearg_char (char const *arg, char ch)
+{
+ struct quoting_options options;
+ options = default_quoting_options;
+ set_char_quoting (&options, ch, 1);
+ return quotearg_n_options (0, arg, SIZE_MAX, &options);
+}
+
+char *
+quotearg_colon (char const *arg)
+{
+ return quotearg_char (arg, ':');
+}
diff --git a/lib/quotearg.h b/lib/quotearg.h
new file mode 100644
index 000000000000..4887df3b6d5d
--- /dev/null
+++ b/lib/quotearg.h
@@ -0,0 +1,140 @@
+/* quotearg.h - quote arguments for output
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#ifndef QUOTEARG_H_
+# define QUOTEARG_H_ 1
+
+# include <stddef.h>
+
+/* Basic quoting styles. */
+enum quoting_style
+ {
+ /* Output names as-is (ls --quoting-style=literal). */
+ literal_quoting_style,
+
+ /* Quote names for the shell if they contain shell metacharacters
+ or would cause ambiguous output (ls --quoting-style=shell). */
+ shell_quoting_style,
+
+ /* Quote names for the shell, even if they would normally not
+ require quoting (ls --quoting-style=shell-always). */
+ shell_always_quoting_style,
+
+ /* Quote names as for a C language string (ls --quoting-style=c). */
+ c_quoting_style,
+
+ /* Like c_quoting_style except omit the surrounding double-quote
+ characters (ls --quoting-style=escape). */
+ escape_quoting_style,
+
+ /* Like clocale_quoting_style, but quote `like this' instead of
+ "like this" in the default C locale (ls --quoting-style=locale). */
+ locale_quoting_style,
+
+ /* Like c_quoting_style except use quotation marks appropriate for
+ the locale (ls --quoting-style=clocale). */
+ clocale_quoting_style
+ };
+
+/* For now, --quoting-style=literal is the default, but this may change. */
+# ifndef DEFAULT_QUOTING_STYLE
+# define DEFAULT_QUOTING_STYLE literal_quoting_style
+# endif
+
+/* Names of quoting styles and their corresponding values. */
+extern char const *const quoting_style_args[];
+extern enum quoting_style const quoting_style_vals[];
+
+struct quoting_options;
+
+/* The functions listed below set and use a hidden variable
+ that contains the default quoting style options. */
+
+/* Allocate a new set of quoting options, with contents initially identical
+ to O if O is not null, or to the default if O is null.
+ It is the caller's responsibility to free the result. */
+struct quoting_options *clone_quoting_options (struct quoting_options *o);
+
+/* Get the value of O's quoting style. If O is null, use the default. */
+enum quoting_style get_quoting_style (struct quoting_options *o);
+
+/* In O (or in the default if O is null),
+ set the value of the quoting style to S. */
+void set_quoting_style (struct quoting_options *o, enum quoting_style s);
+
+/* In O (or in the default if O is null),
+ set the value of the quoting options for character C to I.
+ Return the old value. Currently, the only values defined for I are
+ 0 (the default) and 1 (which means to quote the character even if
+ it would not otherwise be quoted). */
+int set_char_quoting (struct quoting_options *o, char c, int i);
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+ argument ARG (of size ARGSIZE), using O to control quoting.
+ If O is null, use the default.
+ Terminate the output with a null character, and return the written
+ size of the output, not counting the terminating null.
+ If BUFFERSIZE is too small to store the output string, return the
+ value that would have been returned had BUFFERSIZE been large enough.
+ If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */
+size_t quotearg_buffer (char *buffer, size_t buffersize,
+ char const *arg, size_t argsize,
+ struct quoting_options const *o);
+
+/* Like quotearg_buffer, except return the result in a newly allocated
+ buffer. It is the caller's responsibility to free the result. */
+char *quotearg_alloc (char const *arg, size_t argsize,
+ struct quoting_options const *o);
+
+/* Use storage slot N to return a quoted version of the string ARG.
+ Use the default quoting options.
+ The returned value points to static storage that can be
+ reused by the next call to this function with the same value of N.
+ N must be nonnegative. */
+char *quotearg_n (int n, char const *arg);
+
+/* Equivalent to quotearg_n (0, ARG). */
+char *quotearg (char const *arg);
+
+/* Use style S and storage slot N to return a quoted version of the string ARG.
+ This is like quotearg_n (N, ARG), except that it uses S with no other
+ options to specify the quoting method. */
+char *quotearg_n_style (int n, enum quoting_style s, char const *arg);
+
+/* Use style S and storage slot N to return a quoted version of the
+ argument ARG of size ARGSIZE. This is like quotearg_n_style
+ (N, S, ARG), except it can quote null bytes. */
+char *quotearg_n_style_mem (int n, enum quoting_style s,
+ char const *arg, size_t argsize);
+
+/* Equivalent to quotearg_n_style (0, S, ARG). */
+char *quotearg_style (enum quoting_style s, char const *arg);
+
+/* Like quotearg (ARG), except also quote any instances of CH. */
+char *quotearg_char (char const *arg, char ch);
+
+/* Equivalent to quotearg_char (ARG, ':'). */
+char *quotearg_colon (char const *arg);
+
+/* Free any dynamically allocated memory. */
+void quotearg_free (void);
+
+#endif /* !QUOTEARG_H_ */
diff --git a/lib/localedir.h b/lib/rmt-command.h
index 7460e6fc9627..7460e6fc9627 100644
--- a/lib/localedir.h
+++ b/lib/rmt-command.h
diff --git a/lib/rmt.h b/lib/rmt.h
index 1fd2f29f9af4..9f96cdb9b5f0 100644
--- a/lib/rmt.h
+++ b/lib/rmt.h
@@ -15,7 +15,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
extern char *rmt_command;
extern char *rmt_dev_name__;
diff --git a/lib/rtapelib.c b/lib/rtapelib.c
index 0e499b638ca7..af19b04c5d43 100644
--- a/lib/rtapelib.c
+++ b/lib/rtapelib.c
@@ -1,7 +1,7 @@
/* Functions for communicating with a remote tape drive.
- Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004 Free
- Software Foundation, Inc.
+ Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004,
+ 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* The man page rmt(8) for /etc/rmt documents the remote mag tape protocol
which rdump and rrestore use. Unfortunately, the man page is *WRONG*.
@@ -33,6 +33,8 @@
code, courtesy of Dan Kegel. */
#include "system.h"
+#include "system-ioctl.h"
+
#include <safe-read.h>
#include <full-write.h>
@@ -58,7 +60,7 @@
#endif
#include <rmt.h>
-#include <localedir.h>
+#include <rmt-command.h>
/* Exit status if exec errors. */
#define EXIT_ON_EXEC_ERROR 128
@@ -340,9 +342,7 @@ encode_oflag (char *buf, int oflag)
#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
@@ -358,7 +358,7 @@ encode_oflag (char *buf, int oflag)
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,
+rmt_open__ (const char *file_name, int open_mode, int bias,
const char *remote_shell)
{
int remote_pipe_number; /* pseudo, biased file descriptor */
diff --git a/lib/safe-read.c b/lib/safe-read.c
index 6f8bd780ed01..b7bf1d5cd60e 100644
--- a/lib/safe-read.c
+++ b/lib/safe-read.c
@@ -1,7 +1,7 @@
/* An interface to read and write that retries after interrupts.
- Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004 Free Software
- Foundation, Inc.
+ Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004, 2005, 2006 Free
+ Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,11 +15,9 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
/* Specification. */
#ifdef SAFE_WRITE
@@ -30,9 +28,7 @@
/* Get ssize_t. */
#include <sys/types.h>
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
+#include <unistd.h>
#include <errno.h>
diff --git a/lib/safe-read.h b/lib/safe-read.h
index cbe6e0bfd60c..3451955ad4ff 100644
--- a/lib/safe-read.h
+++ b/lib/safe-read.h
@@ -1,5 +1,5 @@
/* An interface to read() that retries after interrupts.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,13 +13,23 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <stddef.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
#define SAFE_READ_ERROR ((size_t) -1)
/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted.
Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR
upon error. */
extern size_t safe_read (int fd, void *buf, size_t count);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/safe-write.c b/lib/safe-write.c
index fbafa7cc6776..4c375a6ca190 100644
--- a/lib/safe-write.c
+++ b/lib/safe-write.c
@@ -13,7 +13,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#define SAFE_WRITE
#include "safe-read.c"
diff --git a/lib/safe-write.h b/lib/safe-write.h
index ab1f45b4ab2b..c194636209f7 100644
--- a/lib/safe-write.h
+++ b/lib/safe-write.h
@@ -13,7 +13,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <stddef.h>
diff --git a/lib/savedir.c b/lib/savedir.c
index c92e62eadccd..d930fb4af273 100644
--- a/lib/savedir.c
+++ b/lib/savedir.c
@@ -1,7 +1,7 @@
/* 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.
+ Copyright (C) 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+ 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,13 +15,11 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
#include "savedir.h"
@@ -29,68 +27,62 @@
#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)
+#include <dirent.h>
+#ifndef _D_EXACT_NAMLEN
+# define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)
#endif
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
+#include "openat.h"
#include "xalloc.h"
-/* 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)
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+ therefore save some unnecessary work in fchdir.c. */
+#undef opendir
+#undef closedir
+
+/* Return a freshly allocated string containing the file names
+ in directory DIRP, separated by '\0' characters;
+ the end is marked by two '\0' characters in a row.
+ Return NULL (setting errno) if DIRP cannot be read or closed.
+ If DIRP is NULL, return NULL without affecting errno. */
+
+static char *
+savedirstream (DIR *dirp)
{
- 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)
+ for (;;)
{
+ struct dirent const *dp;
+ char const *entry;
+
+ errno = 0;
+ dp = readdir (dirp);
+ if (! dp)
+ break;
+
/* Skip "", ".", and "..". "" is returned by at least one buggy
implementation: Solaris 2.4 readdir on NFS file systems. */
- char const *entry = dp->d_name;
+ entry = dp->d_name;
if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
{
- size_t entry_size = strlen (entry) + 1;
+ size_t entry_size = _D_EXACT_NAMLEN (dp) + 1;
if (used + entry_size < used)
xalloc_die ();
if (allocated <= used + entry_size)
@@ -111,7 +103,7 @@ savedir (const char *dir)
}
name_space[used] = '\0';
save_errno = errno;
- if (CLOSEDIR (dirp) != 0)
+ if (closedir (dirp) != 0)
save_errno = errno;
if (save_errno != 0)
{
@@ -121,3 +113,25 @@ savedir (const char *dir)
}
return name_space;
}
+
+/* Return a freshly allocated string containing the file names
+ in directory DIR, separated by '\0' characters;
+ the end is marked by two '\0' characters in a row.
+ Return NULL (setting errno) if DIR cannot be opened, read, or closed. */
+
+char *
+savedir (char const *dir)
+{
+ return savedirstream (opendir (dir));
+}
+
+/* Return a freshly allocated string containing the file names
+ in directory FD, separated by '\0' characters;
+ the end is marked by two '\0' characters in a row.
+ Return NULL (setting errno) if FD cannot be read or closed. */
+
+char *
+fdsavedir (int fd)
+{
+ return savedirstream (fdopendir (fd));
+}
diff --git a/lib/savedir.h b/lib/savedir.h
index bd330852149b..5b7bef97134e 100644
--- a/lib/savedir.h
+++ b/lib/savedir.h
@@ -1,6 +1,6 @@
/* Save the list of files in a directory in a string.
- Copyright 1997, 1999, 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,13 +14,14 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#if !defined SAVEDIR_H_
# define SAVEDIR_H_
-char *savedir (const char *dir);
+char *savedir (char const *dir);
+char *fdsavedir (int fd);
#endif
diff --git a/lib/strcase.h b/lib/strcase.h
deleted file mode 100644
index 9461392f8d6a..000000000000
--- a/lib/strcase.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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 */
diff --git a/lib/strchrnul.c b/lib/strchrnul.c
index be85312c4611..07014be17afb 100644
--- a/lib/strchrnul.c
+++ b/lib/strchrnul.c
@@ -1,5 +1,5 @@
/* Searching in a string.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,10 +13,12 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
/* Specification. */
-#include "strchrnul.h"
+#include <string.h>
/* Find the first occurrence of C in S or the final NUL byte. */
char *
diff --git a/lib/stripslash.c b/lib/stripslash.c
index 9998e641ced7..342d497c8993 100644
--- a/lib/stripslash.c
+++ b/lib/stripslash.c
@@ -1,5 +1,6 @@
/* stripslash.c -- remove redundant trailing slashes from a file name
- Copyright (C) 1990, 2001, 2003, 2004 Free Software Foundation, Inc.
+
+ Copyright (C) 1990, 2001, 2003-2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,27 +14,32 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
#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). */
+/* Remove trailing slashes from FILE. Return true if a trailing slash
+ was removed. This is useful when using file name completion from a
+ shell that adds a "/" after directory names (such as tcsh and
+ bash), because on symlinks to directories, several system calls
+ have different semantics according to whether a trailing slash is
+ present. */
bool
-strip_trailing_slashes (char *path)
+strip_trailing_slashes (char *file)
{
- char *base = base_name (path);
- char *base_lim = base + base_len (base);
- bool had_slash = (*base_lim != '\0');
+ char *base = last_component (file);
+ char *base_lim;
+ bool had_slash;
+
+ /* last_component returns "" for file system roots, but we need to turn
+ `///' into `/'. */
+ if (! *base)
+ base = file;
+ base_lim = base + base_len (base);
+ had_slash = (*base_lim != '\0');
*base_lim = '\0';
return had_slash;
}
diff --git a/lib/strndup.c b/lib/strndup.c
index f85627e879d2..3a1b0eae2e06 100644
--- a/lib/strndup.c
+++ b/lib/strndup.c
@@ -1,7 +1,7 @@
-/* Copyright (C) 1996, 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
+/* A replacement function, for systems that lack strndup.
- 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.
+ Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -15,31 +15,16 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include <config.h>
-#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
+#include <stdlib.h>
char *
-__strndup (const char *s, size_t n)
+strndup (char const *s, size_t n)
{
size_t len = strnlen (s, n);
char *new = malloc (len + 1);
@@ -50,6 +35,3 @@ __strndup (const char *s, size_t n)
new[len] = '\0';
return memcpy (new, s, len);
}
-#ifdef weak_alias
-weak_alias (__strndup, strndup)
-#endif
diff --git a/lib/strnlen.c b/lib/strnlen.c
index c9f389845117..d346d3272c29 100644
--- a/lib/strnlen.c
+++ b/lib/strnlen.c
@@ -1,6 +1,6 @@
/* 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.
+ Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+ Written by Simon Josefsson.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -12,37 +12,20 @@
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. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-#undef strnlen
+#include <config.h>
#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)
+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
diff --git a/lib/system-ioctl.h b/lib/system-ioctl.h
new file mode 100644
index 000000000000..a61c5fdfb01c
--- /dev/null
+++ b/lib/system-ioctl.h
@@ -0,0 +1,55 @@
+/* System dependent definitions for GNU tar's use of ioctl macros.
+
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
+ 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* This is a real challenge to properly get MTIO* symbols :-(. ISC uses
+ <sys/gentape.h>. SCO and BSDi uses <sys/tape.h>; BSDi also requires
+ <sys/tprintf.h> and <sys/device.h> for defining tp_dev and tpr_t. It
+ seems that the rest use <sys/mtio.h>, which itself requires other files,
+ depending on systems. Pyramid defines _IOW in <sgtty.h>, for example. */
+
+#if HAVE_SYS_GENTAPE_H
+# include <sys/gentape.h>
+#else
+# if HAVE_SYS_TAPE_H
+# if HAVE_SYS_DEVICE_H
+# include <sys/device.h>
+# endif
+# if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# endif
+# if HAVE_SYS_BUF_H
+# include <sys/buf.h>
+# endif
+# if HAVE_SYS_TPRINTF_H
+# include <sys/tprintf.h>
+# endif
+# include <sys/tape.h>
+# else
+# if HAVE_SYS_MTIO_H
+# include <sys/ioctl.h>
+# if HAVE_SGTTY_H
+# include <sgtty.h>
+# endif
+# if HAVE_SYS_IO_TRIOCTL_H
+# include <sys/io/trioctl.h>
+# endif
+# include <sys/mtio.h>
+# endif
+# endif
+#endif
diff --git a/lib/system.h b/lib/system.h
index 091419513207..7602263f1393 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -1,7 +1,7 @@
/* System dependent definitions for GNU tar.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
- 2004 Free Software Foundation, Inc.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,8 +15,7 @@
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.
-*/
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#if HAVE_CONFIG_H
# include <config.h>
@@ -109,10 +108,19 @@ extern int errno;
#ifndef O_TRUNC
# define O_TRUNC 32 /* truncate file on open */
#endif
- /* MS-DOG forever, with my love! */
-#ifndef O_BINARY
+
+#ifndef O_BINARY
# define O_BINARY 0
#endif
+#ifndef O_DIRECTORY
+# define O_DIRECTORY 0
+#endif
+#ifndef O_NOATIME
+# define O_NOATIME 0
+#endif
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 0
+#endif
/* Declare file status routines and bits. */
@@ -252,9 +260,7 @@ extern int errno;
#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
+#include <unistd.h>
#ifndef SEEK_SET
# define SEEK_SET 0
@@ -282,6 +288,9 @@ extern int errno;
#if MAJOR_IN_MKDEV
# include <sys/mkdev.h>
+# if !defined(makedev) && defined(mkdev)
+# define makedev(a,b) mkdev((a),(b))
+# endif
# define GOT_MAJOR
#endif
@@ -377,45 +386,12 @@ extern int errno;
#endif
#ifndef ST_NBLOCKSIZE
-#define ST_NBLOCKSIZE 512
+# 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
+#define ST_IS_SPARSE(st) \
+ (ST_NBLOCKS (st) \
+ < ((st).st_size / ST_NBLOCKSIZE + ((st).st_size % ST_NBLOCKSIZE != 0)))
/* Declare standard functions. */
@@ -435,7 +411,6 @@ char *getenv ();
#endif
#if WITH_DMALLOC
-# undef HAVE_DECL_VALLOC
# define DMALLOC_FUNC_CHECK
# include <dmalloc.h>
#endif
@@ -446,28 +421,11 @@ char *getenv ();
# 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)))
+#include <inttypes.h>
-/* 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))
+#include <intprops.h>
-#define UINTMAX_STRSIZE_BOUND (INT_STRLEN_BOUND (uintmax_t) + 1)
+#define UINTMAX_STRSIZE_BOUND INT_BUFSIZE_BOUND (uintmax_t)
/* Prototypes for external functions. */
@@ -479,16 +437,9 @@ char *getenv ();
#endif
#include <time.h>
-#if defined(HAVE_SYS_TIME_H) && defined(TIME_WITH_SYS_TIME)
+#ifdef 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. */
diff --git a/lib/umaxtostr.c b/lib/umaxtostr.c
new file mode 100644
index 000000000000..4f49a7f8ddd9
--- /dev/null
+++ b/lib/umaxtostr.c
@@ -0,0 +1,3 @@
+#define inttostr umaxtostr
+#define inttype uintmax_t
+#include "inttostr.c"
diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h
index 3ff42f279b86..d00930361c26 100644
--- a/lib/unlocked-io.h
+++ b/lib/unlocked-io.h
@@ -14,12 +14,12 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by Jim Meyering. */
#ifndef UNLOCKED_IO_H
-#define UNLOCKED_IO_H 1
+# 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.
@@ -32,106 +32,106 @@
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)
+# 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 */
diff --git a/lib/utimens.c b/lib/utimens.c
new file mode 100644
index 000000000000..7e3175a49516
--- /dev/null
+++ b/lib/utimens.c
@@ -0,0 +1,189 @@
+/* Set file access and modification times.
+
+ Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+/* derived from a function in touch.c */
+
+#include <config.h>
+
+#include "utimens.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#if HAVE_UTIME_H
+# include <utime.h>
+#endif
+
+/* Some systems (even some that do have <utime.h>) don't declare this
+ structure anywhere. */
+#ifndef HAVE_STRUCT_UTIMBUF
+struct utimbuf
+{
+ long actime;
+ long modtime;
+};
+#endif
+
+/* Some systems don't have ENOSYS. */
+#ifndef ENOSYS
+# ifdef ENOTSUP
+# define ENOSYS ENOTSUP
+# else
+/* Some systems don't have ENOTSUP either. */
+# define ENOSYS EINVAL
+# endif
+#endif
+
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+# define __attribute__(x)
+# endif
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
+ TIMESPEC[0] and TIMESPEC[1], respectively.
+ FD must be either negative -- in which case it is ignored --
+ or a file descriptor that is open on FILE.
+ If FD is nonnegative, then FILE can be NULL, which means
+ use just futimes (or equivalent) instead of utimes (or equivalent),
+ and fail if on an old system without futimes (or equivalent).
+ If TIMESPEC is null, set the time stamps to the current time.
+ Return 0 on success, -1 (setting errno) on failure. */
+
+int
+gl_futimens (int fd ATTRIBUTE_UNUSED,
+ char const *file, struct timespec const timespec[2])
+{
+ /* Some Linux-based NFS clients are buggy, and mishandle time stamps
+ of files in NFS file systems in some cases. We have no
+ configure-time test for this, but please see
+ <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
+ some of the problems with Linux 2.6.16. If this affects you,
+ compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
+ help in some cases, albeit at a cost in performance. But you
+ really should upgrade your kernel to a fixed version, since the
+ problem affects many applications. */
+
+#if HAVE_BUGGY_NFS_TIME_STAMPS
+ if (fd < 0)
+ sync ();
+ else
+ fsync (fd);
+#endif
+
+ /* There's currently no interface to set file timestamps with
+ nanosecond resolution, so do the best we can, discarding any
+ fractional part of the timestamp. */
+#if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
+ struct timeval timeval[2];
+ struct timeval const *t;
+ if (timespec)
+ {
+ timeval[0].tv_sec = timespec[0].tv_sec;
+ timeval[0].tv_usec = timespec[0].tv_nsec / 1000;
+ timeval[1].tv_sec = timespec[1].tv_sec;
+ timeval[1].tv_usec = timespec[1].tv_nsec / 1000;
+ t = timeval;
+ }
+ else
+ t = NULL;
+
+
+ if (fd < 0)
+ {
+# if HAVE_FUTIMESAT
+ return futimesat (AT_FDCWD, file, t);
+# endif
+ }
+ else
+ {
+ /* If futimesat or futimes fails here, don't try to speed things
+ up by returning right away. glibc can incorrectly fail with
+ errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
+ in high security mode doesn't allow ordinary users to read
+ /proc/self, so glibc incorrectly fails with errno == EACCES.
+ If errno == EIO, EPERM, or EROFS, it's probably safe to fail
+ right away, but these cases are rare enough that they're not
+ worth optimizing, and who knows what other messed-up systems
+ are out there? So play it safe and fall back on the code
+ below. */
+# if HAVE_FUTIMESAT
+ if (futimesat (fd, NULL, t) == 0)
+ return 0;
+# elif HAVE_FUTIMES
+ if (futimes (fd, t) == 0)
+ return 0;
+# endif
+ }
+#endif
+
+ if (!file)
+ {
+#if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
+ errno = ENOSYS;
+#endif
+
+ /* Prefer EBADF to ENOSYS if both error numbers apply. */
+ if (errno == ENOSYS)
+ {
+ int fd2 = dup (fd);
+ int dup_errno = errno;
+ if (0 <= fd2)
+ close (fd2);
+ errno = (fd2 < 0 && dup_errno == EBADF ? EBADF : ENOSYS);
+ }
+
+ return -1;
+ }
+
+#if HAVE_WORKING_UTIMES
+ return utimes (file, t);
+#else
+ {
+ struct utimbuf utimbuf;
+ struct utimbuf const *ut;
+ if (timespec)
+ {
+ utimbuf.actime = timespec[0].tv_sec;
+ utimbuf.modtime = timespec[1].tv_sec;
+ ut = &utimbuf;
+ }
+ else
+ ut = NULL;
+
+ return utime (file, ut);
+ }
+#endif
+}
+
+/* Set the access and modification time stamps of FILE to be
+ TIMESPEC[0] and TIMESPEC[1], respectively. */
+int
+utimens (char const *file, struct timespec const timespec[2])
+{
+ return gl_futimens (-1, file, timespec);
+}
diff --git a/lib/utimens.h b/lib/utimens.h
new file mode 100644
index 000000000000..169521da73ac
--- /dev/null
+++ b/lib/utimens.h
@@ -0,0 +1,3 @@
+#include <time.h>
+int gl_futimens (int, char const *, struct timespec const [2]);
+int utimens (char const *, struct timespec const [2]);
diff --git a/lib/xalloc-die.c b/lib/xalloc-die.c
index ca3a689fa5c4..090f060df784 100644
--- a/lib/xalloc-die.c
+++ b/lib/xalloc-die.c
@@ -1,6 +1,6 @@
/* Report a memory allocation failure and exit.
- Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004 Free
+ Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2006 Free
Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -15,11 +15,9 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
#include "xalloc.h"
@@ -30,7 +28,6 @@
#include "gettext.h"
#define _(msgid) gettext (msgid)
-#define N_(msgid) msgid
void
xalloc_die (void)
diff --git a/lib/xalloc.h b/lib/xalloc.h
index 8d0fcf0faeed..0c6d8dcf508d 100644
--- a/lib/xalloc.h
+++ b/lib/xalloc.h
@@ -1,7 +1,7 @@
/* 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.
+ 1999, 2000, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef XALLOC_H_
# define XALLOC_H_
@@ -46,13 +46,10 @@ extern "C" {
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);
@@ -71,8 +68,203 @@ char *xstrdup (char const *str);
# define xalloc_oversized(n, s) \
((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
+
+/* In the following macros, T must be an elementary or structure/union or
+ typedef'ed type, or a pointer to such a type. To apply one of the
+ following macros to a function pointer or array type, you need to typedef
+ it first and use the typedef name. */
+
+/* Allocate an object of type T dynamically, with error checking. */
+/* extern t *XMALLOC (typename t); */
+# define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
+
+/* Allocate memory for N elements of type T, with error checking. */
+/* extern t *XNMALLOC (size_t n, typename t); */
+# define XNMALLOC(n, t) \
+ ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
+
+/* Allocate an object of type T dynamically, with error checking,
+ and zero it. */
+/* extern t *XZALLOC (typename t); */
+# define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
+
+/* Allocate memory for N elements of type T, with error checking,
+ and zero it. */
+/* extern t *XCALLOC (size_t n, typename t); */
+# define XCALLOC(n, t) \
+ ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
+
+
+# if HAVE_INLINE
+# define static_inline static inline
+# else
+ void *xnmalloc (size_t n, size_t s);
+ void *xnrealloc (void *p, size_t n, size_t s);
+ void *x2nrealloc (void *p, size_t *pn, size_t s);
+ char *xcharalloc (size_t n);
+# endif
+
+# ifdef static_inline
+
+/* Allocate an array of N objects, each with S bytes of memory,
+ dynamically, with error checking. S must be nonzero. */
+
+static_inline void *
+xnmalloc (size_t n, size_t s)
+{
+ if (xalloc_oversized (n, s))
+ xalloc_die ();
+ return xmalloc (n * s);
+}
+
+/* Change the size of an allocated block of memory P to an array of N
+ objects each of S bytes, with error checking. S must be nonzero. */
+
+static_inline void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+ if (xalloc_oversized (n, s))
+ xalloc_die ();
+ return xrealloc (p, n * s);
+}
+
+/* If P is null, allocate a block of at least *PN such objects;
+ otherwise, reallocate P so that it contains more than *PN objects
+ each of S bytes. *PN must be nonzero unless P is null, and S must
+ be nonzero. Set *PN to the new number of objects, and return the
+ pointer to the new block. *PN is never set to zero, and the
+ returned pointer is never null.
+
+ Repeated reallocations are guaranteed to make progress, either by
+ allocating an initial block with a nonzero size, or by allocating a
+ larger block.
+
+ In the following implementation, nonzero sizes are increased by a
+ factor of approximately 1.5 so that repeated reallocations have
+ O(N) overall cost rather than O(N**2) cost, but the
+ specification for this function does not guarantee that rate.
+
+ Here is an example of use:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ p = x2nrealloc (p, &allocated, sizeof *p);
+ p[used++] = value;
+ }
+
+ This causes x2nrealloc to allocate a block of some nonzero size the
+ first time it is called.
+
+ To have finer-grained control over the initial size, set *PN to a
+ nonzero value before calling this function with P == NULL. For
+ example:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+ size_t allocated1 = 1000;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ {
+ p = x2nrealloc (p, &allocated1, sizeof *p);
+ allocated = allocated1;
+ }
+ p[used++] = value;
+ }
+
+ */
+
+static_inline void *
+x2nrealloc (void *p, size_t *pn, size_t s)
+{
+ size_t n = *pn;
+
+ if (! p)
+ {
+ if (! n)
+ {
+ /* The approximate size to use for initial small allocation
+ requests, when the invoking code specifies an old size of
+ zero. 64 bytes is the largest "small" request for the
+ GNU C library malloc. */
+ enum { DEFAULT_MXFAST = 64 };
+
+ n = DEFAULT_MXFAST / s;
+ n += !n;
+ }
+ }
+ else
+ {
+ /* Set N = ceil (1.5 * N) so that progress is made if N == 1.
+ Check for overflow, so that N * S stays in size_t range.
+ The check is slightly conservative, but an exact check isn't
+ worth the trouble. */
+ if ((size_t) -1 / 3 * 2 / s <= n)
+ xalloc_die ();
+ n += (n + 1) / 2;
+ }
+
+ *pn = n;
+ return xrealloc (p, n * s);
+}
+
+/* Return a pointer to a new buffer of N bytes. This is like xmalloc,
+ except it returns char *. */
+
+static_inline char *
+xcharalloc (size_t n)
+{
+ return XNMALLOC (n, char);
+}
+
+# endif
+
# ifdef __cplusplus
}
+
+/* C++ does not allow conversions from void * to other pointer types
+ without a cast. Use templates to work around the problem when
+ possible. */
+
+template <typename T> inline T *
+xrealloc (T *p, size_t s)
+{
+ return (T *) xrealloc ((void *) p, s);
+}
+
+template <typename T> inline T *
+xnrealloc (T *p, size_t n, size_t s)
+{
+ return (T *) xnrealloc ((void *) p, n, s);
+}
+
+template <typename T> inline T *
+x2realloc (T *p, size_t *pn)
+{
+ return (T *) x2realloc ((void *) p, pn);
+}
+
+template <typename T> inline T *
+x2nrealloc (T *p, size_t *pn, size_t s)
+{
+ return (T *) x2nrealloc ((void *) p, pn, s);
+}
+
+template <typename T> inline T *
+xmemdup (T const *p, size_t s)
+{
+ return (T *) xmemdup ((void const *) p, s);
+}
+
# endif
diff --git a/lib/xmalloc.c b/lib/xmalloc.c
index 13c2490267d4..318e0ddb5a70 100644
--- a/lib/xmalloc.c
+++ b/lib/xmalloc.c
@@ -1,7 +1,8 @@
/* 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.
+ 1999, 2000, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+ Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,13 +16,15 @@
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. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
+#if ! HAVE_INLINE
+# define static_inline
+#endif
#include "xalloc.h"
+#undef static_inline
#include <stdlib.h>
#include <string.h>
@@ -30,148 +33,36 @@
# 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);
-}
+/* 1 if calloc is known to be compatible with GNU calloc. This
+ matters if we are not also using the calloc module, which defines
+ HAVE_CALLOC and supports the GNU API even on non-GNU platforms. */
+#if defined HAVE_CALLOC || defined __GLIBC__
+enum { HAVE_GNU_CALLOC = 1 };
+#else
+enum { HAVE_GNU_CALLOC = 0 };
+#endif
/* Allocate N bytes of memory dynamically, with error checking. */
void *
xmalloc (size_t n)
{
- 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))
+ void *p = malloc (n);
+ if (!p && 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);
+ p = realloc (p, n);
+ if (!p && n != 0)
+ xalloc_die ();
+ return p;
}
/* If P is null, allocate a block of at least *PN bytes; otherwise,
@@ -183,7 +74,7 @@ x2nrealloc (void *p, size_t *pn, size_t s)
void *
x2realloc (void *p, size_t *pn)
{
- return x2nrealloc_inline (p, pn, 1);
+ return x2nrealloc (p, pn, 1);
}
/* Allocate S bytes of zeroed memory dynamically, with error checking.
@@ -204,8 +95,11 @@ 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))
+ proper overflow checks. But omit overflow and size-zero tests if
+ HAVE_GNU_CALLOC, since GNU calloc catches overflow and never
+ returns NULL if successful. */
+ if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s))
+ || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
xalloc_die ();
return p;
}
diff --git a/lib/mempcpy.h b/lib/xstrndup.c
index 4cc7a50c46ac..7ccefd798a02 100644
--- a/lib/mempcpy.h
+++ b/lib/xstrndup.c
@@ -1,5 +1,6 @@
-/* Copy memory area and return pointer after last written byte.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Duplicate a bounded initial segment of a string, with out-of-memory
+ checking.
+ Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,24 +14,24 @@
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
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+/* Specification. */
+#include "xstrndup.h"
+
+#include <string.h>
+#include "xalloc.h"
+
+/* Return a newly allocated copy of at most N bytes of STRING.
+ In other words, return a copy of the initial segment of length N of
+ STRING. */
+char *
+xstrndup (const char *string, size_t n)
+{
+ char *s = strndup (string, n);
+ if (! s)
+ xalloc_die ();
+ return s;
+}
diff --git a/lib/strndup.h b/lib/xstrndup.h
index 318e79983931..88354cfd43a3 100644
--- a/lib/strndup.h
+++ b/lib/xstrndup.h
@@ -1,4 +1,5 @@
-/* Duplicate a size-bounded string.
+/* Duplicate a bounded initial segment of a string, with out-of-memory
+ checking.
Copyright (C) 2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -13,18 +14,11 @@
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
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <stddef.h>
-/* Return a newly allocated copy of at most N bytes of STRING. */
-extern char *strndup (const char *string, size_t n);
-
-#endif
+/* Return a newly allocated copy of at most N bytes of STRING.
+ In other words, return a copy of the initial segment of length N of
+ STRING. */
+extern char *xstrndup (const char *string, size_t n);
diff --git a/src/copyin.c b/src/copyin.c
index a1063a35c407..819e2f4ebc58 100644
--- a/src/copyin.c
+++ b/src/copyin.c
@@ -1,5 +1,6 @@
/* copyin.c - extract or list a cpio archive
- Copyright (C) 1990,1991,1992,2001,2002,2003,2004 Free Software Foundation, Inc.
+ Copyright (C) 1990,1991,1992,2001,2002,2003,2004,
+ 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +12,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#include <system.h>
@@ -27,14 +29,14 @@
#include "defer.h"
#include <rmt.h>
#ifndef FNM_PATHNAME
-#include <fnmatch.h>
+# include <fnmatch.h>
#endif
#ifndef HAVE_LCHOWN
-#define lchown chown
+# define lchown(f,u,g) 0
#endif
-static void copyin_regular_file(struct new_cpio_header* file_hdr,
+static void copyin_regular_file(struct cpio_file_stat* file_hdr,
int in_file_des);
void
@@ -47,7 +49,7 @@ warn_junk_bytes (long bytes_skipped)
static int
-query_rename(struct new_cpio_header* file_hdr, FILE *tty_in, FILE *tty_out,
+query_rename(struct cpio_file_stat* file_hdr, FILE *tty_in, FILE *tty_out,
FILE *rename_in)
{
char *str_res; /* Result for string function. */
@@ -125,7 +127,7 @@ tape_skip_padding (int in_file_des, int offset)
static void
-list_file(struct new_cpio_header* file_hdr, int in_file_des)
+list_file(struct cpio_file_stat* file_hdr, int in_file_des)
{
if (verbose_flag)
{
@@ -176,15 +178,15 @@ list_file(struct new_cpio_header* file_hdr, int in_file_des)
#endif
if (crc != file_hdr->c_chksum)
{
- error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
+ error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
file_hdr->c_name, crc, file_hdr->c_chksum);
}
}
}
static int
-try_existing_file(struct new_cpio_header* file_hdr, int in_file_des,
- int *existing_dir)
+try_existing_file (struct cpio_file_stat* file_hdr, int in_file_des,
+ int *existing_dir)
{
struct stat file_stat;
@@ -238,7 +240,7 @@ struct deferment *deferments = NULL;
go on one list, although we could optimize this if necessary. */
static void
-defer_copyin (struct new_cpio_header *file_hdr)
+defer_copyin (struct cpio_file_stat *file_hdr)
{
struct deferment *d;
d = create_deferment (file_hdr);
@@ -252,7 +254,7 @@ defer_copyin (struct new_cpio_header *file_hdr)
list and create any which are links to this file. */
static void
-create_defered_links (struct new_cpio_header *file_hdr)
+create_defered_links (struct cpio_file_stat *file_hdr)
{
struct deferment *d;
struct deferment *d_prev;
@@ -299,7 +301,7 @@ create_defered_links (struct new_cpio_header *file_hdr)
then create the other deferred links. */
static int
-create_defered_links_to_skipped (struct new_cpio_header *file_hdr,
+create_defered_links_to_skipped (struct cpio_file_stat *file_hdr,
int in_file_des)
{
struct deferment *d;
@@ -307,7 +309,6 @@ create_defered_links_to_skipped (struct new_cpio_header *file_hdr,
int ino;
int maj;
int min;
- int link_res;
if (file_hdr->c_filesize == 0)
{
/* The file doesn't have any data attached to it so we don't have
@@ -355,10 +356,7 @@ create_final_defers ()
struct deferment *d;
int link_res;
int out_file_des;
- 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));
-
+
for (d = deferments; d != NULL; d = d->next)
{
/* Debian hack: A line, which could cause an endless loop, was
@@ -385,34 +383,20 @@ create_final_defers ()
}
if (out_file_des < 0)
{
- error (0, errno, "%s", d->header.c_name);
+ open_error (d->header.c_name);
continue;
}
+ set_perms (out_file_des, &d->header);
+
if (close (out_file_des) < 0)
- error (0, errno, "%s", d->header.c_name);
-
- /* File is now copied; set attributes. */
- if (!no_chown_flag)
- if ((chown (d->header.c_name,
- set_owner_flag ? set_owner : d->header.c_uid,
- set_group_flag ? set_group : d->header.c_gid) < 0)
- && errno != EPERM)
- error (0, errno, "%s", d->header.c_name);
- /* chown may have turned off some permissions we wanted. */
- if (chmod (d->header.c_name, (int) d->header.c_mode) < 0)
- error (0, errno, "%s", d->header.c_name);
- if (retain_time_flag)
- {
- times.actime = times.modtime = d->header.c_mtime;
- if (utime (d->header.c_name, &times) < 0)
- error (0, errno, "%s", d->header.c_name);
- }
+ close_error (d->header.c_name);
+
}
}
static void
-copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
+copyin_regular_file (struct cpio_file_stat* file_hdr, int in_file_des)
{
int out_file_des; /* Output file descriptor. */
@@ -460,7 +444,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
{
tape_toss_input (in_file_des, file_hdr->c_filesize);
tape_skip_padding (in_file_des, file_hdr->c_filesize);
- return;
+ return;
}
}
else if (file_hdr->c_nlink > 1
@@ -509,7 +493,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
if (out_file_des < 0)
{
- error (0, errno, "%s", file_hdr->c_name);
+ open_error (file_hdr->c_name);
tape_toss_input (in_file_des, file_hdr->c_filesize);
tape_skip_padding (in_file_des, file_hdr->c_filesize);
return;
@@ -541,7 +525,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
if (archive_format == arf_crcascii)
{
if (crc != file_hdr->c_chksum)
- error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
+ error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
file_hdr->c_name, crc, file_hdr->c_chksum);
}
tape_skip_padding (in_file_des, file_hdr->c_filesize);
@@ -557,39 +541,19 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
write (out_file_des, "", 1);
delayed_seek_count = 0;
}
+
+ set_perms (out_file_des, file_hdr);
+
if (close (out_file_des) < 0)
- error (0, errno, "%s", file_hdr->c_name);
+ close_error (file_hdr->c_name);
if (archive_format == arf_crcascii)
{
if (crc != file_hdr->c_chksum)
- error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
+ error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
file_hdr->c_name, crc, file_hdr->c_chksum);
}
- /* File is now copied; set attributes. */
- if (!no_chown_flag)
- if ((chown (file_hdr->c_name,
- set_owner_flag ? set_owner : file_hdr->c_uid,
- set_group_flag ? set_group : file_hdr->c_gid) < 0)
- && errno != EPERM)
- error (0, errno, "%s", file_hdr->c_name);
-
- /* chown may have turned off some permissions we wanted. */
- if (chmod (file_hdr->c_name, (int) file_hdr->c_mode) < 0)
- error (0, errno, "%s", file_hdr->c_name);
-
- if (retain_time_flag)
- {
- 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));
-
- times.actime = times.modtime = file_hdr->c_mtime;
- if (utime (file_hdr->c_name, &times) < 0)
- error (0, errno, "%s", file_hdr->c_name);
- }
-
tape_skip_padding (in_file_des, file_hdr->c_filesize);
if (file_hdr->c_nlink > 1
&& (archive_format == arf_newascii || archive_format == arf_crcascii) )
@@ -603,7 +567,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
}
static void
-copyin_directory(struct new_cpio_header* file_hdr, int existing_dir)
+copyin_directory (struct cpio_file_stat *file_hdr, int existing_dir)
{
int res; /* Result of various function calls. */
#ifdef HPUX_CDF
@@ -663,43 +627,29 @@ copyin_directory(struct new_cpio_header* file_hdr, int existing_dir)
because the directory exists. If that's the case,
don't complain about it. */
struct stat file_stat;
- if ( (errno != EEXIST) ||
- (lstat (file_hdr->c_name, &file_stat) != 0) ||
- !(S_ISDIR (file_stat.st_mode) ) )
+ if (errno != EEXIST)
{
- error (0, errno, "%s", file_hdr->c_name);
+ mkdir_error (file_hdr->c_name);
+ return;
+ }
+ if (lstat (file_hdr->c_name, &file_stat))
+ {
+ stat_error (file_hdr->c_name);
+ return;
+ }
+ if (!(S_ISDIR (file_stat.st_mode)))
+ {
+ error (0, 0, _("%s is not a directory"),
+ quotearg_colon (file_hdr->c_name));
return;
}
}
- if (!no_chown_flag)
- if ((chown (file_hdr->c_name,
- set_owner_flag ? set_owner : file_hdr->c_uid,
- set_group_flag ? set_group : file_hdr->c_gid) < 0)
- && errno != EPERM)
- error (0, errno, "%s", file_hdr->c_name);
- /* chown may have turned off some permissions we wanted. */
- if (chmod (file_hdr->c_name, (int) file_hdr->c_mode) < 0)
- error (0, errno, "%s", file_hdr->c_name);
-#ifdef HPUX_CDF
- if (cdf_flag)
- /* Once we "hide" the directory with the chmod(),
- we have to refer to it using name+ instead of name. */
- file_hdr->c_name [cdf_char] = '+';
-#endif
- if (retain_time_flag)
- {
- 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));
- times.actime = times.modtime = file_hdr->c_mtime;
- if (utime (file_hdr->c_name, &times) < 0)
- error (0, errno, "%s", file_hdr->c_name);
- }
+ set_perms (-1, file_hdr);
}
static void
-copyin_device(struct new_cpio_header* file_hdr)
+copyin_device (struct cpio_file_stat* file_hdr)
{
int res; /* Result of various function calls. */
@@ -752,32 +702,27 @@ copyin_device(struct new_cpio_header* file_hdr)
}
if (res < 0)
{
- error (0, errno, "%s", file_hdr->c_name);
+ mknod_error (file_hdr->c_name);
return;
}
if (!no_chown_flag)
- if ((chown (file_hdr->c_name,
- set_owner_flag ? set_owner : file_hdr->c_uid,
- set_group_flag ? set_group : file_hdr->c_gid) < 0)
- && errno != EPERM)
- error (0, errno, "%s", file_hdr->c_name);
+ {
+ uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid;
+ gid_t gid = set_group_flag ? set_group : file_hdr->c_gid;
+ if ((chown (file_hdr->c_name, uid, gid) < 0)
+ && errno != EPERM)
+ chown_error_details (file_hdr->c_name, uid, gid);
+ }
/* chown may have turned off some permissions we wanted. */
if (chmod (file_hdr->c_name, file_hdr->c_mode) < 0)
- error (0, errno, "%s", file_hdr->c_name);
+ chmod_error_details (file_hdr->c_name, file_hdr->c_mode);
if (retain_time_flag)
- {
- 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));
-
- times.actime = times.modtime = file_hdr->c_mtime;
- if (utime (file_hdr->c_name, &times) < 0)
- error (0, errno, "%s", file_hdr->c_name);
- }
+ set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime,
+ file_hdr->c_mtime);
}
static void
-copyin_link(struct new_cpio_header *file_hdr, int in_file_des)
+copyin_link(struct cpio_file_stat *file_hdr, int in_file_des)
{
char *link_name = NULL; /* Name of hard and symbolic links. */
int res; /* Result of various function calls. */
@@ -807,23 +752,24 @@ copyin_link(struct new_cpio_header *file_hdr, int in_file_des)
}
if (res < 0)
{
- error (0, errno, "%s", file_hdr->c_name);
+ error (0, errno, _("%s: Cannot symlink to %s"),
+ quotearg_colon (link_name), quote_n (1, file_hdr->c_name));
free (link_name);
return;
}
if (!no_chown_flag)
- if ((lchown (file_hdr->c_name,
- set_owner_flag ? set_owner : file_hdr->c_uid,
- set_group_flag ? set_group : file_hdr->c_gid) < 0)
- && errno != EPERM)
- {
- error (0, errno, "%s", file_hdr->c_name);
- }
+ {
+ uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid;
+ gid_t gid = set_group_flag ? set_group : file_hdr->c_gid;
+ if ((lchown (file_hdr->c_name, uid, gid) < 0)
+ && errno != EPERM)
+ chown_error_details (file_hdr->c_name, uid, gid);
+ }
free (link_name);
}
static void
-copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
+copyin_file (struct cpio_file_stat* file_hdr, int in_file_des)
{
int existing_dir;
@@ -835,11 +781,11 @@ copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
switch (file_hdr->c_mode & CP_IFMT)
{
case CP_IFREG:
- copyin_regular_file(file_hdr, in_file_des);
+ copyin_regular_file (file_hdr, in_file_des);
break;
case CP_IFDIR:
- copyin_directory(file_hdr, existing_dir);
+ copyin_directory (file_hdr, existing_dir);
break;
case CP_IFCHR:
@@ -850,12 +796,12 @@ copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
#ifdef CP_IFIFO
case CP_IFIFO:
#endif
- copyin_device(file_hdr);
+ copyin_device (file_hdr);
break;
#ifdef CP_IFLNK
case CP_IFLNK:
- copyin_link(file_hdr, in_file_des);
+ copyin_link (file_hdr, in_file_des);
break;
#endif
@@ -876,7 +822,7 @@ static time_t current_time;
this file is a symbolic link to. */
void
-long_format (struct new_cpio_header *file_hdr, char *link_name)
+long_format (struct cpio_file_stat *file_hdr, char *link_name)
{
char mbuf[11];
char tbuf[40];
@@ -897,7 +843,7 @@ long_format (struct new_cpio_header *file_hdr, char *link_name)
}
tbuf[16] = '\0';
- printf ("%s %3u ", mbuf, file_hdr->c_nlink);
+ printf ("%s %3lu ", mbuf, file_hdr->c_nlink);
if (numeric_uid)
printf ("%-8u %-8u ", (unsigned int) file_hdr->c_uid,
@@ -908,10 +854,10 @@ long_format (struct new_cpio_header *file_hdr, char *link_name)
if ((file_hdr->c_mode & CP_IFMT) == CP_IFCHR
|| (file_hdr->c_mode & CP_IFMT) == CP_IFBLK)
- printf ("%3u, %3u ", file_hdr->c_rdev_maj,
+ printf ("%3lu, %3lu ", file_hdr->c_rdev_maj,
file_hdr->c_rdev_min);
else
- printf ("%8lu ", file_hdr->c_filesize);
+ printf ("%8"PRIuMAX" ", (uintmax_t) file_hdr->c_filesize);
printf ("%s ", tbuf + 4);
@@ -997,7 +943,7 @@ read_pattern_file ()
pattern_fp = fopen (pattern_file_name, "r");
if (pattern_fp == NULL)
- error (1, errno, "%s", pattern_file_name);
+ open_error (pattern_file_name);
while (ds_fgetstr (pattern_fp, &pattern_name, '\n') != NULL)
{
if (new_num_patterns >= max_new_patterns)
@@ -1011,7 +957,7 @@ read_pattern_file ()
++new_num_patterns;
}
if (ferror (pattern_fp) || fclose (pattern_fp) == EOF)
- error (1, errno, "%s", pattern_file_name);
+ close_error (pattern_file_name);
for (i = 0; i < num_patterns; ++i)
new_save_patterns[i] = save_patterns[i];
@@ -1020,6 +966,52 @@ read_pattern_file ()
num_patterns = new_num_patterns;
}
+
+uintmax_t
+from_ascii (char const *where, size_t digs, unsigned logbase)
+{
+ uintmax_t value = 0;
+ char const *buf = where;
+ char const *end = buf + digs;
+ int overflow = 0;
+ static char codetab[] = "0123456789ABCDEF";
+
+ for (; *buf == ' '; buf++)
+ {
+ if (buf == end)
+ return 0;
+ }
+
+ if (buf == end || *buf == 0)
+ return 0;
+ while (1)
+ {
+ unsigned d;
+
+ char *p = strchr (codetab, toupper (*buf));
+ if (!p)
+ {
+ error (0, 0, _("Malformed number %.*s"), digs, where);
+ break;
+ }
+
+ d = p - codetab;
+ if ((d >> logbase) > 1)
+ {
+ error (0, 0, _("Malformed number %.*s"), digs, where);
+ break;
+ }
+ value += d;
+ if (++buf == end || *buf == 0)
+ break;
+ overflow |= value ^ (value << logbase >> logbase);
+ value <<= logbase;
+ }
+ if (overflow)
+ error (0, 0, _("Archive value %.*s is out of range"),
+ digs, where);
+ return value;
+}
@@ -1030,8 +1022,13 @@ read_pattern_file ()
descriptor IN_DES into FILE_HDR. */
void
-read_in_header (struct new_cpio_header *file_hdr, int in_des)
+read_in_header (struct cpio_file_stat *file_hdr, int in_des)
{
+ union {
+ char str[6];
+ unsigned short num;
+ struct old_cpio_header old_header;
+ } magic;
long bytes_skipped = 0; /* Bytes of junk found before magic number. */
/* Search for a valid magic number. */
@@ -1090,52 +1087,53 @@ read_in_header (struct new_cpio_header *file_hdr, int in_des)
file_hdr->c_tar_linkname = NULL;
- tape_buffered_read ((char *) file_hdr, in_des, 6L);
+ tape_buffered_read (magic.str, in_des, 6L);
while (1)
{
if (append_flag)
last_header_start = input_bytes - io_block_size
+ (in_buff - input_buffer) - 6;
if (archive_format == arf_newascii
- && !strncmp ((char *) file_hdr, "070701", 6))
+ && !strncmp (magic.str, "070701", 6))
{
if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped);
+ file_hdr->c_magic = 070701;
read_in_new_ascii (file_hdr, in_des);
break;
}
if (archive_format == arf_crcascii
- && !strncmp ((char *) file_hdr, "070702", 6))
+ && !strncmp (magic.str, "070702", 6))
{
if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped);
-
+ file_hdr->c_magic = 070702;
read_in_new_ascii (file_hdr, in_des);
break;
}
if ( (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
- && !strncmp ((char *) file_hdr, "070707", 6))
+ && !strncmp (magic.str, "070707", 6))
{
if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped);
-
+ file_hdr->c_magic = 070707;
read_in_old_ascii (file_hdr, in_des);
break;
}
if ( (archive_format == arf_binary || archive_format == arf_hpbinary)
- && (file_hdr->c_magic == 070707
- || file_hdr->c_magic == swab_short ((unsigned short) 070707)))
+ && (magic.num == 070707
+ || magic.num == swab_short ((unsigned short) 070707)))
{
/* Having to skip 1 byte because of word alignment is normal. */
if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped);
-
- read_in_binary (file_hdr, in_des);
+ file_hdr->c_magic = 070707;
+ read_in_binary (file_hdr, &magic.old_header, in_des);
break;
}
bytes_skipped++;
- bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5);
- tape_buffered_read ((char *) file_hdr + 5, in_des, 1L);
+ memmove (magic.str, magic.str + 1, 5);
+ tape_buffered_read (magic.str, in_des, 1L);
}
}
@@ -1144,25 +1142,30 @@ read_in_header (struct new_cpio_header *file_hdr, int in_des)
already filled in. */
void
-read_in_old_ascii (struct new_cpio_header *file_hdr, int in_des)
+read_in_old_ascii (struct cpio_file_stat *file_hdr, int in_des)
{
- char ascii_header[78];
+ struct old_ascii_header ascii_header;
unsigned long dev;
- unsigned long rdev;
-
- tape_buffered_read (ascii_header, in_des, 70L);
- ascii_header[70] = '\0';
- sscanf (ascii_header,
- "%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo",
- &dev, &file_hdr->c_ino,
- &file_hdr->c_mode, &file_hdr->c_uid, &file_hdr->c_gid,
- &file_hdr->c_nlink, &rdev, &file_hdr->c_mtime,
- &file_hdr->c_namesize, &file_hdr->c_filesize);
+
+ tape_buffered_read (ascii_header.c_dev, in_des,
+ sizeof ascii_header - sizeof ascii_header.c_magic);
+ dev = FROM_OCTAL (ascii_header.c_dev);
file_hdr->c_dev_maj = major (dev);
file_hdr->c_dev_min = minor (dev);
- file_hdr->c_rdev_maj = major (rdev);
- file_hdr->c_rdev_min = minor (rdev);
+ file_hdr->c_ino = FROM_OCTAL (ascii_header.c_ino);
+ file_hdr->c_mode = FROM_OCTAL (ascii_header.c_mode);
+ file_hdr->c_uid = FROM_OCTAL (ascii_header.c_uid);
+ file_hdr->c_gid = FROM_OCTAL (ascii_header.c_gid);
+ file_hdr->c_nlink = FROM_OCTAL (ascii_header.c_nlink);
+ dev = FROM_OCTAL (ascii_header.c_rdev);
+ file_hdr->c_rdev_maj = major (dev);
+ file_hdr->c_rdev_min = minor (dev);
+
+ file_hdr->c_mtime = FROM_OCTAL (ascii_header.c_mtime);
+ file_hdr->c_namesize = FROM_OCTAL (ascii_header.c_namesize);
+ file_hdr->c_filesize = FROM_OCTAL (ascii_header.c_filesize);
+
/* Read file name from input. */
if (file_hdr->c_name != NULL)
free (file_hdr->c_name);
@@ -1204,19 +1207,27 @@ read_in_old_ascii (struct new_cpio_header *file_hdr, int in_des)
already filled in. */
void
-read_in_new_ascii (struct new_cpio_header *file_hdr, int in_des)
+read_in_new_ascii (struct cpio_file_stat *file_hdr, int in_des)
{
- char ascii_header[112];
-
- tape_buffered_read (ascii_header, in_des, 104L);
- ascii_header[104] = '\0';
- sscanf (ascii_header,
- "%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
- &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);
+ struct new_ascii_header ascii_header;
+
+ tape_buffered_read (ascii_header.c_ino, in_des,
+ sizeof ascii_header - sizeof ascii_header.c_magic);
+
+ file_hdr->c_ino = FROM_HEX (ascii_header.c_ino);
+ file_hdr->c_mode = FROM_HEX (ascii_header.c_mode);
+ file_hdr->c_uid = FROM_HEX (ascii_header.c_uid);
+ file_hdr->c_gid = FROM_HEX (ascii_header.c_gid);
+ file_hdr->c_nlink = FROM_HEX (ascii_header.c_nlink);
+ file_hdr->c_mtime = FROM_HEX (ascii_header.c_mtime);
+ file_hdr->c_filesize = FROM_HEX (ascii_header.c_filesize);
+ file_hdr->c_dev_maj = FROM_HEX (ascii_header.c_dev_maj);
+ file_hdr->c_dev_min = FROM_HEX (ascii_header.c_dev_min);
+ file_hdr->c_rdev_maj = FROM_HEX (ascii_header.c_rdev_maj);
+ file_hdr->c_rdev_min = FROM_HEX (ascii_header.c_rdev_min);
+ file_hdr->c_namesize = FROM_HEX (ascii_header.c_namesize);
+ file_hdr->c_chksum = FROM_HEX (ascii_header.c_chksum);
+
/* Read file name from input. */
if (file_hdr->c_name != NULL)
free (file_hdr->c_name);
@@ -1234,15 +1245,14 @@ read_in_new_ascii (struct new_cpio_header *file_hdr, int in_des)
number, device, and inode number), which are already filled in. */
void
-read_in_binary (struct new_cpio_header *file_hdr, int in_des)
+read_in_binary (struct cpio_file_stat *file_hdr,
+ struct old_cpio_header *short_hdr,
+ int in_des)
{
- struct old_cpio_header short_hdr;
+ file_hdr->c_magic = short_hdr->c_magic;
- /* Copy the data into the short header, then later transfer
- it into the argument long header. */
- short_hdr.c_dev = ((struct old_cpio_header *) file_hdr)->c_dev;
- short_hdr.c_ino = ((struct old_cpio_header *) file_hdr)->c_ino;
- tape_buffered_read (((char *) &short_hdr) + 6, in_des, 20L);
+ tape_buffered_read (((char *) short_hdr) + 6, in_des,
+ sizeof *short_hdr - 6 /* = 20 */);
/* If the magic number is byte swapped, fix the header. */
if (file_hdr->c_magic == swab_short ((unsigned short) 070707))
@@ -1259,21 +1269,21 @@ read_in_binary (struct new_cpio_header *file_hdr, int in_des)
swab_array ((char *) &short_hdr, 13);
}
- file_hdr->c_dev_maj = major (short_hdr.c_dev);
- file_hdr->c_dev_min = minor (short_hdr.c_dev);
- file_hdr->c_ino = short_hdr.c_ino;
- file_hdr->c_mode = short_hdr.c_mode;
- file_hdr->c_uid = short_hdr.c_uid;
- file_hdr->c_gid = short_hdr.c_gid;
- file_hdr->c_nlink = short_hdr.c_nlink;
- file_hdr->c_rdev_maj = major (short_hdr.c_rdev);
- file_hdr->c_rdev_min = minor (short_hdr.c_rdev);
- file_hdr->c_mtime = (unsigned long) short_hdr.c_mtimes[0] << 16
- | short_hdr.c_mtimes[1];
-
- file_hdr->c_namesize = short_hdr.c_namesize;
- file_hdr->c_filesize = (unsigned long) short_hdr.c_filesizes[0] << 16
- | short_hdr.c_filesizes[1];
+ file_hdr->c_dev_maj = major (short_hdr->c_dev);
+ file_hdr->c_dev_min = minor (short_hdr->c_dev);
+ file_hdr->c_ino = short_hdr->c_ino;
+ file_hdr->c_mode = short_hdr->c_mode;
+ file_hdr->c_uid = short_hdr->c_uid;
+ file_hdr->c_gid = short_hdr->c_gid;
+ file_hdr->c_nlink = short_hdr->c_nlink;
+ file_hdr->c_rdev_maj = major (short_hdr->c_rdev);
+ file_hdr->c_rdev_min = minor (short_hdr->c_rdev);
+ file_hdr->c_mtime = (unsigned long) short_hdr->c_mtimes[0] << 16
+ | short_hdr->c_mtimes[1];
+
+ file_hdr->c_namesize = short_hdr->c_namesize;
+ file_hdr->c_filesize = (unsigned long) short_hdr->c_filesizes[0] << 16
+ | short_hdr->c_filesizes[1];
/* Read file name from input. */
if (file_hdr->c_name != NULL)
@@ -1342,15 +1352,18 @@ void
process_copy_in ()
{
char done = false; /* True if trailer reached. */
- FILE *tty_in; /* Interactive file for rename option. */
- FILE *tty_out; /* Interactive file for rename option. */
- FILE *rename_in; /* Batch file for rename option. */
+ FILE *tty_in = NULL; /* Interactive file for rename option. */
+ FILE *tty_out = NULL; /* Interactive file for rename option. */
+ FILE *rename_in = NULL; /* Batch file for rename option. */
struct stat file_stat; /* Output file stat record. */
- struct new_cpio_header file_hdr; /* Output header information. */
+ struct cpio_file_stat file_hdr; /* Output header information. */
int in_file_des; /* Input file descriptor. */
char skip_file; /* Flag for use with patterns. */
int i; /* Loop index variable. */
+ umask (0); /* Reset umask to preserve modes of
+ created files */
+
/* Initialize the copy in. */
if (pattern_file_name)
{
@@ -1418,7 +1431,7 @@ process_copy_in ()
#ifdef DEBUG_CPIO
if (debug_flag)
{
- struct new_cpio_header *h;
+ struct cpio_file_stat *h;
h = &file_hdr;
fprintf (stderr,
"magic = 0%o, ino = %d, mode = 0%o, uid = %d, gid = %d\n",
@@ -1437,37 +1450,15 @@ process_copy_in ()
}
#endif
/* Is this the header for the TRAILER file? */
- if (strcmp ("TRAILER!!!", file_hdr.c_name) == 0)
+ if (strcmp (CPIO_TRAILER_NAME, file_hdr.c_name) == 0)
{
done = true;
break;
}
- /* Do we have to ignore absolute paths, and if so, does the filename
- have an absolute path? */
- if (no_abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0] == '/')
- {
- char *p;
-
- p = file_hdr.c_name;
- while (*p == '/')
- ++p;
- if (*p == '\0')
- {
- strcpy (file_hdr.c_name, ".");
- }
- else
- {
- /* Debian hack: file_hrd.c_name is sometimes set to
- point to static memory by code in tar.c. This
- causes a segfault. Therefore, memmove is used
- instead of freeing and reallocating. (Reported by
- Horst Knobloch.) This bug has been reported to
- "bug-gnu-utils@prep.ai.mit.edu". (99/1/6) -BEM */
- (void)memmove (file_hdr.c_name, p, (size_t)(strlen (p) + 1));
- }
- }
-
+ cpio_safer_name_suffix (file_hdr.c_name, false, !no_abs_paths_flag,
+ false);
+
/* Does the file name match one of the given patterns? */
if (num_patterns <= 0)
skip_file = false;
@@ -1530,7 +1521,7 @@ process_copy_in ()
tape_skip_padding (in_file_des, file_hdr.c_filesize);
if (crc != file_hdr.c_chksum)
{
- error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
+ error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
file_hdr.c_name, crc, file_hdr.c_chksum);
}
/* Debian hack: -v and -V now work with --only-verify-crc.
diff --git a/src/copyout.c b/src/copyout.c
index 23da993de584..0ab294ec64b0 100644
--- a/src/copyout.c
+++ b/src/copyout.c
@@ -1,5 +1,6 @@
/* copyout.c - create a cpio archive
- Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004,
+ 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +12,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#include <system.h>
@@ -26,14 +28,15 @@
#include "extern.h"
#include "defer.h"
#include <rmt.h>
+#include <paxlib.h>
/* Read FILE_SIZE bytes of FILE_NAME from IN_FILE_DES and
compute and return a checksum for them. */
-static unsigned long
+static unsigned int
read_for_checksum (int in_file_des, int file_size, char *file_name)
{
- unsigned long crc;
+ unsigned int crc;
char buf[BUFSIZ];
int bytes_left;
int bytes_read;
@@ -65,13 +68,8 @@ read_for_checksum (int in_file_des, int file_size, char *file_name)
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_to_file (io_block_size - output_size, out_file_des,
+ tape_buffered_write);
}
/* Write NULs on OUT_FILE_DES to move from OFFSET (the current location)
@@ -80,7 +78,7 @@ tape_clear_rest_of_block (int out_file_des)
static void
tape_pad_output (int out_file_des, int offset)
{
- int pad;
+ size_t pad;
if (archive_format == arf_newascii || archive_format == arf_crcascii)
pad = (4 - (offset % 4)) % 4;
@@ -92,7 +90,7 @@ tape_pad_output (int out_file_des, int offset)
pad = 0;
if (pad != 0)
- tape_buffered_write (zeros_512, out_file_des, pad);
+ write_nuls_to_file (pad, out_file_des, tape_buffered_write);
}
@@ -109,7 +107,7 @@ struct deferment *deferouts = NULL;
already been defered. */
static int
-count_defered_links_to_dev_ino (struct new_cpio_header *file_hdr)
+count_defered_links_to_dev_ino (struct cpio_file_stat *file_hdr)
{
struct deferment *d;
int ino;
@@ -133,7 +131,7 @@ count_defered_links_to_dev_ino (struct new_cpio_header *file_hdr)
we already seen and defered all of the other links? */
static int
-last_link (struct new_cpio_header *file_hdr)
+last_link (struct cpio_file_stat *file_hdr)
{
int other_files_sofar;
@@ -150,7 +148,7 @@ last_link (struct new_cpio_header *file_hdr)
list. */
static void
-add_link_defer (struct new_cpio_header *file_hdr)
+add_link_defer (struct cpio_file_stat *file_hdr)
{
struct deferment *d;
d = create_deferment (file_hdr);
@@ -159,13 +157,13 @@ add_link_defer (struct new_cpio_header *file_hdr)
}
/* 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
+ multiply linked. We have already seen and deferred 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)
+writeout_other_defers (struct cpio_file_stat *file_hdr, int out_des)
{
struct deferment *d;
struct deferment *d_prev;
@@ -207,13 +205,10 @@ writeout_other_defers (struct new_cpio_header *file_hdr, int out_des)
for writeout_final_defers() to call. */
static void
-writeout_defered_file (struct new_cpio_header *header, int out_file_des)
+writeout_defered_file (struct cpio_file_stat *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));
+ struct cpio_file_stat file_hdr;
file_hdr = *header;
@@ -222,7 +217,7 @@ writeout_defered_file (struct new_cpio_header *header, int out_file_des)
O_RDONLY | O_BINARY, 0);
if (in_file_des < 0)
{
- error (0, errno, "%s", header->c_name);
+ open_error (header->c_name);
return;
}
@@ -231,8 +226,10 @@ writeout_defered_file (struct new_cpio_header *header, int out_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);
+ if (write_out_header (&file_hdr, out_file_des))
+ return;
+ 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)
@@ -241,21 +238,11 @@ writeout_defered_file (struct new_cpio_header *header, int out_file_des)
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;
+ set_file_times (in_file_des, file_hdr.c_name, file_hdr.c_mtime,
+ file_hdr.c_mtime);
+ if (close (in_file_des) < 0)
+ close_error (header->c_name);
}
/* When writing newc and crc format archives we defer multiply linked
@@ -279,7 +266,7 @@ writeout_final_defers (int out_des)
}
else
{
- struct new_cpio_header file_hdr;
+ struct cpio_file_stat file_hdr;
file_hdr = d->header;
file_hdr.c_filesize = 0;
write_out_header (&file_hdr, out_des);
@@ -288,156 +275,319 @@ writeout_final_defers (int out_des)
}
}
-
-/* Write out header FILE_HDR, including the file name, to file
- descriptor OUT_DES. */
+/* FIXME: to_ascii could be used instead of to_oct() and to_octal() from tar,
+ so it should be moved to paxutils too.
+ Allowed values for logbase are: 1 (binary), 2, 3 (octal), 4 (hex) */
+int
+to_ascii (char *where, uintmax_t v, size_t digits, unsigned logbase)
+{
+ static char codetab[] = "0123456789ABCDEF";
+ int i = digits;
+
+ do
+ {
+ where[--i] = codetab[(v & ((1 << logbase) - 1))];
+ v >>= logbase;
+ }
+ while (i);
+
+ return v != 0;
+}
+
+static void
+field_width_error (const char *filename, const char *fieldname)
+{
+ error (0, 0, _("%s: field width not sufficient for storing %s"),
+ filename, fieldname);
+}
+
+static void
+field_width_warning (const char *filename, const char *fieldname)
+{
+ if (warn_option & CPIO_WARN_TRUNCATE)
+ error (0, 0, _("%s: truncating %s"), filename, fieldname);
+}
void
-write_out_header (struct new_cpio_header *file_hdr, int out_des)
+to_ascii_or_warn (char *where, uintmax_t n, size_t digits,
+ unsigned logbase,
+ const char *filename, const char *fieldname)
{
- if (archive_format == arf_newascii || archive_format == arf_crcascii)
+ if (to_ascii (where, n, digits, logbase))
+ field_width_warning (filename, fieldname);
+}
+
+int
+to_ascii_or_error (char *where, uintmax_t n, size_t digits,
+ unsigned logbase,
+ const char *filename, const char *fieldname)
+{
+ if (to_ascii (where, n, digits, logbase))
{
- 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);
+ field_width_error (filename, fieldname);
+ return 1;
}
- else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
- {
- char ascii_header[78];
- dev_t dev;
- dev_t rdev;
+ return 0;
+}
- 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:
+
+int
+write_out_new_ascii_header (const char *magic_string,
+ struct cpio_file_stat *file_hdr, int out_des)
+{
+ char ascii_header[110];
+ char *p;
+
+ p = stpcpy (ascii_header, magic_string);
+ to_ascii_or_warn (p, file_hdr->c_ino, 8, LG_16,
+ file_hdr->c_name, _("inode number"));
+ p += 8;
+ to_ascii_or_warn (p, file_hdr->c_mode, 8, LG_16, file_hdr->c_name,
+ _("file mode"));
+ p += 8;
+ to_ascii_or_warn (p, file_hdr->c_uid, 8, LG_16, file_hdr->c_name,
+ _("uid"));
+ p += 8;
+ to_ascii_or_warn (p, file_hdr->c_gid, 8, LG_16, file_hdr->c_name,
+ _("gid"));
+ p += 8;
+ to_ascii_or_warn (p, file_hdr->c_nlink, 8, LG_16, file_hdr->c_name,
+ _("number of links"));
+ p += 8;
+ to_ascii_or_warn (p, file_hdr->c_mtime, 8, LG_16, file_hdr->c_name,
+ _("modification time"));
+ p += 8;
+ if (to_ascii_or_error (p, file_hdr->c_filesize, 8, LG_16, file_hdr->c_name,
+ _("file size")))
+ return 1;
+ p += 8;
+ if (to_ascii_or_error (p, file_hdr->c_dev_maj, 8, LG_16, file_hdr->c_name,
+ _("device major number")))
+ return 1;
+ p += 8;
+ if (to_ascii_or_error (p, file_hdr->c_dev_min, 8, LG_16, file_hdr->c_name,
+ _("device minor number")))
+ return 1;
+ p += 8;
+ if (to_ascii_or_error (p, file_hdr->c_rdev_maj, 8, LG_16, file_hdr->c_name,
+ _("rdev major")))
+ return 1;
+ p += 8;
+ if (to_ascii_or_error (p, file_hdr->c_rdev_min, 8, LG_16, file_hdr->c_name,
+ _("rdev minor")))
+ return 1;
+ p += 8;
+ if (to_ascii_or_error (p, file_hdr->c_namesize, 8, LG_16, file_hdr->c_name,
+ _("name size")))
+ return 1;
+ p += 8;
+ to_ascii (p, file_hdr->c_chksum & 0xffffffff, 8, LG_16);
+
+ tape_buffered_write (ascii_header, out_des, sizeof ascii_header);
+
+ /* 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 + sizeof ascii_header);
+ return 0;
+}
+
+int
+write_out_old_ascii_header (dev_t dev, dev_t rdev,
+ struct cpio_file_stat *file_hdr, int out_des)
+{
+ char ascii_header[76];
+ char *p = ascii_header;
+
+ to_ascii (p, file_hdr->c_magic, 6, LG_8);
+ p += 6;
+ to_ascii_or_warn (p, dev, 6, LG_8, file_hdr->c_name, _("device number"));
+ p += 6;
+ to_ascii_or_warn (p, file_hdr->c_ino, 6, LG_8, file_hdr->c_name,
+ _("inode number"));
+ p += 6;
+ to_ascii_or_warn (p, file_hdr->c_mode, 6, LG_8, file_hdr->c_name,
+ _("file mode"));
+ p += 6;
+ to_ascii_or_warn (p, file_hdr->c_uid, 6, LG_8, file_hdr->c_name, _("uid"));
+ p += 6;
+ to_ascii_or_warn (p, file_hdr->c_gid, 6, LG_8, file_hdr->c_name, _("gid"));
+ p += 6;
+ to_ascii_or_warn (p, file_hdr->c_nlink, 6, LG_8, file_hdr->c_name,
+ _("number of links"));
+ p += 6;
+ to_ascii_or_warn (p, rdev, 6, LG_8, file_hdr->c_name, _("rdev"));
+ p += 6;
+ to_ascii_or_warn (p, file_hdr->c_mtime, 11, LG_8, file_hdr->c_name,
+ _("modification time"));
+ p += 11;
+ if (to_ascii_or_error (p, file_hdr->c_namesize, 6, LG_8, file_hdr->c_name,
+ _("name size")))
+ return 1;
+ p += 6;
+ if (to_ascii_or_error (p, file_hdr->c_filesize, 11, LG_8, file_hdr->c_name,
+ _("file size")))
+ return 1;
+
+ tape_buffered_write (ascii_header, out_des, sizeof ascii_header);
+
+ /* Write file name to output. */
+ tape_buffered_write (file_hdr->c_name, out_des, file_hdr->c_namesize);
+ return 0;
+}
+
+void
+hp_compute_dev (struct cpio_file_stat *file_hdr, dev_t *pdev, dev_t *prdev)
+{
+ /* 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:
+ case CP_IFSOCK:
#endif
#ifdef CP_IFIFO
- case 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);
+ file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
+ file_hdr->c_rdev_min);
+ *pdev = *prdev = makedev (0, 1);
+ break;
+
+ default:
+ *pdev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
+ *prdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
+ break;
}
- else if (archive_format == arf_tar || archive_format == arf_ustar)
+}
+
+int
+write_out_binary_header (dev_t rdev,
+ struct cpio_file_stat *file_hdr, int out_des)
+{
+ 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;
+ if (short_hdr.c_ino != file_hdr->c_ino)
+ field_width_warning (file_hdr->c_name, _("inode number"));
+
+ short_hdr.c_mode = file_hdr->c_mode & 0xFFFF;
+ if (short_hdr.c_mode != file_hdr->c_mode)
+ field_width_warning (file_hdr->c_name, _("file mode"));
+
+ short_hdr.c_uid = file_hdr->c_uid & 0xFFFF;
+ if (short_hdr.c_uid != file_hdr->c_uid)
+ field_width_warning (file_hdr->c_name, _("uid"));
+
+ short_hdr.c_gid = file_hdr->c_gid & 0xFFFF;
+ if (short_hdr.c_gid != file_hdr->c_gid)
+ field_width_warning (file_hdr->c_name, _("gid"));
+
+ short_hdr.c_nlink = file_hdr->c_nlink & 0xFFFF;
+ if (short_hdr.c_nlink != file_hdr->c_nlink)
+ field_width_warning (file_hdr->c_name, _("number of links"));
+
+ short_hdr.c_rdev = rdev;
+ 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;
+ if (short_hdr.c_namesize != file_hdr->c_namesize)
{
- write_out_tar_header (file_hdr, out_des);
+ field_width_error (file_hdr->c_name, _("name size"));
+ return 1;
}
- else
+
+ short_hdr.c_filesizes[0] = file_hdr->c_filesize >> 16;
+ short_hdr.c_filesizes[1] = file_hdr->c_filesize & 0xFFFF;
+
+ if (((off_t)short_hdr.c_filesizes[0] << 16) + short_hdr.c_filesizes[1]
+ != file_hdr->c_filesize)
{
- struct old_cpio_header short_hdr;
+ field_width_error (file_hdr->c_name, _("file size"));
+ return 1;
+ }
+
+ /* Output the file header. */
+ tape_buffered_write ((char *) &short_hdr, out_des, 26);
- short_hdr.c_magic = 070707;
- short_hdr.c_dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
+ /* Write file name to output. */
+ tape_buffered_write (file_hdr->c_name, out_des, file_hdr->c_namesize);
- if ((warn_option & CPIO_WARN_TRUNCATE) && (file_hdr->c_ino >> 16) != 0)
- error (0, 0, _("%s: truncating inode number"), file_hdr->c_name);
+ tape_pad_output (out_des, file_hdr->c_namesize + 26);
+ return 0;
+}
- 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
+
+/* Write out header FILE_HDR, including the file name, to file
+ descriptor OUT_DES. */
+
+int
+write_out_header (struct cpio_file_stat *file_hdr, int out_des)
+{
+ dev_t dev;
+ dev_t rdev;
+
+ switch (archive_format)
+ {
+ case arf_newascii:
+ return write_out_new_ascii_header ("070701", file_hdr, out_des);
+
+ case arf_crcascii:
+ return write_out_new_ascii_header ("070702", file_hdr, out_des);
+
+ case arf_oldascii:
+ return write_out_old_ascii_header (makedev (file_hdr->c_dev_maj,
+ file_hdr->c_dev_min),
+ makedev (file_hdr->c_rdev_maj,
+ file_hdr->c_rdev_min),
+ file_hdr, out_des);
+
+ case arf_hpoldascii:
+ hp_compute_dev (file_hdr, &dev, &rdev);
+ return write_out_old_ascii_header (dev, rdev, file_hdr, out_des);
+
+ case arf_tar:
+ case arf_ustar:
+ if (is_tar_filename_too_long (file_hdr->c_name))
{
- 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;
- }
+ error (0, 0, _("%s: file name too long"), file_hdr->c_name);
+ return 1;
}
- short_hdr.c_mtimes[0] = file_hdr->c_mtime >> 16;
- short_hdr.c_mtimes[1] = file_hdr->c_mtime & 0xFFFF;
+ write_out_tar_header (file_hdr, out_des); /* FIXME: No error checking */
+ return 0;
- short_hdr.c_namesize = file_hdr->c_namesize & 0xFFFF;
+ case arf_binary:
+ return write_out_binary_header (makedev (file_hdr->c_rdev_maj,
+ file_hdr->c_rdev_min),
+ file_hdr, out_des);
- short_hdr.c_filesizes[0] = file_hdr->c_filesize >> 16;
- short_hdr.c_filesizes[1] = file_hdr->c_filesize & 0xFFFF;
+ case arf_hpbinary:
+ hp_compute_dev (file_hdr, &dev, &rdev);
+ /* FIXME: dev ignored. Should it be? */
+ return write_out_binary_header (rdev, file_hdr, out_des);
- /* 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);
+ default:
+ abort ();
}
}
+static void
+assign_string (char **pvar, char *value)
+{
+ char *p = xrealloc (*pvar, strlen (value) + 1);
+ strcpy (p, value);
+ *pvar = p;
+}
+
/* 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. */
@@ -447,17 +597,14 @@ 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. */
+ struct cpio_file_stat file_hdr; /* Output header information. */
int in_file_des; /* Source file descriptor. */
int out_file_des; /* Output file descriptor. */
- char *p;
+ char *orig_file_name = NULL;
/* 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. */
@@ -497,55 +644,11 @@ process_copy_out ()
/* Process next file. */
if ((*xstat) (input_name.ds_string, &file_stat) < 0)
- error (0, errno, "%s", input_name.ds_string);
+ stat_error (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;
+ stat_to_cpio (&file_hdr, &file_stat);
if (archive_format == arf_tar || archive_format == arf_ustar)
{
@@ -562,17 +665,12 @@ process_copy_out ()
}
}
- /* Strip leading `./' from the filename. */
- p = input_name.ds_string;
- while (*p == '.' && *(p + 1) == '/')
- {
- ++p;
- while (*p == '/')
- ++p;
- }
+ assign_string (&orig_file_name, input_name.ds_string);
+ cpio_safer_name_suffix (input_name.ds_string, false,
+ !no_abs_paths_flag, true);
#ifndef HPUX_CDF
- file_hdr.c_name = p;
- file_hdr.c_namesize = strlen (p) + 1;
+ file_hdr.c_name = input_name.ds_string;
+ file_hdr.c_namesize = strlen (input_name.ds_string) + 1;
#else
if ( (archive_format != arf_tar) && (archive_format != arf_ustar) )
{
@@ -581,7 +679,7 @@ process_copy_out ()
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_name = add_cdf_double_slashes (input_name.ds_string);
file_hdr.c_namesize = strlen (file_hdr.c_name) + 1;
}
else
@@ -589,18 +687,11 @@ process_copy_out ()
/* 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;
+ file_hdr.c_name = input_name.ds_string;
+ file_hdr.c_namesize = strlen (input_name.ds_string) + 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)
{
@@ -613,7 +704,8 @@ process_copy_out ()
file_hdr.c_dev_min)))
{
file_hdr.c_tar_linkname = otherfile;
- write_out_header (&file_hdr, out_file_des);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
break;
}
}
@@ -630,50 +722,45 @@ process_copy_out ()
break;
}
}
- in_file_des = open (input_name.ds_string,
+ in_file_des = open (orig_file_name,
O_RDONLY | O_BINARY, 0);
if (in_file_des < 0)
{
- error (0, errno, "%s", input_name.ds_string);
+ open_error (orig_file_name);
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,
+ orig_file_name);
+
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
+ copy_files_disk_to_tape (in_file_des,
+ out_file_des, file_hdr.c_filesize,
+ orig_file_name);
+ warn_if_file_changed(orig_file_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,
+ add_inode (file_hdr.c_ino, orig_file_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);
- }
+ set_file_times (in_file_des,
+ orig_file_name,
+ file_stat.st_atime, file_stat.st_mtime);
+ if (close (in_file_des) < 0)
+ close_error (orig_file_name);
break;
case CP_IFDIR:
file_hdr.c_filesize = 0;
- write_out_header (&file_hdr, out_file_des);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
break;
case CP_IFCHR:
@@ -687,7 +774,7 @@ process_copy_out ()
if (archive_format == arf_tar)
{
error (0, 0, _("%s not dumped: not a regular file"),
- file_hdr.c_name);
+ orig_file_name);
continue;
}
else if (archive_format == arf_ustar)
@@ -702,14 +789,16 @@ process_copy_out ()
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);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
break;
}
- add_inode (file_hdr.c_ino, file_hdr.c_name,
+ add_inode (file_hdr.c_ino, orig_file_name,
file_hdr.c_dev_maj, file_hdr.c_dev_min);
}
file_hdr.c_filesize = 0;
- write_out_header (&file_hdr, out_file_des);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
break;
#ifdef CP_IFLNK
@@ -718,14 +807,18 @@ process_copy_out ()
char *link_name = (char *) xmalloc (file_stat.st_size + 1);
int link_size;
- link_size = readlink (input_name.ds_string, link_name,
+ link_size = readlink (orig_file_name, link_name,
file_stat.st_size);
if (link_size < 0)
{
- error (0, errno, "%s", input_name.ds_string);
+ readlink_warn (orig_file_name);
free (link_name);
continue;
}
+ link_name[link_size] = 0;
+ cpio_safer_name_suffix (link_name, false,
+ !no_abs_paths_flag, true);
+ link_size = strlen (link_name);
file_hdr.c_filesize = link_size;
if (archive_format == arf_tar || archive_format == arf_ustar)
{
@@ -738,12 +831,14 @@ process_copy_out ()
{
link_name[link_size] = '\0';
file_hdr.c_tar_linkname = link_name;
- write_out_header (&file_hdr, out_file_des);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
}
}
else
{
- write_out_header (&file_hdr, out_file_des);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
tape_buffered_write (link_name, out_file_des, link_size);
tape_pad_output (out_file_des, link_size);
}
@@ -753,16 +848,18 @@ process_copy_out ()
#endif
default:
- error (0, 0, _("%s: unknown file type"), input_name.ds_string);
+ error (0, 0, _("%s: unknown file type"), orig_file_name);
}
-
+
if (verbose_flag)
- fprintf (stderr, "%s\n", input_name.ds_string);
+ fprintf (stderr, "%s\n", orig_file_name);
if (dot_flag)
fputc ('.', stderr);
}
}
+ free (orig_file_name);
+
writeout_final_defers(out_file_des);
/* The collection is complete; append the trailer. */
file_hdr.c_ino = 0;
@@ -779,14 +876,11 @@ process_copy_out ()
file_hdr.c_filesize = 0;
file_hdr.c_namesize = 11;
- file_hdr.c_name = "TRAILER!!!";
+ file_hdr.c_name = CPIO_TRAILER_NAME;
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);
- }
+ write_nuls_to_file (1024, out_file_des, tape_buffered_write);
/* Fill up the output block. */
tape_clear_rest_of_block (out_file_des);
diff --git a/src/copypass.c b/src/copypass.c
index db6f327159d8..78576c6231cd 100644
--- a/src/copypass.c
+++ b/src/copypass.c
@@ -1,5 +1,6 @@
/* copypass.c - cpio copy pass sub-function.
- Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004,
+ 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +12,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#include <system.h>
@@ -24,11 +26,23 @@
#include "cpiohdr.h"
#include "dstring.h"
#include "extern.h"
+#include "paxlib.h"
#ifndef HAVE_LCHOWN
-#define lchown chown
+# define lchown chown
#endif
+
+/* A wrapper around set_perms using another set of arguments */
+static void
+set_copypass_perms (int fd, const char *name, struct stat *st)
+{
+ struct cpio_file_stat header;
+ header.c_name = name;
+ stat_to_cpio (&header, st);
+ set_perms (fd, &header);
+}
+
/* Copy files listed on the standard input into directory `directory_name'.
If `link_flag', link instead of copying. */
@@ -40,7 +54,6 @@ process_copy_pass ()
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. */
@@ -51,6 +64,9 @@ process_copy_pass ()
int cdf_char;
#endif
+ umask (0); /* Reset umask to preserve modes of
+ created files */
+
/* Initialize the copy pass. */
dirname_len = strlen (directory_name);
ds_init (&input_name, 128);
@@ -58,8 +74,6 @@ process_copy_pass ()
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)
@@ -82,7 +96,7 @@ process_copy_pass ()
if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
{
- error (0, errno, "%s", input_name.ds_string);
+ stat_error (input_name.ds_string);
continue;
}
@@ -150,7 +164,7 @@ process_copy_pass ()
O_RDONLY | O_BINARY, 0);
if (in_file_des < 0)
{
- error (0, errno, "%s", input_name.ds_string);
+ open_error (input_name.ds_string);
continue;
}
out_file_des = open (output_name.ds_string,
@@ -163,7 +177,7 @@ process_copy_pass ()
}
if (out_file_des < 0)
{
- error (0, errno, "%s", output_name.ds_string);
+ open_error (output_name.ds_string);
close (in_file_des);
continue;
}
@@ -179,43 +193,28 @@ process_copy_pass ()
write (out_file_des, "", 1);
delayed_seek_count = 0;
}
+
+ set_copypass_perms (out_file_des,
+ output_name.ds_string, &in_file_stat);
+
+ if (reset_time_flag)
+ {
+ set_file_times (in_file_des,
+ input_name.ds_string,
+ in_file_stat.st_atime,
+ in_file_stat.st_mtime);
+ set_file_times (out_file_des,
+ output_name.ds_string,
+ in_file_stat.st_atime,
+ in_file_stat.st_mtime);
+ }
+
if (close (in_file_des) < 0)
- error (0, errno, "%s", input_name.ds_string);
+ close_error (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);
- }
+ close_error (output_name.ds_string);
+
warn_if_file_changed(input_name.ds_string, in_file_stat.st_size,
in_file_stat.st_mtime);
}
@@ -261,31 +260,11 @@ process_copy_pass ()
(lstat (output_name.ds_string, &out_file_stat) != 0) ||
!(S_ISDIR (out_file_stat.st_mode) ) )
{
- error (0, errno, "%s", output_name.ds_string);
+ stat_error (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);
- }
+ set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
}
else if (S_ISCHR (in_file_stat.st_mode) ||
S_ISBLK (in_file_stat.st_mode) ||
@@ -321,24 +300,10 @@ process_copy_pass ()
}
if (res < 0)
{
- error (0, errno, "%s", output_name.ds_string);
+ mknod_error (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);
- }
+ set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
}
}
@@ -353,7 +318,7 @@ process_copy_pass ()
in_file_stat.st_size);
if (link_size < 0)
{
- error (0, errno, "%s", input_name.ds_string);
+ readlink_error (input_name.ds_string);
free (link_name);
continue;
}
@@ -369,18 +334,20 @@ process_copy_pass ()
}
if (res < 0)
{
- error (0, errno, "%s", output_name.ds_string);
+ symlink_error (output_name.ds_string, link_name);
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);
+ {
+ uid_t uid = set_owner_flag ? set_owner : in_file_stat.st_uid;
+ gid_t gid = set_group_flag ? set_group : in_file_stat.st_gid;
+ if ((lchown (output_name.ds_string, uid, gid) < 0)
+ && errno != EPERM)
+ chown_error_details (output_name.ds_string, uid, gid);
+ }
free (link_name);
}
#endif
diff --git a/src/cpio.h b/src/cpio.h
index 3861ab0d668f..34d1cf10e408 100644
--- a/src/cpio.h
+++ b/src/cpio.h
@@ -1,5 +1,5 @@
/* Extended cpio format from POSIX.1.
- Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright (C) 1992, 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#ifndef _CPIO_H
@@ -25,6 +26,8 @@
and variable length file data.
A header for a filename "TRAILER!!!" indicates the end of the archive. */
+#define CPIO_TRAILER_NAME "TRAILER!!!"
+
/* All the fields in the header are ISO 646 (approximately ASCII) strings
of octal numbers, left padded, not NUL terminated.
diff --git a/src/cpiohdr.h b/src/cpiohdr.h
index c3943b464e16..503563f84406 100644
--- a/src/cpiohdr.h
+++ b/src/cpiohdr.h
@@ -1,5 +1,5 @@
/* Extended cpio header from POSIX.1.
- Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright (C) 1992, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#ifndef _CPIOHDR_H
@@ -34,9 +35,21 @@ struct old_cpio_header
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;
+};
+
+struct old_ascii_header
+{
+ char c_magic[6];
+ char c_dev[6];
+ char c_ino[6];
+ char c_mode[6];
+ char c_uid[6];
+ char c_gid[6];
+ char c_nlink[6];
+ char c_rdev[6];
+ char c_mtime[11];
+ char c_namesize[6];
+ char c_filesize[11];
};
/* "New" portable format and CRC format:
@@ -47,44 +60,47 @@ struct old_cpio_header
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.
+ 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_ascii_header
+{
+ char c_magic[6]; /* "070701" for "new" portable format
+ "070702" for CRC format */
+ char c_ino[8];
+ char c_mode[8];
+ char c_uid[8];
+ char c_gid[8];
+ char c_nlink[8];
+ char c_mtime[8];
+ char c_filesize[8]; /* must be 0 for FIFOs and directories */
+ char c_dev_maj[8];
+ char c_dev_min[8];
+ char c_rdev_maj[8]; /* only valid for chr and blk special files */
+ char c_rdev_min[8]; /* only valid for chr and blk special files */
+ char c_namesize[8]; /* count includes terminating NUL in pathname */
+ char c_chksum[8]; /* 0 for "new" portable format; for CRC format
+ the sum of all the bytes in the file */
+};
-struct new_cpio_header
+struct cpio_file_stat /* Internal representation of a 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;
+ ino_t c_ino;
+ mode_t c_mode;
+ uid_t c_uid;
+ gid_t c_gid;
+ size_t c_nlink;
+ time_t c_mtime;
+ off_t c_filesize;
long c_dev_maj;
long c_dev_min;
long c_rdev_maj;
long c_rdev_min;
- unsigned long c_namesize;
+ size_t c_namesize;
unsigned long c_chksum;
char *c_name;
char *c_tar_linkname;
};
+
#endif /* cpiohdr.h */
diff --git a/src/defer.c b/src/defer.c
index cb6fb40c1135..83e15dd7c3d2 100644
--- a/src/defer.c
+++ b/src/defer.c
@@ -1,5 +1,5 @@
/* defer.c - handle "defered" links in newc and crc archives
- Copyright (C) 1993,2003,2004 Free Software Foundation, Inc.
+ Copyright (C) 1993, 2003, 2004, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#include <system.h>
@@ -24,7 +25,7 @@
#include "defer.h"
struct deferment *
-create_deferment (struct new_cpio_header *file_hdr)
+create_deferment (struct cpio_file_stat *file_hdr)
{
struct deferment *d;
d = (struct deferment *) xmalloc (sizeof (struct deferment) );
diff --git a/src/defer.h b/src/defer.h
index 657257f353df..00aafecc01b6 100644
--- a/src/defer.h
+++ b/src/defer.h
@@ -1,5 +1,5 @@
/* defer.h
- Copyright (C) 1993, 2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1993, 2001, 2004, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,15 +11,16 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
struct deferment
{
struct deferment *next;
- struct new_cpio_header header;
+ struct cpio_file_stat header;
};
-struct deferment *create_deferment P_((struct new_cpio_header *file_hdr));
-void free_deferment P_((struct deferment *d));
+struct deferment *create_deferment (struct cpio_file_stat *file_hdr);
+void free_deferment (struct deferment *d);
diff --git a/src/dstring.c b/src/dstring.c
index e3cdae764a91..aefeab88ce87 100644
--- a/src/dstring.c
+++ b/src/dstring.c
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#if defined(HAVE_CONFIG_H)
# include <config.h>
@@ -27,13 +28,8 @@
#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));
+char *xmalloc (unsigned n);
+char *xrealloc (char *p, unsigned n);
/* Initialiaze dynamic string STRING with space for SIZE characters. */
diff --git a/src/dstring.h b/src/dstring.h
index 1615518c4420..3628b99b3f66 100644
--- a/src/dstring.h
+++ b/src/dstring.h
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#ifndef NULL
#define NULL 0
diff --git a/src/extern.h b/src/extern.h
index e6e3d6e28e94..2bed3ce8f0be 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -1,5 +1,5 @@
/* extern.h - External declarations for cpio. Requires system.h.
- Copyright (C) 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 2001, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,15 +11,21 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
+
+#include "paxlib.h"
+#include "quotearg.h"
+#include "quote.h"
enum archive_format
{
arf_unknown, arf_binary, arf_oldascii, arf_newascii, arf_crcascii,
arf_tar, arf_ustar, arf_hpoldascii, arf_hpbinary
};
+
extern enum archive_format archive_format;
extern int reset_time_flag;
extern int io_block_size;
@@ -66,7 +72,7 @@ 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 unsigned int crc;
extern int delayed_seek_count;
#ifdef DEBUG_CPIO
extern int debug_flag;
@@ -81,7 +87,6 @@ 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;
@@ -94,38 +99,35 @@ 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));
+void warn_junk_bytes (long bytes_skipped);
+/* FIXME: make read_* static in copyin.c */
+void read_in_header (struct cpio_file_stat *file_hdr, int in_des);
+void read_in_old_ascii (struct cpio_file_stat *file_hdr, int in_des);
+void read_in_new_ascii (struct cpio_file_stat *file_hdr, int in_des);
+void read_in_binary (struct cpio_file_stat *file_hdr,
+ struct old_cpio_header *short_hdr, int in_des);
+void swab_array (char *arg, int count);
+void process_copy_in (void);
+void long_format (struct cpio_file_stat *file_hdr, char *link_name);
+void print_name_with_quoting (char *p);
/* copyout.c */
-void write_out_header P_((struct new_cpio_header *file_hdr, int out_des));
-void process_copy_out P_((void));
+int write_out_header (struct cpio_file_stat *file_hdr, int out_des);
+void process_copy_out (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));
+void process_copy_pass (void);
+int link_to_maj_min_ino (char *file_name, int st_dev_maj,
+ int st_dev_min, int st_ino);
+int link_to_name (char *link_name, char *link_target);
/* dirname.c */
-char *dirname P_((char *path));
+char *dirname (char *path);
/* filemode.c */
-void mode_string P_((unsigned int mode, char *str));
+void mode_string (unsigned int mode, char *str);
/* idcache.c */
#ifndef __MSDOS__
@@ -136,61 +138,63 @@ gid_t *getgidbyname ();
#endif
/* main.c */
-void process_args P_((int argc, char *argv[]));
-void initialize_buffers P_((void));
+void process_args (int argc, char *argv[]);
+void initialize_buffers (void);
/* makepath.c */
-int make_path P_((char *argpath, int mode, int parent_mode,
- uid_t owner, gid_t group, char *verbose_fmt_string));
+int make_path (char *argpath, int mode, int parent_mode,
+ uid_t owner, gid_t group, char *verbose_fmt_string);
/* tar.c */
-void write_out_tar_header 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));
+void write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des);
+int null_block (long *block, int size);
+void read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des);
+int otoa (char *s, unsigned long *n);
+int is_tar_header (char *buf);
+int is_tar_filename_too_long (char *name);
/* userspec.c */
#ifndef __MSDOS__
-char *parse_user_spec P_((char *name, uid_t *uid, gid_t *gid,
- char **username, char **groupname));
+char *parse_user_spec (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));
+void tape_empty_output_buffer (int out_des);
+void disk_empty_output_buffer (int out_des);
+void swahw_array (char *ptr, int count);
+void tape_buffered_write (char *in_buf, int out_des, off_t num_bytes);
+void tape_buffered_read (char *in_buf, int in_des, off_t num_bytes);
+int tape_buffered_peek (char *peek_buf, int in_des, int num_bytes);
+void tape_toss_input (int in_des, off_t num_bytes);
+void copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes);
+void copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes, char *filename);
+void copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes, char *filename);
+void warn_if_file_changed (char *file_name, unsigned long old_file_size,
+ off_t old_file_mtime);
+void create_all_directories (char *name);
+void prepare_append (int out_file_des);
+char *find_inode_file (unsigned long node_num,
+ unsigned long major_num, unsigned long minor_num);
+void add_inode (unsigned long node_num, char *file_name,
+ unsigned long major_num, unsigned long minor_num);
+int open_archive (char *file);
+void tape_offline (int tape_des);
+void get_next_reel (int tape_des);
+void set_new_media_message (char *message);
#if defined(__MSDOS__) && !defined(__GNUC__)
-int chown P_((char *path, int owner, int group));
+int chown (char *path, int owner, int group);
#endif
#ifdef __TURBOC__
-int utime P_((char *filename, struct utimbuf *utb));
+int utime (char *filename, struct utimbuf *utb);
#endif
#ifdef HPUX_CDF
-char *add_cdf_double_slashes P_((char *filename));
+char *add_cdf_double_slashes (char *filename);
#endif
-
-#define DISK_IO_BLOCK_SIZE (512)
+void write_nuls_to_file (off_t num_bytes, int out_des,
+ void (*writer) (char *in_buf,
+ int out_des, off_t num_bytes));
+#define DISK_IO_BLOCK_SIZE 512
/* FIXME: Move to system.h? */
#ifndef SYMLINK_USES_UMASK
@@ -198,3 +202,20 @@ char *add_cdf_double_slashes P_((char *filename));
#else
# define UMASKED_SYMLINK(name1,name2,mode) umasked_symlink(name1,name2,mode)
#endif /* SYMLINK_USES_UMASK */
+
+void set_perms (int fd, struct cpio_file_stat *header);
+void set_file_times (int fd, const char *name, unsigned long atime,
+ unsigned long mtime);
+void stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st);
+void cpio_safer_name_suffix (char *name, bool link_target,
+ bool absolute_names, bool strip_leading_dots);
+
+/* FIXME: These two defines should be defined in paxutils */
+#define LG_8 3
+#define LG_16 4
+
+uintmax_t from_ascii (char const *where, size_t digs, unsigned logbase);
+
+#define FROM_OCTAL(f) from_ascii (f, sizeof f, LG_8)
+#define FROM_HEX(f) from_ascii (f, sizeof f, LG_16)
+
diff --git a/src/filemode.c b/src/filemode.c
index ff4d379c7a4f..98f281370dd8 100644
--- a/src/filemode.c
+++ b/src/filemode.c
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
diff --git a/src/filetypes.h b/src/filetypes.h
index 9f785a182662..de6d77f6284a 100644
--- a/src/filetypes.h
+++ b/src/filetypes.h
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
/* Include sys/types.h and sys/stat.h before this file. */
diff --git a/src/global.c b/src/global.c
index 97b6bea1495d..3341e8ab1d6f 100644
--- a/src/global.c
+++ b/src/global.c
@@ -1,5 +1,5 @@
/* global.c - global variables and initial values for cpio.
- Copyright (C) 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 2001, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#include <system.h>
@@ -139,7 +140,7 @@ char *archive_name = NULL;
char *rsh_command_option = NULL;
/* CRC checksum. */
-unsigned long crc;
+unsigned int crc;
/* Input and output buffers. */
char *input_buffer, *output_buffer;
@@ -165,9 +166,6 @@ long long input_bytes, output_bytes;
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;
diff --git a/src/idcache.c b/src/idcache.c
index d3bf482472f2..17fcc04e238c 100644
--- a/src/idcache.c
+++ b/src/idcache.c
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
diff --git a/src/main.c b/src/main.c
index cd96e584d99f..7581b8ffd17e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,6 @@
/* main.c - main program and argument processing for cpio.
- Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +12,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
/* Written by Phil Nelson <phil@cs.wwu.edu>,
David MacKenzie <djm@gnu.ai.mit.edu>,
@@ -21,6 +23,7 @@
and Sergey Poznyakoff <gray@mirddin.farlep.net> */
#include <system.h>
+#include <paxlib.h>
#include <stdio.h>
#include <getopt.h>
@@ -29,7 +32,7 @@
#include <sys/stat.h>
#ifdef HAVE_LOCALE_H
-# include <locale.h>
+# include <locale.h>
#endif
#include "filetypes.h"
@@ -37,10 +40,11 @@
#include "dstring.h"
#include "extern.h"
#include <rmt.h>
-#include <localedir.h>
+#include <rmt-command.h>
enum cpio_options {
- NO_ABSOLUTE_FILENAMES_OPTION=256,
+ NO_ABSOLUTE_FILENAMES_OPTION=256,
+ ABSOLUTE_FILENAMES_OPTION,
NO_PRESERVE_OWNER_OPTION,
ONLY_VERIFY_CRC_OPTION,
RENAME_BATCH_FILE_OPTION,
@@ -50,8 +54,9 @@ enum cpio_options {
FORCE_LOCAL_OPTION,
DEBUG_OPTION,
BLOCK_SIZE_OPTION,
- TO_STDOUT_OPTION,
-
+ TO_STDOUT_OPTION,
+
+ HANG_OPTION,
USAGE_OPTION,
LICENSE_OPTION,
VERSION_OPTION
@@ -71,129 +76,156 @@ Examples:\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));
+ if (cond) \
+ ERROR((PAXEXIT_FAILURE, 0, _("%s is meaningless with %s"), opt, mode_opt));
static struct argp_option options[] = {
+ /* ********** */
+#define GRID 10
{NULL, 0, NULL, 0,
- N_("Main operation mode:"), 10},
+ N_("Main operation mode:"), GRID },
{"create", 'o', 0, 0,
- N_("Create the archive (run in copy-out mode)"), 10},
+ N_("Create the archive (run in copy-out mode)"), GRID },
{"extract", 'i', 0, 0,
- N_("Extract files from an archive (run in copy-in mode)")},
+ N_("Extract files from an archive (run in copy-in mode)"), GRID },
{"pass-through", 'p', 0, 0,
- N_("Run in copy-pass mode"), 10},
+ N_("Run in copy-pass mode"), GRID },
{"list", 't', 0, 0,
- N_("Print a table of contents of the input"), 10},
-
+ N_("Print a table of contents of the input"), GRID },
+#undef GRID
+
+ /* ********** */
+#define GRID 100
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid in any mode:"), 100},
+ N_("Operation modifiers valid in any mode:"), GRID },
{"file", 'F', N_("[[USER@]HOST:]FILE-NAME"), 0,
- N_("Use this FILE-NAME instead of standard input or output. Optional USER and HOST specify the user and host names in case of a remote archive"), 110},
+ N_("Use this FILE-NAME instead of standard input or output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
{"force-local", FORCE_LOCAL_OPTION, 0, 0,
- N_("Archive file is local, even if its name contains colons"), 110},
+ N_("Archive file is local, even if its name contains colons"), GRID+1 },
{"format", 'H', N_("FORMAT"), 0,
- N_("Use given archive FORMAT"), 110},
+ N_("Use given archive FORMAT"), GRID+1 },
{NULL, 'B', NULL, 0,
- N_("Set the I/O block size to 5120 bytes"), 110},
+ N_("Set the I/O block size to 5120 bytes"), GRID+1 },
{"block-size", BLOCK_SIZE_OPTION, N_("BLOCK-SIZE"), 0,
- N_("Set the I/O block size to BLOCK-SIZE * 512 bytes"), 110},
+ N_("Set the I/O block size to BLOCK-SIZE * 512 bytes"), GRID+1 },
{NULL, 'c', NULL, 0,
- N_("Use the old portable (ASCII) archive format"), 0},
+ N_("Use the old portable (ASCII) archive format"), GRID+1 },
{"dot", 'V', NULL, 0,
- N_("Print a \".\" for each file processed"), 110},
+ N_("Print a \".\" for each file processed"), GRID+1 },
{"io-size", 'C', N_("NUMBER"), 0,
- N_("Set the I/O block size to the given NUMBER of bytes"), 110},
+ N_("Set the I/O block size to the given NUMBER of bytes"), GRID+1 },
{"message", 'M', N_("STRING"), 0,
N_("Print STRING when the end of a volume of the backup media is reached"),
- 110},
+ GRID+1 },
{"nonmatching", 'f', 0, 0,
- N_("Only copy files that do not match any of the given patterns"), 110},
+ N_("Only copy files that do not match any of the given patterns"), GRID+1 },
{"numeric-uid-gid", 'n', 0, 0,
N_("In the verbose table of contents listing, show numeric UID and GID"),
- 110},
+ GRID+1 },
{"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
- N_("Use remote COMMAND instead of rsh"), 110},
+ N_("Use remote COMMAND instead of rsh"), GRID+1 },
{"quiet", QUIET_OPTION, NULL, 0,
- N_("Do not print the number of blocks copied"), 110},
+ N_("Do not print the number of blocks copied"), GRID+1 },
{"verbose", 'v', NULL, 0,
- N_("Verbosely list the files processed"), 110},
+ N_("Verbosely list the files processed"), GRID+1 },
#ifdef DEBUG_CPIO
{"debug", DEBUG_OPTION, NULL, 0,
- N_("Enable debugging info"), 110},
+ N_("Enable debugging info"), GRID+1 },
#endif
{"warning", 'W', N_("FLAG"), 0,
- N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), 110 },
-
+ N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), GRID+1 },
+#undef GRID
+
/* ********** */
+#define GRID 200
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid only in copy-in mode:"), 200},
+ N_("Operation modifiers valid only in copy-in mode:"), GRID },
{"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},
+ N_("Read additional patterns specifying filenames to extract or list from FILE"), 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},
+ N_("When reading a CRC format archive, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
{"rename", 'r', 0, 0,
- N_("Interactively rename files"), 210},
+ N_("Interactively rename files"), GRID+1 },
{"rename-batch-file", RENAME_BATCH_FILE_OPTION, N_("FILE"), OPTION_HIDDEN,
- "", 210},
+ "", GRID+1 },
{"swap", 'b', NULL, 0,
- N_("Swap both halfwords of words and bytes of halfwords in the data. Equivalent to -sS"), 210},
+ N_("Swap both halfwords of words and bytes of halfwords in the data. Equivalent to -sS"), GRID+1 },
{"swap-bytes", 's', NULL, 0,
- N_("Swap the bytes of each halfword in the files"), 210},
+ N_("Swap the bytes of each halfword in the files"), GRID+1 },
{"swap-halfwords", 'S', NULL, 0,
N_("Swap the halfwords of each word (4 bytes) in the files"),
- 210},
+ GRID+1 },
{"to-stdout", TO_STDOUT_OPTION, NULL, 0,
- N_("Extract files to standard output"), 210},
+ N_("Extract files to standard output"), GRID+1 },
+#undef GRID
/* ********** */
+#define GRID 300
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid only in copy-out mode:"), 300},
+ N_("Operation modifiers valid only in copy-out mode:"), GRID },
{"append", 'A', 0, 0,
- N_("Append to an existing archive."), 310 },
+ N_("Append to an existing archive."), GRID+1 },
{NULL, 'O', N_("[[USER@]HOST:]FILE-NAME"), 0,
- N_("Archive filename to use instead of standard output. Optional USER and HOST specify the user and host names in case of a remote archive"), 310},
+ N_("Archive filename to use instead of standard output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
+#undef GRID
/* ********** */
+#define GRID 400
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid only in copy-pass mode:"), 400},
+ N_("Operation modifiers valid only in copy-pass mode:"), GRID},
{"link", 'l', 0, 0,
- N_("Link files instead of copying them, when possible"), 410},
+ N_("Link files instead of copying them, when possible"), GRID+1 },
+#undef GRID
+
/* ********** */
+#define GRID 500
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid for copy-out and copy-pass modes:"), 500},
+ N_("Operation modifiers valid in copy-in and copy-out modes:"), GRID },
+ {"absolute-filenames", ABSOLUTE_FILENAMES_OPTION, 0, 0,
+ N_("Do not strip file system prefix components from the file names"),
+ GRID+1 },
+ {"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
+ N_("Create all files relative to the current directory"), GRID+1 },
+#undef GRID
+ /* ********** */
+#define GRID 600
+ {NULL, 0, NULL, 0,
+ N_("Operation modifiers valid in copy-out and copy-pass modes:"), GRID },
{"null", '0', 0, 0,
- N_("A list of filenames is terminated by a null character instead of a newline"), 510 },
+ N_("A list of filenames is terminated by a null character instead of a newline"), GRID+1 },
{NULL, 'I', N_("[[USER@]HOST:]FILE-NAME"), 0,
- N_("Archive filename to use instead of standard input. Optional USER and HOST specify the user and host names in case of a remote archive"), 510},
+ N_("Archive filename to use instead of standard input. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
{"dereference", 'L', 0, 0,
- N_("Dereference symbolic links (copy the files that they point to instead of copying the links)."), 510},
+ N_("Dereference symbolic links (copy the files that they point to instead of copying the links)."), GRID+1 },
{"owner", 'R', N_("[USER][:.][GROUP]"), 0,
- N_("Set the ownership of all files created to the specified USER and/or GROUP"), 510},
- {"sparse", SPARSE_OPTION, NULL, 0,
- N_("Write files with large blocks of zeros as sparse files"), 510},
+ N_("Set the ownership of all files created to the specified USER and/or GROUP"), GRID+1 },
{"reset-access-time", 'a', NULL, 0,
- N_("Reset the access times of files after reading them"), 510},
+ N_("Reset the access times of files after reading them"), GRID+1 },
+#undef GRID
/* ********** */
+#define GRID 700
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid for copy-in and copy-pass modes:"), 600},
+ N_("Operation modifiers valid in copy-in and copy-pass modes:"), GRID },
{"preserve-modification-time", 'm', 0, 0,
- N_("Retain previous file modification times when creating files"), 610},
+ N_("Retain previous file modification times when creating files"), GRID+1 },
{"make-directories", 'd', 0, 0,
- N_("Create leading directories where needed"), 610},
+ N_("Create leading directories where needed"), GRID+1 },
{"no-preserve-owner", NO_PRESERVE_OWNER_OPTION, 0, 0,
- N_("Do not change the ownership of the files"), 610},
+ N_("Do not change the ownership of the files"), GRID+1 },
{"unconditional", 'u', NULL, 0,
- N_("Replace all files unconditionally"), 610},
-
+ N_("Replace all files unconditionally"), GRID+1 },
+ {"sparse", SPARSE_OPTION, NULL, 0,
+ N_("Write files with large blocks of zeros as sparse files"), GRID+1 },
+#undef GRID
+
+ /* ********** */
+#define GRID 800
{NULL, 0, NULL, 0,
- N_("Informative options:"), 700 },
+ N_("Informative options:"), GRID },
{"help", '?', 0, 0, N_("Give this help list"), -1},
{"usage", USAGE_OPTION, 0, 0, N_("Give a short usage message"), -1},
@@ -201,7 +233,9 @@ static struct argp_option options[] = {
{"version", VERSION_OPTION, 0, 0, N_("Print program version"), -1},
/* FIXME -V (--dot) conflicts with the default short option for
--version */
-
+ {"HANG", HANG_OPTION, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
+ N_("hang for SECS seconds (default 3600)"), 0},
+#undef GRID
{0, 0, 0, 0}
};
@@ -224,8 +258,8 @@ license ()
" 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"));
+ " along with GNU cpio; if not, write to the Free Software Foundation,\n"
+ " Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n\n"));
exit (0);
}
@@ -269,6 +303,7 @@ warn_control (char *arg)
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
+ static volatile int _argp_hang;
switch (key)
{
case '0': /* Read null-terminated filenames. */
@@ -301,7 +336,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'c': /* Use the old portable ASCII format. */
if (archive_format != arf_unknown)
- USAGE_ERROR ((0, 0, _("Archive format multiply defined")));
+ error (0, EXIT_FAILURE, _("Archive format multiply defined"));
#ifdef SVR4_COMPAT
archive_format = arf_newascii; /* -H newc. */
#else
@@ -333,7 +368,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'H': /* Header format name. */
if (archive_format != arf_unknown)
- USAGE_ERROR ((0, 0, _("Archive format multiply defined")));
+ error (PAXEXIT_FAILURE, 0, _("Archive format multiply defined"));
if (!strcasecmp (arg, "crc"))
archive_format = arf_crcascii;
else if (!strcasecmp (arg, "newc"))
@@ -358,7 +393,7 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case 'i': /* Copy-in mode. */
if (copy_function != 0)
- USAGE_ERROR ((0, 0, _("Mode already defined")));
+ error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
copy_function = process_copy_in;
break;
@@ -394,17 +429,21 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case NO_ABSOLUTE_FILENAMES_OPTION: /* --no-absolute-filenames */
no_abs_paths_flag = true;
break;
-
+
+ case ABSOLUTE_FILENAMES_OPTION: /* --absolute-filenames */
+ no_abs_paths_flag = false;
+ 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")));
+ error (PAXEXIT_FAILURE, 0,
+ _("--no-preserve-owner cannot be used with --owner"));
no_chown_flag = true;
break;
case 'o': /* Copy-out mode. */
if (copy_function != 0)
- USAGE_ERROR ((0, 0, _("Mode already defined")));
+ error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
copy_function = process_copy_out;
break;
@@ -418,7 +457,7 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case 'p': /* Copy-pass mode. */
if (copy_function != 0)
- USAGE_ERROR ((0, 0, _("Mode already defined")));
+ error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
copy_function = process_copy_pass;
break;
@@ -440,25 +479,26 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
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;
- }
- }
+ error (PAXEXIT_FAILURE, 0,
+ _("--owner cannot be used with --no-preserve-owner"));
+ else
+ {
+ char *e, *u, *g;
+
+ e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
+ if (e)
+ error (PAXEXIT_FAILURE, 0, "%s: %s", arg, e);
+ if (u)
+ {
+ free (u);
+ set_owner_flag = true;
+ }
+ if (g)
+ {
+ free (g);
+ set_group_flag = true;
+ }
+ }
break;
case 's': /* Swap bytes. */
@@ -507,6 +547,12 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case TO_STDOUT_OPTION:
to_stdout_option = true;
break;
+
+ case HANG_OPTION:
+ _argp_hang = atoi (arg ? arg : "3600");
+ while (_argp_hang-- > 0)
+ sleep (1);
+ break;
case '?':
argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
@@ -552,9 +598,9 @@ process_args (int argc, char *argv[])
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));
+ error (PAXEXIT_FAILURE, 0,
+ _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
+ program_name, program_name);
xstat = lstat;
@@ -568,9 +614,9 @@ process_args (int argc, char *argv[])
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));
+ error (PAXEXIT_FAILURE, 0,
+ _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
+ program_name, program_name);
}
/* Work around for pcc bug. */
@@ -584,7 +630,6 @@ process_args (int argc, char *argv[])
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)
{
@@ -597,7 +642,8 @@ process_args (int argc, char *argv[])
}
if (archive_name && input_archive_name)
- USAGE_ERROR((0, 0, _("Both -I and -F are used in copy-in mode")));
+ error (PAXEXIT_FAILURE, 0,
+ _("Both -I and -F are used in copy-in mode"));
if (archive_format == arf_crcascii)
crc_i_flag = true;
@@ -609,7 +655,7 @@ process_args (int argc, char *argv[])
else if (copy_function == copy_out)
{
if (index != argc)
- USAGE_ERROR ((0, 0, _("Too many arguments")));
+ error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
archive_des = 1;
CHECK_USAGE(create_dir_flag, "--make-directories", "--create");
@@ -617,24 +663,24 @@ process_args (int argc, char *argv[])
CHECK_USAGE(table_flag, "--list", "--create");
CHECK_USAGE(unconditional_flag, "--unconditional", "--create");
CHECK_USAGE(link_flag, "--link", "--create");
+ CHECK_USAGE(sparse_flag, "--sparse", "--create");
CHECK_USAGE(retain_time_flag, "--preserve-modification-time",
"--create");
CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--create");
- CHECK_USAGE(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")));
+ error (PAXEXIT_FAILURE, 0,
+ _("--append is used but no archive file name is given (use -F or -O options)"));
CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--create");
- CHECK_USAGE(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")));
+ error (PAXEXIT_FAILURE, 0,
+ _("Both -O and -F are used in copy-out mode"));
if (archive_format == arf_unknown)
archive_format = arf_binary;
@@ -644,12 +690,14 @@ process_args (int argc, char *argv[])
else
{
/* Copy pass. */
- if (index != argc - 1)
- USAGE_ERROR ((0, 0, _("Too many arguments")));
+ if (index < argc - 1)
+ error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
+ else if (index > argc - 1)
+ error (PAXEXIT_FAILURE, 0, _("Not enough arguments"));
if (archive_format != arf_unknown)
- USAGE_ERROR((0, 0,
- _("Archive format is not specified in copy-pass mode (use --format option)")));
+ error (PAXEXIT_FAILURE, 0,
+ _("Archive format is not specified in copy-pass mode (use --format option)"));
CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--pass-through");
CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
@@ -660,6 +708,8 @@ process_args (int argc, char *argv[])
CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--pass-through");
CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames",
"--pass-through");
+ CHECK_USAGE(no_abs_paths_flag, "--absolute-pathnames",
+ "--pass-through");
CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through");
directory_name = argv[index];
@@ -668,11 +718,12 @@ process_args (int argc, char *argv[])
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")));
+ error (PAXEXIT_FAILURE, 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);
+ error (PAXEXIT_FAILURE, errno, _("Cannot open %s"),
+ quotearg_colon (archive_name));
}
/* Prevent SysV non-root users from giving away files inadvertantly.
@@ -725,33 +776,19 @@ initialize_buffers ()
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) ();
diff --git a/src/makepath.c b/src/makepath.c
index 9587ba8dc629..ff4c25f72c8d 100644
--- a/src/makepath.c
+++ b/src/makepath.c
@@ -1,5 +1,5 @@
/* makepath.c -- Ensure that a directory path exists.
- Copyright (C) 1990 Free Software Foundation, Inc.
+ Copyright (C) 1990, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu> and
Jim Meyering <meyering@cs.utexas.edu>. */
@@ -23,46 +24,11 @@
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 <paxlib.h>
#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.
@@ -126,7 +92,7 @@ make_path (char *argpath,
slash = dirpath;
while (*slash == '/')
slash++;
- while ((slash = index (slash, '/')))
+ while ((slash = strchr (slash, '/')))
{
#ifdef HPUX_CDF
int iscdf;
@@ -164,7 +130,7 @@ make_path (char *argpath,
#endif
)
{
- error (0, errno, "%s", dirpath);
+ chown_error_details (dirpath, owner, group);
retval = 1;
}
if (re_protect)
@@ -231,23 +197,23 @@ make_path (char *argpath,
#endif
)
{
- error (0, errno, "%s", dirpath);
+ chown_error_details (dirpath, owner, group);
retval = 1;
}
}
- /* chown may have turned off some permission bits we wanted. */
- if ((mode & 07000) != 0 && chmod (dirpath, mode))
- {
- error (0, errno, "%s", dirpath);
- retval = 1;
- }
+ /* chown may have turned off some permission bits we wanted. */
+ if ((mode & 07000) != 0 && chmod (dirpath, mode))
+ {
+ chmod_error_details (dirpath, mode);
+ retval = 1;
+ }
/* If the mode for leading directories didn't include owner "wx"
privileges, we have to reset their protections to the correct
value. */
for (p = leading_dirs; p != NULL; p = p->next)
{
- *(p->dirname_end) = '\0';
+ *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,
@@ -255,7 +221,7 @@ make_path (char *argpath,
bit so we don't break HP CDF's. */
if (chmod (dirpath, parent_mode))
{
- error (0, errno, "%s", dirpath);
+ chmod_error_details (dirpath, parent_mode);
retval = 1;
}
#endif
@@ -286,12 +252,12 @@ make_path (char *argpath,
#endif
)
{
- error (0, errno, "%s", dirpath);
+ chown_error_details (dirpath, owner, group);
retval = 1;
}
if (chmod (dirpath, mode))
{
- error (0, errno, "%s", dirpath);
+ chmod_error_details (dirpath, mode);
retval = 1;
}
}
diff --git a/src/tar.c b/src/tar.c
index 939d83a225aa..2a470c49516e 100644
--- a/src/tar.c
+++ b/src/tar.c
@@ -1,5 +1,5 @@
/* tar.c - read in write tar headers for cpio
- Copyright (C) 1992, 2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1992, 2001, 2004, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#include <system.h>
@@ -112,10 +113,10 @@ to_oct (register long value, register int digits, register char *where)
/* Compute and return a checksum for TAR_HDR,
counting the checksum bytes as if they were spaces. */
-unsigned long
+unsigned int
tar_checksum (struct tar_header *tar_hdr)
{
- unsigned long sum = 0;
+ unsigned int sum = 0;
char *p = (char *) tar_hdr;
char *q = p + TARRECORDSIZE;
int i;
@@ -136,13 +137,13 @@ tar_checksum (struct tar_header *tar_hdr)
descriptor OUT_DES. */
void
-write_out_tar_header (struct new_cpio_header *file_hdr, int out_des)
+write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des)
{
int name_len;
union tar_record tar_rec;
struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
- bzero ((char *) &tar_rec, TARRECORDSIZE);
+ memset (&tar_rec, 0, sizeof tar_rec);
/* process_copy_out must ensure that file_hdr->c_name is short enough,
or we will lose here. */
@@ -254,7 +255,7 @@ null_block (long *block, int size)
into FILE_HDR. */
void
-read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
+read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des)
{
long bytes_skipped = 0;
int warned = false;
@@ -280,7 +281,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
#endif
{
- file_hdr->c_name = "TRAILER!!!";
+ file_hdr->c_name = CPIO_TRAILER_NAME;
return;
}
#if 0
@@ -290,7 +291,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
while (1)
{
- otoa (tar_hdr->chksum, &file_hdr->c_chksum);
+ file_hdr->c_chksum = FROM_OCTAL (tar_hdr->chksum);
if (file_hdr->c_chksum != tar_checksum (tar_hdr))
{
@@ -307,8 +308,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
error (0, 0, _("invalid header: checksum error"));
warned = true;
}
- bcopy (((char *) &tar_rec) + 1, (char *) &tar_rec,
- TARRECORDSIZE - 1);
+ memmove (&tar_rec, ((char *) &tar_rec) + 1, TARRECORDSIZE - 1);
tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
++bytes_skipped;
continue;
@@ -319,7 +319,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
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 = FROM_OCTAL (tar_hdr->mode);
file_hdr->c_mode = file_hdr->c_mode & 07777;
/* Debian hack: This version of cpio uses the -n flag also to extract
tar archives using the numeric UID/GID instead of the user/group
@@ -328,17 +328,17 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
&& (uidp = getuidbyname (tar_hdr->uname)))
file_hdr->c_uid = *uidp;
else
- otoa (tar_hdr->uid, &file_hdr->c_uid);
+ file_hdr->c_uid = FROM_OCTAL (tar_hdr->uid);
if (archive_format == arf_ustar && !numeric_uid
&& (gidp = getgidbyname (tar_hdr->gname)))
file_hdr->c_gid = *gidp;
else
- 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_gid = FROM_OCTAL (tar_hdr->gid);
+ file_hdr->c_filesize = FROM_OCTAL (tar_hdr->size);
+ file_hdr->c_mtime = FROM_OCTAL (tar_hdr->mtime);
+ file_hdr->c_rdev_maj = FROM_OCTAL (tar_hdr->devmajor);
+ file_hdr->c_rdev_min = FROM_OCTAL (tar_hdr->devminor);
file_hdr->c_tar_linkname = NULL;
switch (tar_hdr->typeflag)
@@ -409,26 +409,6 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
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),
@@ -441,7 +421,7 @@ is_tar_header (char *buf)
struct tar_header *tar_hdr = (struct tar_header *) buf;
unsigned long chksum;
- otoa (tar_hdr->chksum, &chksum);
+ chksum = FROM_OCTAL (tar_hdr->chksum);
if (chksum != tar_checksum (tar_hdr))
return 0;
@@ -473,7 +453,6 @@ 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)
diff --git a/src/tar.h b/src/tar.h
index 79f289eea15e..7b27e86a56fc 100644
--- a/src/tar.h
+++ b/src/tar.h
@@ -14,10 +14,10 @@ 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. */
+You should have received a copy of the GNU Library General
+Public License along with this library; see the file COPYING.LIB.
+If not, write to the Free Software Foundation, Inc., 51 Franklin
+Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#ifndef _TAR_H
diff --git a/src/tarhdr.h b/src/tarhdr.h
index 8b1211dffae0..b901739c19cc 100644
--- a/src/tarhdr.h
+++ b/src/tarhdr.h
@@ -11,9 +11,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#ifndef _TARHDR_H
diff --git a/src/userspec.c b/src/userspec.c
index c426acd81bda..d9be4f43570d 100644
--- a/src/userspec.c
+++ b/src/userspec.c
@@ -1,5 +1,6 @@
/* userspec.c -- Parse a user and group string.
- Copyright (C) 1989, 1990, 1991, 1992, 2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1992, 2001,
+ 2004, 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +12,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
@@ -72,7 +74,7 @@ extern struct group *getgrgid (gid_t gid);
otherwise return 0. */
static int
-isnumber (const char *str)
+isnumber_p (const char *str)
{
for (; *str; str++)
if (!isdigit (*str))
@@ -111,9 +113,9 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
V_STRDUP (spec, spec_arg);
/* Find the separator if there is one. */
- separator = index (spec, ':');
+ separator = strchr (spec, ':');
if (separator == NULL)
- separator = index (spec, '.');
+ separator = strchr (spec, '.');
/* Replace separator with a NUL. */
if (separator != NULL)
@@ -136,7 +138,7 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
if (pwd == NULL)
{
- if (!isnumber (u))
+ if (!isnumber_p (u))
error_msg = _("invalid user");
else
{
@@ -182,7 +184,7 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
grp = getgrnam (g);
if (grp == NULL)
{
- if (!isnumber (g))
+ if (!isnumber_p (g))
error_msg = _("invalid group");
else
*gid = atoi (g);
diff --git a/src/util.c b/src/util.c
index 4b64648ee2b1..5bcc40aa2495 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,5 +1,6 @@
/* util.c - Several utility routines for cpio.
- Copyright (C) 1990, 1991, 1992, 2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 2001, 2004,
+ 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -11,9 +12,10 @@
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. */
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
#include <system.h>
@@ -23,15 +25,21 @@
#include "cpiohdr.h"
#include "dstring.h"
#include "extern.h"
+#include <paxlib.h>
+#include "filetypes.h"
+#include <safe-read.h>
+#include <full-write.h>
#include <rmt.h>
+#include <hash.h>
+#include <utimens.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_MTIO_H
-#ifdef HAVE_SYS_IO_TRIOCTL_H
-#include <sys/io/trioctl.h>
-#endif
-#include <sys/mtio.h>
+# ifdef HAVE_SYS_IO_TRIOCTL_H
+# include <sys/io/trioctl.h>
+# endif
+# include <sys/mtio.h>
#endif
#if !HAVE_DECL_ERRNO
@@ -90,6 +98,8 @@ tape_empty_output_buffer (int out_des)
output_size = 0;
}
+static int sparse_write (int fildes, char *buf, unsigned int nbyte);
+
/* Write `output_size' bytes of `output_buffer' to file
descriptor OUT_DES and reset `output_size' and `out_buff'.
If `swapping_halfwords' or `swapping_bytes' is set,
@@ -207,7 +217,7 @@ tape_fill_input_buffer (int in_des, int num_bytes)
Exit with an error if end of file is reached. */
static int
-disk_fill_input_buffer (int in_des, int num_bytes)
+disk_fill_input_buffer (int in_des, off_t num_bytes)
{
in_buff = input_buffer;
num_bytes = (num_bytes < DISK_IO_BLOCK_SIZE) ? num_bytes : DISK_IO_BLOCK_SIZE;
@@ -227,10 +237,10 @@ disk_fill_input_buffer (int in_des, int num_bytes)
When `out_buff' fills up, flush it to file descriptor OUT_DES. */
void
-tape_buffered_write (char *in_buf, int out_des, long num_bytes)
+tape_buffered_write (char *in_buf, int out_des, off_t num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
- register long space_left; /* Room left in output buffer. */
+ off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
+ off_t space_left; /* Room left in output buffer. */
while (bytes_left > 0)
{
@@ -241,7 +251,7 @@ tape_buffered_write (char *in_buf, int out_des, long num_bytes)
{
if (bytes_left < space_left)
space_left = bytes_left;
- bcopy (in_buf, out_buff, (unsigned) space_left);
+ memcpy (out_buff, in_buf, (unsigned) space_left);
out_buff += space_left;
output_size += space_left;
in_buf += space_left;
@@ -254,10 +264,10 @@ tape_buffered_write (char *in_buf, int out_des, long num_bytes)
When `out_buff' fills up, flush it to file descriptor OUT_DES. */
void
-disk_buffered_write (char *in_buf, int out_des, long num_bytes)
+disk_buffered_write (char *in_buf, int out_des, off_t num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
- register long space_left; /* Room left in output buffer. */
+ off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
+ off_t space_left; /* Room left in output buffer. */
while (bytes_left > 0)
{
@@ -268,7 +278,7 @@ disk_buffered_write (char *in_buf, int out_des, long num_bytes)
{
if (bytes_left < space_left)
space_left = bytes_left;
- bcopy (in_buf, out_buff, (unsigned) space_left);
+ memcpy (out_buff, in_buf, (unsigned) space_left);
out_buff += space_left;
output_size += space_left;
in_buf += space_left;
@@ -282,10 +292,10 @@ disk_buffered_write (char *in_buf, int out_des, long num_bytes)
When `in_buff' is exhausted, refill it from file descriptor IN_DES. */
void
-tape_buffered_read (char *in_buf, int in_des, long num_bytes)
+tape_buffered_read (char *in_buf, int in_des, off_t num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
- register long space_left; /* Bytes to copy from input buffer. */
+ off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
+ off_t space_left; /* Bytes to copy from input buffer. */
while (bytes_left > 0)
{
@@ -295,7 +305,7 @@ tape_buffered_read (char *in_buf, int in_des, long num_bytes)
space_left = bytes_left;
else
space_left = input_size;
- bcopy (in_buff, in_buf, (unsigned) space_left);
+ memcpy (in_buf, in_buff, (unsigned) space_left);
in_buff += space_left;
in_buf += space_left;
input_size -= space_left;
@@ -345,7 +355,7 @@ tape_buffered_peek (char *peek_buf, int in_des, int num_bytes)
first block to make room. */
int half;
half = input_buffer_size / 2;
- bcopy (input_buffer + half, input_buffer, half);
+ memmove (input_buffer, input_buffer + half, half);
in_buff = in_buff - half;
append_buf = append_buf - half;
}
@@ -369,17 +379,17 @@ tape_buffered_peek (char *peek_buf, int in_des, int num_bytes)
got_bytes = num_bytes;
else
got_bytes = input_size;
- bcopy (in_buff, peek_buf, (unsigned) got_bytes);
+ memcpy (peek_buf, in_buff, (unsigned) got_bytes);
return got_bytes;
}
/* Skip the next NUM_BYTES bytes of file descriptor IN_DES. */
void
-tape_toss_input (int in_des, long num_bytes)
+tape_toss_input (int in_des, off_t num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
- register long space_left; /* Bytes to copy from input buffer. */
+ off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
+ off_t space_left; /* Bytes to copy from input buffer. */
while (bytes_left > 0)
{
@@ -403,18 +413,19 @@ tape_toss_input (int in_des, long num_bytes)
}
}
-static void
-write_nuls_to_file (long num_bytes, int out_des,
- void (*writer) (char *in_buf, int out_des, long num_bytes))
+void
+write_nuls_to_file (off_t num_bytes, int out_des,
+ void (*writer) (char *in_buf, int out_des, off_t num_bytes))
{
- long blocks;
- long extra_bytes;
- long i;
-
- blocks = num_bytes / 512;
- extra_bytes = num_bytes % 512;
+ off_t blocks;
+ off_t extra_bytes;
+ off_t i;
+ static char zeros_512[512];
+
+ blocks = num_bytes / sizeof zeros_512;
+ extra_bytes = num_bytes % sizeof zeros_512;
for (i = 0; i < blocks; ++i)
- writer (zeros_512, out_des, 512);
+ writer (zeros_512, out_des, sizeof zeros_512);
if (extra_bytes)
writer (zeros_512, out_des, extra_bytes);
}
@@ -428,7 +439,7 @@ write_nuls_to_file (long num_bytes, int out_des,
NUM_BYTES is the number of bytes to copy. */
void
-copy_files_tape_to_disk (int in_des, int out_des, long num_bytes)
+copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes)
{
long size;
long k;
@@ -458,13 +469,13 @@ copy_files_tape_to_disk (int in_des, int out_des, long num_bytes)
NUM_BYTES is the number of bytes to copy. */
void
-copy_files_disk_to_tape (int in_des, int out_des, long num_bytes,
+copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes,
char *filename)
{
long size;
long k;
int rc;
- long original_num_bytes;
+ off_t original_num_bytes;
original_num_bytes = num_bytes;
@@ -472,14 +483,20 @@ copy_files_disk_to_tape (int in_des, int out_des, long num_bytes,
{
if (input_size == 0)
if (rc = disk_fill_input_buffer (in_des,
- num_bytes < DISK_IO_BLOCK_SIZE ?
- num_bytes : DISK_IO_BLOCK_SIZE))
+ num_bytes < DISK_IO_BLOCK_SIZE ?
+ num_bytes : DISK_IO_BLOCK_SIZE))
{
if (rc > 0)
- error (0, 0, _("File %s shrunk by %ld bytes, padding with zeros"),
- filename, num_bytes);
+ {
+ char buf[UINTMAX_STRSIZE_BOUND];
+ error (0, 0,
+ ngettext ("File %s shrunk by %s byte, padding with zeros",
+ "File %s shrunk by %s bytes, padding with zeros",
+ num_bytes),
+ filename, STRINGIFY_BIGINT (num_bytes, buf));
+ }
else
- error (0, 0, _("Read error at byte %ld in file %s, padding with zeros"),
+ error (0, 0, _("Read error at byte %lld in file %s, padding with zeros"),
original_num_bytes - num_bytes, filename);
write_nuls_to_file (num_bytes, out_des, tape_buffered_write);
break;
@@ -505,12 +522,12 @@ copy_files_disk_to_tape (int in_des, int out_des, long num_bytes,
NUM_BYTES is the number of bytes to copy. */
void
-copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
+copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes,
char *filename)
{
long size;
long k;
- long original_num_bytes;
+ off_t original_num_bytes;
int rc;
original_num_bytes = num_bytes;
@@ -520,10 +537,16 @@ copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
if (rc = disk_fill_input_buffer (in_des, num_bytes))
{
if (rc > 0)
- error (0, 0, _("File %s shrunk by %ld bytes, padding with zeros"),
- filename, num_bytes);
+ {
+ char buf[UINTMAX_STRSIZE_BOUND];
+ error (0, 0,
+ ngettext ("File %s shrunk by %s byte, padding with zeros",
+ "File %s shrunk by %s bytes, padding with zeros",
+ num_bytes),
+ filename, STRINGIFY_BIGINT (num_bytes, buf));
+ }
else
- error (0, 0, _("Read error at byte %ld in file %s, padding with zeros"),
+ error (0, 0, _("Read error at byte %lld in file %s, padding with zeros"),
original_num_bytes - num_bytes, filename);
write_nuls_to_file (num_bytes, out_des, disk_buffered_write);
break;
@@ -545,20 +568,23 @@ copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
void
warn_if_file_changed (char *file_name, unsigned long old_file_size,
- unsigned long old_file_mtime)
+ off_t old_file_mtime)
{
struct stat new_file_stat;
if ((*xstat) (file_name, &new_file_stat) < 0)
{
- error (0, errno, "%s", file_name);
+ stat_error (file_name);
return;
}
/* Only check growth, shrinkage detected in copy_files_disk_to_{disk,tape}()
*/
if (new_file_stat.st_size > old_file_size)
- error (0, 0, _("File %s grew, %ld new bytes not copied"),
- file_name, (long)(new_file_stat.st_size - old_file_size));
+ error (0, 0,
+ ngettext ("File %s grew, %"PRIuMAX" new byte not copied",
+ "File %s grew, %"PRIuMAX" new bytes not copied",
+ (long)(new_file_stat.st_size - old_file_size)),
+ file_name, (uintmax_t) (new_file_stat.st_size - old_file_size));
else if (new_file_stat.st_mtime != old_file_mtime)
error (0, 0, _("File %s was modified while being copied"), file_name);
@@ -658,82 +684,40 @@ struct inode_val
};
/* Inode hash table. Allocated by first call to add_inode. */
-static struct inode_val **hash_table = NULL;
-
-/* Size of current hash table. Initial size is 47. (47 = 2*22 + 3) */
-static int hash_size = 22;
+static Hash_table *hash_table = NULL;
-/* Number of elements in current hash table. */
-static int hash_num;
+static size_t
+inode_val_hasher (const void *val, size_t n_buckets)
+{
+ const struct inode_val *ival = val;
+ return ival->inode % n_buckets;
+}
-/* Find the file name associated with NODE_NUM. If there is no file
- associated with NODE_NUM, return NULL. */
+static bool
+inode_val_compare (const void *val1, const void *val2)
+{
+ const struct inode_val *ival1 = val1;
+ const struct inode_val *ival2 = val2;
+ return ival1->inode == ival2->inode
+ && ival1->major_num == ival2->major_num
+ && ival1->minor_num == ival2->minor_num;
+}
char *
find_inode_file (unsigned long node_num, unsigned long major_num,
unsigned long minor_num)
{
- int start; /* Initial hash location. */
- int temp; /* Rehash search variable. */
-
- if (hash_table != NULL)
- {
- /* Hash function is node number modulo the table size. */
- start = node_num % hash_size;
-
- /* Initial look into the table. */
- if (hash_table[start] == NULL)
- return NULL;
- if (hash_table[start]->inode == node_num
- && hash_table[start]->major_num == major_num
- && hash_table[start]->minor_num == minor_num)
- return hash_table[start]->file_name;
-
- /* The home position is full with a different inode record.
- Do a linear search terminated by a NULL pointer. */
- for (temp = (start + 1) % hash_size;
- hash_table[temp] != NULL && temp != start;
- temp = (temp + 1) % hash_size)
- {
- if (hash_table[temp]->inode == node_num
- && hash_table[start]->major_num == major_num
- && hash_table[start]->minor_num == minor_num)
- return hash_table[temp]->file_name;
- }
- }
- return NULL;
-}
-
-/* Do the hash insert. Used in normal inserts and resizing the hash
- table. It is guaranteed that there is room to insert the item.
- NEW_VALUE is the pointer to the previously allocated inode, file
- name association record. */
-
-static void
-hash_insert (struct inode_val *new_value)
-{
- int start; /* Home position for the value. */
- int temp; /* Used for rehashing. */
-
- /* Hash function is node number modulo the table size. */
- start = new_value->inode % hash_size;
-
- /* Do the initial look into the table. */
- if (hash_table[start] == NULL)
- {
- hash_table[start] = new_value;
- return;
- }
-
- /* If we get to here, the home position is full with a different inode
- record. Do a linear search for the first NULL pointer and insert
- the new item there. */
- temp = (start + 1) % hash_size;
- while (hash_table[temp] != NULL)
- temp = (temp + 1) % hash_size;
-
- /* Insert at the NULL. */
- hash_table[temp] = new_value;
+ struct inode_val sample;
+ struct inode_val *ival;
+
+ if (!hash_table)
+ return NULL;
+
+ sample.inode = node_num;
+ sample.major_num = major_num;
+ sample.minor_num = minor_num;
+ ival = hash_lookup (hash_table, &sample);
+ return ival ? ival->file_name : NULL;
}
/* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */
@@ -743,7 +727,8 @@ add_inode (unsigned long node_num, char *file_name, unsigned long major_num,
unsigned long minor_num)
{
struct inode_val *temp;
-
+ struct inode_val *e;
+
/* Create new inode record. */
temp = (struct inode_val *) xmalloc (sizeof (struct inode_val));
temp->inode = node_num;
@@ -751,39 +736,12 @@ add_inode (unsigned long node_num, char *file_name, unsigned long major_num,
temp->minor_num = minor_num;
temp->file_name = xstrdup (file_name);
- /* Do we have to increase the size of (or initially allocate)
- the hash table? */
- if (hash_num == hash_size || hash_table == NULL)
- {
- struct inode_val **old_table; /* Pointer to old table. */
- int i; /* Index for re-insert loop. */
-
- /* Save old table. */
- old_table = hash_table;
- if (old_table == NULL)
- hash_num = 0;
-
- /* Calculate new size of table and allocate it.
- Sequence of table sizes is 47, 97, 197, 397, 797, 1597, 3197, 6397 ...
- where 3197 and most of the sizes after 6397 are not prime. The other
- numbers listed are prime. */
- hash_size = 2 * hash_size + 3;
- hash_table = (struct inode_val **)
- xmalloc (hash_size * sizeof (struct inode_val *));
- bzero (hash_table, hash_size * sizeof (struct inode_val *));
-
- /* Insert the values from the old table into the new table. */
- for (i = 0; i < hash_num; i++)
- hash_insert (old_table[i]);
-
- if (old_table != NULL)
- free (old_table);
- }
-
- /* Insert the new record and increment the count of elements in the
- hash table. */
- hash_insert (temp);
- hash_num++;
+ if (!((hash_table
+ || (hash_table = hash_initialize (0, 0, inode_val_hasher,
+ inode_val_compare, 0)))
+ && (e = hash_insert (hash_table, temp))))
+ xalloc_die ();
+ /* FIXME: e is not used */
}
@@ -800,14 +758,14 @@ open_archive (char *file)
copy_in = process_copy_in;
if (copy_function == copy_in)
- fd = rmtopen (file, O_RDONLY | O_BINARY, 0666, rsh_command_option);
+ fd = rmtopen (file, O_RDONLY | O_BINARY, MODE_RW, rsh_command_option);
else
{
if (!append_flag)
- fd = rmtopen (file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666,
+ fd = rmtopen (file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, MODE_RW,
rsh_command_option);
else
- fd = rmtopen (file, O_RDWR | O_BINARY, 0666, rsh_command_option);
+ fd = rmtopen (file, O_RDWR | O_BINARY, MODE_RW, rsh_command_option);
}
return fd;
@@ -887,7 +845,7 @@ get_next_reel (int tape_des)
tape_des = open_archive (archive_name);
if (tape_des == -1)
- error (1, errno, "%s", archive_name);
+ open_error (archive_name);
}
else
{
@@ -907,7 +865,7 @@ get_next_reel (int tape_des)
tape_des = open_archive (next_archive_name);
if (tape_des == -1)
- error (0, errno, "%s", next_archive_name);
+ open_error (next_archive_name);
}
while (tape_des < 0);
}
@@ -1003,9 +961,10 @@ umasked_symlink (char *name1, char *name2, int mode)
/* Take an input pathname and check it for CDF's. Insert an extra
`/' in the pathname after each "hidden" directory. If we add
- any `/'s, return a malloced string (which it will reuse for
- later calls so our caller doesn't have to worry about freeing
- the string) instead of the original input string. */
+ any `/'s, return a malloced string instead of the original input
+ string.
+ FIXME: This creates a memory leak.
+*/
char *
add_cdf_double_slashes (char *input_name)
@@ -1055,7 +1014,7 @@ add_cdf_double_slashes (char *input_name)
*p = '\0';
if ((*xstat) (input_name, &dir_stat) < 0)
{
- error (0, errno, "%s", input_name);
+ stat_error (input_name);
return input_name;
}
@@ -1081,7 +1040,7 @@ add_cdf_double_slashes (char *input_name)
*p = '\0';
if ((*xstat) (input_name, &dir_stat) < 0)
{
- error (0, errno, "%s", input_name);
+ stat_error (input_name);
return input_name;
}
*p = '/';
@@ -1109,7 +1068,7 @@ islastparentcdf (char *path)
int slash_count;
int length; /* Length of result, not including NUL. */
- slash = rindex (path, '/');
+ slash = strrchr (path, '/');
if (slash == 0)
return 0;
else
@@ -1131,9 +1090,6 @@ islastparentcdf (char *path)
#define DISKBLOCKSIZE (512)
-enum sparse_write_states { begin, in_zeros, not_in_zeros };
-
-
static int
buf_all_zeros (char *buf, int bufsize)
{
@@ -1151,7 +1107,7 @@ int delayed_seek_count = 0;
/* Write NBYTE bytes from BUF to remote tape connection FILDES.
Return the number of bytes written on success, -1 on error. */
-int
+static int
sparse_write (int fildes, char *buf, unsigned int nbyte)
{
int complete_block_count;
@@ -1162,7 +1118,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
int lseek_rc;
int write_rc;
int i;
- enum sparse_write_states state;
+ enum { begin, in_zeros, not_in_zeros } state;
complete_block_count = nbyte / DISKBLOCKSIZE;
leftover_bytes_count = nbyte % DISKBLOCKSIZE;
@@ -1192,6 +1148,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
}
buf += DISKBLOCKSIZE;
break;
+
case in_zeros :
if (buf_all_zeros (buf, DISKBLOCKSIZE))
{
@@ -1206,6 +1163,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
}
buf += DISKBLOCKSIZE;
break;
+
case not_in_zeros :
if (buf_all_zeros (buf, DISKBLOCKSIZE))
{
@@ -1228,6 +1186,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
case in_zeros :
delayed_seek_count = seek_count;
break;
+
case not_in_zeros :
write_rc = write (fildes, cur_write_start, write_count);
delayed_seek_count = 0;
@@ -1245,3 +1204,139 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
}
return nbyte;
}
+
+#define CPIO_UID(uid) (set_owner_flag ? set_owner : (uid))
+#define CPIO_GID(gid) (set_group_flag ? set_group : (gid))
+
+void
+stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st)
+{
+ hdr->c_dev_maj = major (st->st_dev);
+ hdr->c_dev_min = minor (st->st_dev);
+ hdr->c_ino = st->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. */
+ hdr->c_mode = (st->st_mode & 07777);
+ if (S_ISREG (st->st_mode))
+ hdr->c_mode |= CP_IFREG;
+ else if (S_ISDIR (st->st_mode))
+ hdr->c_mode |= CP_IFDIR;
+#ifdef S_ISBLK
+ else if (S_ISBLK (st->st_mode))
+ hdr->c_mode |= CP_IFBLK;
+#endif
+#ifdef S_ISCHR
+ else if (S_ISCHR (st->st_mode))
+ hdr->c_mode |= CP_IFCHR;
+#endif
+#ifdef S_ISFIFO
+ else if (S_ISFIFO (st->st_mode))
+ hdr->c_mode |= CP_IFIFO;
+#endif
+#ifdef S_ISLNK
+ else if (S_ISLNK (st->st_mode))
+ hdr->c_mode |= CP_IFLNK;
+#endif
+#ifdef S_ISSOCK
+ else if (S_ISSOCK (st->st_mode))
+ hdr->c_mode |= CP_IFSOCK;
+#endif
+#ifdef S_ISNWK
+ else if (S_ISNWK (st->st_mode))
+ hdr->c_mode |= CP_IFNWK;
+#endif
+ hdr->c_uid = CPIO_UID (st->st_uid);
+ hdr->c_gid = CPIO_GID (st->st_gid);
+ hdr->c_nlink = st->st_nlink;
+ hdr->c_rdev_maj = major (st->st_rdev);
+ hdr->c_rdev_min = minor (st->st_rdev);
+ hdr->c_mtime = st->st_mtime;
+ hdr->c_filesize = st->st_size;
+ hdr->c_chksum = 0;
+ hdr->c_tar_linkname = NULL;
+}
+
+#ifndef HAVE_FCHOWN
+# define fchown(fd, uid, gid) (-1)
+#endif
+
+int
+fchown_or_chown (int fd, const char *name, uid_t uid, uid_t gid)
+{
+ if (HAVE_FCHOWN && fd != -1)
+ return fchown (fd, uid, gid);
+ else
+ return chown (name, uid, gid);
+}
+
+int
+fchmod_or_chmod (int fd, const char *name, mode_t mode)
+{
+ if (HAVE_FCHMOD && fd != -1)
+ return fchmod (fd, mode);
+ else
+ return chmod(name, mode);
+}
+
+void
+set_perms (int fd, struct cpio_file_stat *header)
+{
+ if (!no_chown_flag)
+ {
+ uid_t uid = CPIO_UID (header->c_uid);
+ gid_t gid = CPIO_GID (header->c_gid);
+ if ((fchown_or_chown (fd, header->c_name, uid, gid) < 0)
+ && errno != EPERM)
+ chown_error_details (header->c_name, uid, gid);
+ }
+ /* chown may have turned off some permissions we wanted. */
+ if (fchmod_or_chmod (fd, header->c_name, header->c_mode) < 0)
+ chmod_error_details (header->c_name, header->c_mode);
+#ifdef HPUX_CDF
+ if ((header->c_mode & CP_IFMT) && cdf_flag)
+ /* Once we "hide" the directory with the chmod(),
+ we have to refer to it using name+ instead of name. */
+ file_hdr->c_name [cdf_char] = '+';
+#endif
+ if (retain_time_flag)
+ set_file_times (fd, header->c_name, header->c_mtime, header->c_mtime);
+}
+
+void
+set_file_times (int fd,
+ const char *name, unsigned long atime, unsigned long mtime)
+{
+ struct timespec ts[2];
+
+ memset (&ts, 0, sizeof ts);
+
+ ts[0].tv_sec = atime;
+ ts[1].tv_sec = mtime;
+
+ /* Silently ignore EROFS because reading the file won't have upset its
+ timestamp if it's on a read-only filesystem. */
+ if (gl_futimens (fd, name, ts) < 0 && errno != EROFS)
+ utime_error (name);
+}
+
+/* Do we have to ignore absolute paths, and if so, does the filename
+ have an absolute path? */
+void
+cpio_safer_name_suffix (char *name, bool link_target, bool absolute_names,
+ bool strip_leading_dots)
+{
+ char *p = safer_name_suffix (name, link_target, absolute_names);
+ if (strip_leading_dots && strcmp (p, "./"))
+ /* strip leading `./' from the filename. */
+ while (*p == '.' && *(p + 1) == '/')
+ {
+ ++p;
+ while (*p == '/')
+ ++p;
+ }
+ if (p != name)
+ memmove (name, p, (size_t)(strlen (p) + 1));
+}
+