Import heavily trimmed gnu cpio-2.8.

(2.9 switched to gpl3 a few weeks later)
This commit is contained in:
peter 2008-07-10 00:52:03 +00:00
parent 43c61ec889
commit 6ae22f7302
98 changed files with 7554 additions and 3319 deletions

1454
ABOUT-NLS

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Version 2, June 1991 Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc. 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 Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software 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. Also add information on how to contact you by electronic and paper mail.

384
ChangeLog
View File

@ -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> 2004-12-20 Sergey Poznyakoff <gray@Mirddin.farlep.net>
Released version 2.6. Sources up to this point are tagged Released version 2.6. Sources up to this point are tagged

65
INSTALL
View File

@ -1,8 +1,8 @@
Installation Instructions Installation Instructions
************************* *************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
Software Foundation, Inc. 2006 Free Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it. unlimited permission to copy, distribute and modify it.
@ -10,7 +10,10 @@ unlimited permission to copy, distribute and modify it.
Basic Installation 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 The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses 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' It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves 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 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 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 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. may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need `configure' by a program called `autoconf'. You need `configure.ac' if
`configure.ac' if you want to change it or regenerate `configure' using you want to change it or regenerate `configure' using a newer version
a newer version of `autoconf'. of `autoconf'.
The simplest way to compile this package is: The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type 1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're `./configure' to configure the package for your system.
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some Running `configure' might take a while. While running, it prints
messages telling which features it is checking for. some messages telling which features it is checking for.
2. Type `make' to compile the package. 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 by setting variables in the command line or in the environment. Here
is an example: is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details. *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 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 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 own directory. To do this, you can use GNU `make'. `cd' to the
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH' With a non-GNU `make', it is safer to compile the package for one
variable, you have to compile the package for one architecture at a architecture at a time in the source code directory. After you have
time in the source code directory. After you have installed the installed the package for one architecture, use `make distclean' before
package for one architecture, use `make distclean' before reconfiguring reconfiguring for another architecture.
for another architecture.
Installation Names Installation Names
================== ==================
By default, `make install' will install the package's files in By default, `make install' installs the package's commands under
`/usr/local/bin', `/usr/local/man', etc. You can specify an `/usr/local/bin', include files under `/usr/local/include', etc. You
installation prefix other than `/usr/local' by giving `configure' the can specify an installation prefix other than `/usr/local' by giving
option `--prefix=PREFIX'. `configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PREFIX', the package will pass the option `--exec-prefix=PREFIX' to `configure', the package uses
use PREFIX as the prefix for installing programs and libraries. PREFIX as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix. Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular 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. need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should 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. produce code for.
If you want to _use_ a cross compiler, that generates code for a 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 ./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). overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation `configure' Invocation
====================== ======================

38
NEWS
View File

@ -1,10 +1,36 @@
GNU cpio NEWS -- history of user-visible changes. 2004-12-20 GNU cpio NEWS -- history of user-visible changes. 2007-06-08
Copyright (C) 2003, 2004 Free Software Foundation, Inc. Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
See the end of file for copying conditions. See the end of file for copying conditions.
Please send cpio bug reports to <bug-cpio@gnu.org>. 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 * Added NLS support
@ -107,7 +133,7 @@ multiple links and of multi-volume archives on floppy disks.
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright information: 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 Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the 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: Local variables:
mode: outline mode: outline
paragraph-separate: "[ ]*$" 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: end:

8
THANKS
View File

@ -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 reporting problems, suggesting various improvements or submitting actual
code. Help us keep it complete and exempt of errors. 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> Matthew Braithwaite <mab@cnet.com>
Mike Frysinger <vapier@gentoo.org>
Mitsuru Chinen <mchinen@yamato.ibm.com> Mitsuru Chinen <mchinen@yamato.ibm.com>
Holger Fleischmann <holger_fleischmann@mra.man.de> Peter Vrabec <pvrabec@redhat.com>

357
TODO
View File

@ -1,54 +1,21 @@
Following is the list of cpio-related reports to bug-gnu-utils. 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 Many of them appear to be fixed, but quite a number of them is
probably still waiting for being handled. The list is sorted probably still waiting for being handled. The list is divided
in reverse chronological order. into two parts, the messages are in somehow arbitrary order.
4. copyin.c cpio probably questions/rfc (score: 35) * Bug reports
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) ** cpio -d bug (fwd) (score: 47)
will be able to read/write cpio format (only ascii). Thus i am Author: Christian Smith <csmith@micromuse.com>
separating some of cpio structures into libcpio. I've been Date: Wed, 14 Nov 2001 02:06:46 +0000 (GMT)
going through cop This was bounced from bug-cpio@bogus.example.com I guess that
/archive/html/bug-gnu-utils/2003-06/msg00422.html (5,430 bytes) 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)
5. RE: Problem when building on HP-UX 11i(11.11) (score: 4) ** bug in cpio with tapechange in copy-in-mode (score: 34)
Author: "Leon Strydom" <leon.strydom@tasima.co.za>
Date: Thu, 13 Mar 2003 09:10:02 +0200
Hi Bob, I got it to compile, thanks. The reason why I had to
try GNU-Tar is because of the 2GB file size limit problems:
Here are the errors I got: With TAR(hp-ux 11i tar): CMD: tar
cvf backup.tar /a
/archive/html/bug-gnu-utils/2003-03/msg00106.html (5,191 bytes)
6. cpio - large file support (score: 35)
Author: "Keith Ansell" <keitha@edp.fastfreenet.com>
Date: Tue, 4 Mar 2003 16:24:37 -0000
Can you help. I need to archive a large database, this will
create a cpio file greater than 2 Gigabytes. Have you added
large file support to the build of cpio. Regards Keith
Ansell.....
/archive/html/bug-gnu-utils/2003-03/msg00024.html (4,329 bytes)
7. cpio-2.5 typos (score: 36)
Author: Thomas Klausner <wiz@danbala.ifoer.tuwien.ac.at>
Date: Sat, 21 Dec 2002 23:53:38 +0100
In cpio-2.5, in cpio.texi (and thus cpio.1) and main.c the word
'compatibility' is misspelled as 'compatability'. Please fix,
thanks. Thomas -- Thomas Klausner - wiz@bogus.example.com What
is wanted
/archive/html/bug-gnu-utils/2002-12/msg00200.html (3,783 bytes)
9. Re: bug in cpio with tapechange in copy-in-mode (score: 46)
Author: Paul Eggert <eggert@twinsun.com>
Date: Mon, 5 Aug 2002 12:28:33 -0700 (PDT)
Thanks for your bug report. Can you please verify that the bug
still exists in the latest CPIO version
<ftp://ftp.gnu.org/gnu/cpio/cpio-2.5.tar.gz>, and if so, please
send a patch to <bug-cpio@bogus.
/archive/html/bug-gnu-utils/2002-08/msg00127.html (4,275 bytes)
10. bug in cpio with tapechange in copy-in-mode (score: 34)
Author: Bernd =?ISO-8859-1?Q?Sch=FCler?= Author: Bernd =?ISO-8859-1?Q?Sch=FCler?=
<b.schueler@eckert-buerotechnik.de> <b.schueler@eckert-buerotechnik.de>
Date: 05 Aug 2002 18:37:56 +0200 Date: 05 Aug 2002 18:37:56 +0200
@ -58,15 +25,7 @@ in reverse chronological order.
sure, if the pr sure, if the pr
/archive/html/bug-gnu-utils/2002-08/msg00122.html (4,518 bytes) /archive/html/bug-gnu-utils/2002-08/msg00122.html (4,518 bytes)
11. Re: CPIO Bug ? (score: 36) ** Re: bug in cpio? (score: 40)
Author: Albert Chin <bug-gnu-utils@lists.thewrittenword.com>
Date: Thu, 4 Jul 2002 19:31:04 -0500
I think the default CPIO format understands only 16-bit inodes.
Look at the -H option. '-H newc' should work better for you. --
albert chin (china@bogus.example.com)
/archive/html/bug-gnu-utils/2002-07/msg00091.html (4,286 bytes)
14. Re: bug in cpio? (score: 40)
Author: kasal@matsrv.math.cas.cz (Stepan Kasal) Author: kasal@matsrv.math.cas.cz (Stepan Kasal)
Date: Thu, 13 Jun 2002 07:44:14 +0000 (UTC) Date: Thu, 13 Jun 2002 07:44:14 +0000 (UTC)
Hallo, the following option should help: -d, --make-directories Hallo, the following option should help: -d, --make-directories
@ -75,44 +34,7 @@ in reverse chronological order.
/home/kasal/tmp/db /home/kasal/tmp/db
/archive/html/bug-gnu-utils/2002-06/msg00306.html (4,862 bytes) /archive/html/bug-gnu-utils/2002-06/msg00306.html (4,862 bytes)
15. bug in cpio? (score: 34) ** cpio 2.4.2 bug? (score: 40)
Author: "Jeff Holt" <jeff.holt@hotsos.com>
Date: Wed, 12 Jun 2002 14:07:59 -0500
According to the man page, I should be able to extract an
absolute pathname from an archive and have the file created
relative to the current directory (by removing the leading
&#8216;/&#8217;).<o:p>
/archive/html/bug-gnu-utils/2002-06/msg00296.html (5,331 bytes)
16. CPIO Bug ? (score: 35)
Author: =?iso-8859-1?Q?Gr=E9goire_Fiot?=
<gfiot@eiffageconstruction.fr>
Date: Tue, 14 May 2002 17:01:18 +0200
Hello, We ve got a problem here using cpio: many "troncating
inode number" appear during the process: cpio -ocv Is that a
real problem? Does it corrupt files? Well.. what does that
mean? We have look
/archive/html/bug-gnu-utils/2002-05/msg00333.html (3,855 bytes)
23. [cpio texinfo] typo (score: 2)
Author: fabrice bauzac <fabrice.bauzac@wanadoo.fr>
Date: Tue, 7 May 2002 16:37:28 +0200
Good afternoon, There is a typo in the Texinfo documentation of
GNU cpio, node "Copy-in mode": [--format=format]
[--owner=[user][:.][group]] [--no- preserve-owner]
[--message=message] [--help] [--ver
/archive/html/bug-gnu-utils/2002-05/msg00153.html (4,040 bytes)
26. cpio: memory exhausted (score: 43)
Author: Thomas McLaughlin <tamm@scotlegal.com>
Date: Thu, 18 Apr 2002 09:51:18 +0100
This is probably not the place for my query, but I have
exhausted other avenues and would be glad of some help. I can't
work out what's going on with my nightly cpio backup. If I do:
cd / find . -pri
/archive/html/bug-gnu-utils/2002-04/msg00406.html (4,988 bytes)
30. cpio 2.4.2 bug? (score: 40)
Author: "H.J. Thomassen" <H.J.Thomassen@ATComputing.nl> Author: "H.J. Thomassen" <H.J.Thomassen@ATComputing.nl>
Date: Thu, 10 Jan 2002 18:09:10 +0100 (CET) Date: Thu, 10 Jan 2002 18:09:10 +0100 (CET)
Hello, We use GNU-cpio 2.4.2 and have the following problem: 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 hardlinks to the same i-node. I make a crc-cpio archive with
both files; th both files; th
/archive/html/bug-gnu-utils/2002-01/msg00161.html (5,624 bytes) /archive/html/bug-gnu-utils/2002-01/msg00161.html (5,624 bytes)
32. GNU cpio suggestion (score: 42) ** These two seem to be related:
Author: "H.J.Thomassen" <hjt@ATComputing.nl> *** cpio copy-in and multiply-linked files (score: 35)
Date: Mon, 17 Dec 2001 11:27:11 +0100
Re: suggestion for GNU-cpio extension (plus reference
implementation) We use cpio for our backup purposes. The backup
is started automatically in the middle of the night. To chase
away all users we d
/archive/html/bug-gnu-utils/2001-12/msg00244.html (7,474 bytes)
35. GNU cpio compile problem (score: 34)
Author: Daniel Savard <dsavard@videotron.ca>
Date: Wed, 14 Nov 2001 12:43:11 -0500
Hi, I am trying to make the GNU cpio utility (version 2.4.2)
using the gcc 3.0.2 compiler. The make failed on the userspec.c
file compilation. I then tried to compile with gcc 2.95.3 with
the followi
/archive/html/bug-gnu-utils/2001-11/msg00180.html (5,518 bytes)
36. cpio -d bug (fwd) (score: 47)
Author: Christian Smith <csmith@micromuse.com>
Date: Wed, 14 Nov 2001 02:06:46 +0000 (GMT)
This was bounced from bug-cpio@bogus.example.com I guess that
isn't set up yet. -- /"\ \ / ASCII RIBBON CAMPAIGN - AGAINST
HTML MAIL X - AGAINST MS ATTACHMENTS / \ $ cpio --version GNU
cpio version 2
/archive/html/bug-gnu-utils/2001-11/msg00170.html (4,548 bytes)
38. [cpio] man page enhancement: a Example section ? (score: 5)
Author: Yannick Patois <patois@calvix.org>
Date: Wed, 24 Oct 2001 12:48:33 +0200 (CEST)
Hello, I seldom use cpio (as I think many people) and only had
to use it once or twice. IMHA, would be good to have a small
section with an example of most often performed actions
(creating an archiv
/archive/html/bug-gnu-utils/2001-10/msg00270.html (4,336 bytes)
39. Patch to cpio to enable verbose *skipping* of files (score: 40)
Author: Tomas Pospisek <tpo@sourcepole.ch>
Date: Mon, 8 Oct 2001 13:54:14 +0200 (CEST)
This patch enables cpio to be verbose about the files that it
does not copy, which is very handy for seeing cpio's progress
through a tape or simply for debuging. The patch along with a
Debian packag
/archive/html/bug-gnu-utils/2001-10/msg00083.html (4,548 bytes)
40. cpio-2.4.2 patch (score: 39)
Author: Alex Efros <powerman@sky.net.ua>
Date: Wed, 29 Aug 2001 07:36:31 +0300 (EEST)
Hi. Linux-2.4.9, GCC-3.0, GLIBC-2.2.4, cpio-2.4.2. Compile-time
errors: --cut-- gcc -c -DRETSIGTYPE=void -DHAVE_SYS_MTIO_H=1
-DHAVE_NETDB_H=1 -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1
-DHAVE_STRING_H=1 -DHA
/archive/html/bug-gnu-utils/2001-08/msg00264.html (5,259 bytes)
41. cpio copy-in and multiply-linked files (score: 35)
Author: Chris Jaeger <cjaeger@ensim.com> Author: Chris Jaeger <cjaeger@ensim.com>
Date: Tue, 07 Aug 2001 23:46:04 -0700 Date: Tue, 07 Aug 2001 23:46:04 -0700
Hi, I was wondering whether it was a bug or a feature that GNU 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 due to th
/archive/html/bug-gnu-utils/2001-08/msg00074.html (4,142 bytes) /archive/html/bug-gnu-utils/2001-08/msg00074.html (4,142 bytes)
42. Re: minor problems with slackware-current (score: 7) *** (no subject) (score: 2)
Author: Cezary Sliwa <sliwa@cft.edu.pl>
Date: Wed, 1 Aug 2001 10:43:37 +0200
"cpio --sparse" corrupts data. A fix attached. C.S. Attachment:
cpio-2.4.2-sparse.diff Description: Text document
/archive/html/bug-gnu-utils/2001-08/msg00000.html (3,989 bytes)
43. (no subject) (score: 2)
Author: brian@debian.org (Brian Mays) Author: brian@debian.org (Brian Mays)
Date: Sat, 07 Jul 2001 16:35:13 -0400 Date: Sat, 07 Jul 2001 16:35:13 -0400
When hard-linked files (along with many other files) are When hard-linked files (along with many other files) are
@ -200,69 +62,24 @@ in reverse chronological order.
the same set of fil the same set of fil
/archive/html/bug-gnu-utils/2001-07/msg00080.html (5,666 bytes) /archive/html/bug-gnu-utils/2001-07/msg00080.html (5,666 bytes)
44. gnu cpio and files over 2G (score: 37) ** These too:
Author: J.S.Peatfield@damtp.cam.ac.uk
Date: Wed, 2 May 2001 06:28:18 +0100 *** Re: minor problems with slackware-current (score: 7)
As an increasing number of opertaing systems now support files Author: Cezary Sliwa <sliwa@cft.edu.pl>
over 2G I took a look at the cpio (2.4.2) source to see how Date: Wed, 1 Aug 2001 10:43:37 +0200
hard it would be to make it cope, and was slightly shocked at "cpio --sparse" corrupts data. A fix attached. C.S. Attachment:
the number of cpio-2.4.2-sparse.diff Description: Text document
/archive/html/bug-gnu-utils/2001-05/msg00010.html (4,802 bytes) /archive/html/bug-gnu-utils/2001-08/msg00000.html (3,989 bytes)
45. cpio suggestion + patch (score: 38) *** cpio --sparse (score: 34)
Author: Taylor Gautier <tgautier@s8.com>
Date: Fri, 20 Apr 2001 09:40:05 -0700
I have a suggestion for cpio. The suggestion is to make it copy
files into a temporary name and then rename the file as the
last operation. Since UNIX filesystems are supposed to
gaurantee atomicity
/archive/html/bug-gnu-utils/2001-04/msg00169.html (10,674
bytes)
46. [cpio 2.4.2] rmt build fails (score: 8)
Author: Gert <n8w8@n8w8.wox.org>
Date: Thu, 29 Mar 2001 21:28:52 +0200 (CEST)
Hi, The cpio 2.4.2 rmt tool fails to build on my system. I run
the following software: - Linux 2.4.2 - GCC 2.95.2 - GNU Make
3.79.1 - GNU ld 2.10 (with BFD 2.10) - glibc 2.1.3 The build
fails like th
/archive/html/bug-gnu-utils/2001-03/msg00262.html (5,498 bytes)
47. cpio --sparse (score: 34)
Author: Cezary Sliwa <sliwa@cft.edu.pl> Author: Cezary Sliwa <sliwa@cft.edu.pl>
Date: Mon, 26 Mar 2001 10:43:34 +0200 (CEST) Date: Mon, 26 Mar 2001 10:43:34 +0200 (CEST)
the '--sparse' option of gnu cpio causes data corruption the '--sparse' option of gnu cpio causes data corruption
(blocks of zeros are lost or appended to other files). C.S. (blocks of zeros are lost or appended to other files). C.S.
/archive/html/bug-gnu-utils/2001-03/msg00235.html (3,671 bytes) /archive/html/bug-gnu-utils/2001-03/msg00235.html (3,671 bytes)
49. Re: bug with gnu cpio 2.4.2 (score: 38) ** And these too
Author: Hans-Bernhard Broeker <broeker@physik.rwth-aachen.de> *** cpio-2.4.2: data corruption bug (score: 35)
Date: 6 Mar 2001 15:19:34 GMT
This would happen if cpio want to do any user interaction (ask
for the next tape cartridge, because the current one is full,
e.g.). Cron jobs don't have access to a terminal (/dev/tty), so
this will
/archive/html/bug-gnu-utils/2001-03/msg00029.html (5,062 bytes)
50. bug with gnu cpio 2.4.2 (score: 37)
Author: dominique.bieber@sagem.com
Date: Tue, 6 Mar 2001 12:27:14 +0100
Hi, I have a problem using cpio with a Red Hat 6.2 whith a
2.2.14-5.0smp kernel. The backup device is a HP DAT DDS4 20/40
with the right cartridge. The cpio is launched by the cron.
During the backup
/archive/html/bug-gnu-utils/2001-03/msg00024.html (4,315 bytes)
52. [PATCH] cpio 2.4.2 does not compile with libc 2.2, gcc 2.95
(score: 38)
Author: "John Fremlin" <chief@bandits.org>
Date: 11 Feb 2001 22:19:09 +0000
In fact it violates the GNU coding standards by declaring stuff
when it shouldn't. Tsk, tsk. Attachment: cpio-2.4.2-build.patch
Description: Text Data -- http://www.penguinpowered.com/~vii
/archive/html/bug-gnu-utils/2001-02/msg00065.html (4,169 bytes)
53. cpio-2.4.2: data corruption bug (score: 35)
Author: Todd Kelley <toddk@oeone.com> Author: Todd Kelley <toddk@oeone.com>
Date: Fri, 09 Feb 2001 17:00:06 -0500 Date: Fri, 09 Feb 2001 17:00:06 -0500
Hello, Recently at OEone we fixed a bug in GNU cpio-2.4.2: When 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 corrupted. The crc do
/archive/html/bug-gnu-utils/2001-02/msg00062.html (4,297 bytes) /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) 39)
Author: Scott Larson <scowl@plaza.ds.adp.com> Author: Scott Larson <scowl@plaza.ds.adp.com>
Date: Thu, 11 Jan 2001 13:15:52 -0800 Date: Thu, 11 Jan 2001 13:15:52 -0800
@ -281,7 +107,7 @@ in reverse chronological order.
tape) after rea tape) after rea
/archive/html/bug-gnu-utils/2001-01/msg00087.html (4,264 bytes) /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) (score: 35)
Author: "Dan Jacobson" <jidanni@kimo.FiXcomTHiS.tw> Author: "Dan Jacobson" <jidanni@kimo.FiXcomTHiS.tw>
Date: Tue, 26 Dec 2000 07:38:53 +0800 Date: Tue, 26 Dec 2000 07:38:53 +0800
@ -291,66 +117,43 @@ in reverse chronological order.
http://www.geocities.com/jidanni http://www.geocities.com/jidanni
/archive/html/bug-gnu-utils/2000-12/msg00143.html (4,084 bytes) /archive/html/bug-gnu-utils/2000-12/msg00143.html (4,084 bytes)
56. cpio-2.4.2 compilation problems (score: 34) * Suggestions
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 ** GNU cpio suggestion (score: 42)
running linux-2.2.17, glibc-2.1.3 and gcc 2.95.2. The errors I Author: "H.J.Thomassen" <hjt@ATComputing.nl>
received were mostly due to the source files re-declaring Date: Mon, 17 Dec 2001 11:27:11 +0100
things unconditionall Re: suggestion for GNU-cpio extension (plus reference
/archive/html/bug-gnu-utils/2000-12/msg00109.html (5,782 bytes) 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)
58. cpio-2.4.2 & glibc-2.* (score: 46) ** cpio suggestion + patch (score: 38)
Author: Florian Wunderlich <fwunderlich@devbrain.de> Author: Taylor Gautier <tgautier@s8.com>
Date: Mon, 18 Dec 2000 16:25:00 +0100 Date: Fri, 20 Apr 2001 09:40:05 -0700
I still do not see a new version of cpio or at least extra I have a suggestion for cpio. The suggestion is to make it copy
patches that fix it so it works with the glibc. Thus, here is a files into a temporary name and then rename the file as the
simple patch to make it compile with glibc: diff -u last operation. Since UNIX filesystems are supposed to
cpio-2.4.2-old/rmt.c cpi gaurantee atomicity
/archive/html/bug-gnu-utils/2000-12/msg00098.html (4,846 bytes) /archive/html/bug-gnu-utils/2001-04/msg00169.html (10,674
bytes)
60. cpio-2.4.2 signed-unsigned int disagreement with malloc (score: ** [cpio] man page enhancement: a Example section ? (score: 5)
39) Author: Yannick Patois <patois@calvix.org>
Author: Antonomasia <ant@notatla.demon.co.uk> Date: Wed, 24 Oct 2001 12:48:33 +0200 (CEST)
Date: Mon, 27 Nov 2000 07:05:01 GMT Hello, I seldom use cpio (as I think many people) and only had
copyin.c: 534 link_name = (char *) xmalloc ((unsigned int) to use it once or twice. IMHA, would be good to have a small
file_hdr.c_filesize + 1); 535 link_name[file_hdr.c_filesize] = section with an example of most often performed actions
'\0'; file_hdr.c_filesize can be a large negative number as (creating an archiv
seen here then th /archive/html/bug-gnu-utils/2001-10/msg00270.html (4,336 bytes)
/archive/html/bug-gnu-utils/2000-11/msg00171.html (4,718 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)
61. gnu CPIO (score: 38)
Author: Clark Cooper <Clark.Cooper@vc3.com>
Date: Mon, 13 Nov 2000 13:21:07 -0500 (EST)
The gnu version of CPIO appears to send all output to stderr.
Take for instance a need to have the list of files copied and
any errors separated as should be produced by the following:
find . -print
/archive/html/bug-gnu-utils/2000-11/msg00089.html (3,903 bytes)
62. Desire enhancement to GNU cpio 2.4.2 (score: 35)
Author: Dave Dykstra <dwd@bell-labs.com>
Date: Mon, 13 Nov 2000 10:24:56 -0600
I have a new GNU/Linux system with large disks on which I need
to generate cpio files for many different systems including
older ones that don't support the "newc" format, only the "odc"
format. The
/archive/html/bug-gnu-utils/2000-11/msg00087.html (5,115 bytes)
65. cpio pass-through can corrupt files (score: 36)
Author: "Parrott, Jeff" <Jeff.Parrott@sea.siemens.com>
Date: Mon, 16 Oct 2000 13:32:57 -0400
I have seen corrupted files as a result of using the
pass-through option in cpio. The corruption occurs when
active/in-use (and growing) files are being copied. The problem
is that the file size has
/archive/html/bug-gnu-utils/2000-10/msg00087.html (4,974 bytes)
66. [Bug-gnu-utils] A small problem with cpio (score: 36)
Author: Chris Hall <Chris@clapham.org>
Date: Fri, 15 Sep 2000 11:05:56 +0100
Hi, I'm running cpio 2.4.2 on AIX 4.3.3 and have a problem with
very large files, I get this output when running the command: $
ls -l total 2867988 drwxrwxrwx 2 root sys 512 Sep 14 17:05
chris/ -rw-r
/archive/html/bug-gnu-utils/2000-09/msg00004.html (4,481 bytes)

View File

@ -3,94 +3,70 @@
@setfilename cpio.info @setfilename cpio.info
@settitle cpio @settitle cpio
@setchapternewpage off @setchapternewpage off
@set VERSION GNU cpio 2.5
@set RELEASEDATE June 2002
@c %**end of header @c %**end of header
@ifinfo @dircategory Archiving
@format @direntry
START-INFO-DIR-ENTRY * Cpio: (cpio). Copy-in-copy-out archiver to tape or disk.
* cpio: (cpio). Making tape (or disk) archives. @end direntry
END-INFO-DIR-ENTRY
@end format
@end ifinfo
@ifinfo @include version.texi
This file documents @value{VERSION}.
Copyright (C) 1995, 2001, 2002 Free Software Foundation, Inc. @copying
This manual documents GNU cpio (version @value{VERSION}, @value{UPDATED}).
Permission is granted to make and distribute verbatim copies of Copyright @copyright{} 1995, 2001, 2002, 2004 Free Software Foundation, Inc.
this manual provided the copyright notice and this permission notice @sp 1
are preserved on all copies. @quotation
Permission is granted to copy, distribute and/or modify this document
@ignore under the terms of the GNU Free Documentation License, Version 1.2 or
Permission is granted to process this file through TeX and print the any later version published by the Free Software Foundation; with no
results, provided the printed document carries copying permission Invariant Sections, with the Front-Cover texts being ``A GNU Manual'',
notice identical to this one except for the removal of this paragraph 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 @titlepage
@title GNU CPIO @title GNU CPIO
@subtitle @value{VERSION} @value{RELEASEDATE} @subtitle @value{VERSION} @value{UPDATED}
@author by Robert Carleton @author by Robert Carleton
@c copyright page @c copyright page
@page @page
@vskip 0pt plus 1filll @vskip 0pt plus 1filll
Copyright @copyright{} 1995, 2001, 2002 Free Software Foundation, Inc. @insertcopying
@sp 2
This is the first edition of the GNU cpio documentation,@*
and is consistent with @value{VERSION}.@*
@sp 2 @sp 2
Published by the Free Software Foundation @* Published by the Free Software Foundation @*
59 Temple Place - Suite 330, @* 51 Franklin Street, Fifth Floor, @*
Boston, MA 02111-1307, USA @* Boston, MA 02110-1301, USA @*
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation
approved by the Free Software Foundation.
@end titlepage @end titlepage
@ifinfo
@node Top, Introduction, (dir), (dir) @node Top, Introduction, (dir), (dir)
@comment node-name, next, previous, up @comment node-name, next, previous, up
@ifinfo
@top @top
GNU cpio is a tool for creating and extracting archives, or copying 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 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 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 @menu
* Introduction:: * Introduction::
* Tutorial:: Getting started. * Tutorial:: Getting started.
* Invoking `cpio':: How to invoke `cpio'. * Invoking cpio:: How to invoke @command{cpio}.
* Media:: Using tapes and other archive media. * Media:: Using tapes and other archive media.
* Reports:: Reporting bugs or suggestions
* Concept Index:: Concept index. * Concept Index:: Concept index.
@detailmenu
--- The Detailed Node Listing --- --- The Detailed Node Listing ---
Invoking cpio Invoking cpio
@ -99,9 +75,9 @@ Invoking cpio
* Copy-in mode:: * Copy-in mode::
* Copy-pass mode:: * Copy-pass mode::
* Options:: * Options::
@end menu
@end ifinfo @end detailmenu
@end menu
@node Introduction, Tutorial, Top, Top @node Introduction, Tutorial, Top, Top
@comment node-name, next, previous, up @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 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 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 default, cpio creates binary format archives, for compatibility with
older cpio programs. When extracting from archives, cpio automatically older cpio programs. When extracting from archives, cpio automatically
recognizes which kind of archive it is reading and can read archives recognizes which kind of archive it is reading and can read archives
created on machines with a different byte-order. 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 @comment node-name, next, previous, up
@chapter Tutorial @chapter Tutorial
@cindex creating a cpio archive @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 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 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 @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 to the standard input. In the following example you can see the
possibilities for archiving the contents of a single directory. 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 cartouche
@end example @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 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 separately on the command line. The @samp{>} redirects the cpio output
to the file @samp{directory.cpio}. 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 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} below and place them in the archive tree.cpio. Again the @option{-o}
creates an archive, and the @samp{-v} option shows you the name of the 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 `.' in 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 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 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 entries in a directory before printing the directory itself. This
limits the effects of restrictive directory permissions by printing the limits the effects of restrictive directory permissions by printing the
directory entries in a directory before the directory name itself. directory entries in a directory before the directory name itself.
@ -190,10 +166,10 @@ overwrite existing files unless you tell it to.
@end example @end example
This will retrieve the files archived in the file directory.cpio and This will retrieve the files archived in the file directory.cpio and
place them in the present directory. The @samp{-i} option extracts the place them in the present directory. The @option{-i} option extracts the
archive and the @samp{-v} shows the file names as they are extracted. 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 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 @example
@cartouche @cartouche
@ -223,13 +199,13 @@ argument. @xref{Copy-pass mode}.
The example shows copying the files of the present directory, and The example shows copying the files of the present directory, and
sub-directories to a new directory called new-dir. Some new options are sub-directories to a new directory called new-dir. Some new options are
the @samp{-print0} available with GNU find, combined with the the @option{-print0} available with GNU find, combined with the
@samp{--null} option of cpio. These two options act together to send @option{--null} option of cpio. These two options act together to send
file names between find and cpio, even if special characters are 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}. 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 @comment node-name, next, previous, up
@chapter Invoking cpio @chapter Invoking cpio
@cindex invoking cpio @cindex invoking cpio
@ -242,7 +218,7 @@ pass the files it finds to the directory @samp{new-dir}.
* Options:: * Options::
@end menu @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 @comment node-name, next, previous, up
@section Copy-out mode @section Copy-out mode
@ -264,7 +240,7 @@ cpio @{-o|--create@} [-0acvABLV] [-C bytes] [-H format]
< name-list [> archive] < name-list [> archive]
@end example @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 @comment node-name, next, previous, up
@section Copy-in mode @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 archive contents. It reads the archive from the standard input. Any
non-option command line arguments are shell globbing patterns; only non-option command line arguments are shell globbing patterns; only
files in the archive whose names match one or more of those patterns are 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 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 `/' 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 filename can match wildcards. If no patterns are given, all files are
extracted. @xref{Options}. extracted. @xref{Options}.
@ -288,11 +264,11 @@ cpio @{-i|--extract@} [-bcdfmnrtsuvBSV] [-C bytes] [-E file]
[--swap-halfwords] [--io-size=bytes] [--pattern-file=file] [--swap-halfwords] [--io-size=bytes] [--pattern-file=file]
[--format=format] [--owner=[user][:.][group]] [--format=format] [--owner=[user][:.][group]]
[--no-preserve-owner] [--message=message] [--help] [--version] [--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] [--rsh-command=command] [pattern...] [< archive]
@end example @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 @comment node-name, next, previous, up
@section Copy-pass mode @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 @comment node-name, next, previous, up
@section Options @section Options
@ -322,22 +298,26 @@ cpio @{-p|--pass-through@} [-0adlmuvLV] [-R [user][:.][group]]
@table @code @table @code
@item -0, --null @item -0
@itemx --null
Read a list of filenames terminated by a null character, instead of a Read a list of filenames terminated by a null character, instead of a
newline, so that files whose names contain newlines can be archived. newline, so that files whose names contain newlines can be archived.
GNU find is one way to produce a list of null-terminated filenames. 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. 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 Reset the access times of files after reading them, so
that it does not look like they have just been read. 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 Append to an existing archive. Only works in copy-out
mode. The archive must be a disk file specified with 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. 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 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 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 Set the I/O block size to 5120 bytes. Initially the
block size is 512 bytes. block size is 512 bytes.
@item --block-size=BLOCK-SIZE @item --block-size=@var{block-size}
Set the I/O block size to BLOCK-SIZE * 512 bytes. Set the I/O block size to @var{block-size} * 512 bytes.
@item -c @item -c
Use the old portable (ASCII) archive format. Use the old portable (ASCII) archive format.
@item -C IO-SIZE, --io-size=IO-SIZE @item -C @var{io-size}
Set the I/O block size to IO-SIZE bytes. @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. 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 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, 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 Only copy files that do not match any of the given
patterns. 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 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 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 with @samp{@var{hostname}:}, where @var{hostname} is the name or IP
`@@' to access the remote tape drive as that user, if you have address of the machine. The hostname can be preceded by a username and an
permission to do so (typically an entry in that user's `~/.rhosts' @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). file).
@item --force-local @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 local file even if it contains a colon, which would
ordinarily indicate a remote host name. ordinarily indicate a remote host name.
@item -H FORMAT, --format=FORMAT @item -H @var{format}
Use archive format FORMAT. The valid formats are listed below; the same @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 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 to automatically detect the archive format, and in copy-out mode is
@samp{bin}. @samp{bin}.
@ -417,39 +404,46 @@ The portable format used by HPUX's cpio (which stores device files
differently). differently).
@end table @end table
@item -i, --extract @item -i
@itemx --extract
Run in copy-in mode. Run in copy-in mode.
@xref{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 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 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 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 @item -k
Ignored; for compatibility with other versions of cpio. Ignored; for compatibility with other versions of cpio.
@item -l, --link @item -l
@itemx --link
Link files instead of copying them, when possible. 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 Copy the file that a symbolic link points to, rather than the symbolic
link itself. link itself.
@item -m, --preserve-modification-time @item -m
@itemx --preserve-modification-time
Retain previous file modification times when creating files. Retain previous file modification times when creating files.
@item -M MESSAGE, --message=MESSAGE @item -M @var{message}
Print MESSAGE when the end of a volume of the backup media (such as a @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 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). 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 Show numeric UID and GID instead of translating them into names when using the
@samp{--verbose option}. @option{--verbose} option.
@item --no-absolute-filenames @item --no-absolute-filenames
Create all files relative to the current directory in copy-in mode, even 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 on System V don't inadvertantly give away files. This option can be
used in copy-in mode and copy-pass mode used in copy-in mode and copy-pass mode
@item -o, --create @item -o
@itemx --create
Run in copy-out mode. Run in copy-out mode.
@xref{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 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 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 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 @item --only-verify-crc
Verify the CRC's of each file in the archive, when reading a CRC format Verify the CRC's of each file in the archive, when reading a CRC format
archive. Don't actually extract the files. archive. Don't actually extract the files.
@item -p, --pass-through @item -p
@itemx --pass-through
Run in copy-pass mode. Run in copy-pass mode.
@xref{Copy-pass mode}. @xref{Copy-pass mode}.
@item --quiet @item --quiet
Do not print the number of blocks copied. Do not print the number of blocks copied.
@item -r, --rename @item -r
@itemx --rename
Interactively rename files. Interactively rename files.
@item -R [user][:.][group], --owner [user][:.][group] @item -R @var{owner}
Set the ownership of all files created to the specified user and/or @itemx --owner @var{owner}
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 In copy-in and copy-pass mode, set the ownership of all files created
Notifies cpio that is should use COMMAND to communicate with remote 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. devices.
@item -s, --swap-bytes @item -s
Swap the bytes of each halfword (pair of bytes) in the files.This option @itemx --swap-bytes
Swap the bytes of each halfword (pair of bytes) in the files. This option
can be used in copy-in mode. 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 Swap the halfwords of each word (4 bytes) in the files. This option may
be used in copy-in mode. 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 Write files with large blocks of zeros as sparse files. This option is
used in copy-in and copy-pass modes. used in copy-in and copy-pass modes.
@item -t, --list @item -t
@itemx --list
Print a table of contents of the input. Print a table of contents of the input.
@item -u, --unconditional @item -u
@itemx --unconditional
Replace all files, without asking whether to replace Replace all files, without asking whether to replace
existing newer files with older files. existing newer files with older files.
@item -v, --verbose @item -v
List the files processed, or with @samp{-t}, give an @samp{ls -l} style @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 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 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 local system are replaced by the names that correspond locally to the
numeric UID and GID stored in the archive. numeric UID and GID stored in the archive.
@item -V --dot @item -V
Print a @kbd{.} for each file processed. @itemx --dot
Print a @samp{.} for each file processed.
@item --version @item --version
Print the cpio program version number and exit. Print the cpio program version number and exit.
@end table @end table
@node Media, Concept Index, Invoking `cpio', Top @node Media, Reports, Invoking cpio, Top
@comment node-name, next, previous, up @comment node-name, next, previous, up
@chapter Magnetic Media @chapter Magnetic Media
@cindex 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 a floppy disk to a filing cabinet using a magnet is probably not a good
idea. idea.
@node Reports, Concept Index, Media, Top
@chapter Reporting bugs or suggestions
@node Concept Index, , Media, Top It is possible you will encounter a bug in @command{cpio}.
If this happens, we would like to hear about it. As the purpose of bug
reporting is to improve software, please be sure to include maximum
information when reporting a bug. The information needed is:
@itemize @bullet
@item Version of the package you are using.
@item Compilation options used when configuring the package.
@item Conditions under which the bug appears.
@end itemize
Send your report to <bug-cpio@@gnu.org>. Allow us a couple of
days to answer.
@node Concept Index, , Reports, Top
@comment node-name, next, previous, up @comment node-name, next, previous, up
@unnumbered Concept Index @unnumbered Concept Index
@printindex cp @printindex cp

4
doc/version.texi Normal file
View File

@ -0,0 +1,4 @@
@set UPDATED 7 June 2007
@set UPDATED-MONTH June 2007
@set EDITION 2.8
@set VERSION 2.8

View File

@ -1,6 +1,6 @@
/* Memory allocation on the stack. /* 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. Foundation, Inc.
This program is free software; you can redistribute it and/or modify it 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 You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free Software 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. */ USA. */
/* When this file is included, it may be preceded only by preprocessor /* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
declarations. Thanks to AIX. Therefore we include it right after means there is a real alloca function. */
"config.h", not later. */ #ifndef _GL_ALLOCA_H
#define _GL_ALLOCA_H
#ifndef _ALLOCA_H
# define _ALLOCA_H
/* alloca (N) returns a pointer to N bytes of memory /* alloca (N) returns a pointer to N bytes of memory
allocated on the stack, which will last until the function returns. allocated on the stack, which will last until the function returns.
@ -36,19 +34,21 @@
request, the program just crashes. request, the program just crashes.
*/ */
#ifdef __GNUC__ #ifndef alloca
# define alloca __builtin_alloca # ifdef __GNUC__
#elif defined _AIX # define alloca __builtin_alloca
# define alloca __alloca # elif defined _AIX
#elif defined _MSC_VER # define alloca __alloca
# include <malloc.h> # elif defined _MSC_VER
# define alloca _alloca # include <malloc.h>
#else # define alloca _alloca
# include <stddef.h> # else
# ifdef __cplusplus # include <stddef.h>
# ifdef __cplusplus
extern "C" extern "C"
# endif # endif
void *alloca (size_t); void *alloca (size_t);
# endif
#endif #endif
#endif /* _ALLOCA_H */ #endif /* _GL_ALLOCA_H */

View File

@ -15,7 +15,7 @@
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 /* 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 bug-reporting address for the program. It will be printed by argp_help if

View File

@ -15,10 +15,10 @@
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifdef HAVE_CONFIG_H
#include <config.h> # include <config.h>
#endif #endif
#include <sysexits.h> #include <sysexits.h>

View File

@ -1,5 +1,5 @@
/* Word-wrapping and line-truncating streams /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 /* This package emulates glibc `line_wrap_stream' semantics for systems that
don't have that. */ don't have that. */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> # include <config.h>
#endif #endif
#include <stdlib.h> #include <stdlib.h>
@ -101,11 +101,10 @@ __argp_fmtstream_free (argp_fmtstream_t fs)
if (fs->p > fs->buf) if (fs->p > fs->buf)
{ {
#ifdef USE_IN_LIBIO #ifdef USE_IN_LIBIO
if (_IO_fwide (fs->stream, 0) > 0) __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); #else
else fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
#endif #endif
fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
} }
free (fs->buf); free (fs->buf);
free (fs); free (fs);
@ -247,9 +246,10 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
Oh well. Put it on an overlong line by itself. */ Oh well. Put it on an overlong line by itself. */
p = buf + (r + 1 - fs->point_col); p = buf + (r + 1 - fs->point_col);
/* Find the end of the long word. */ /* Find the end of the long word. */
do if (p < nl)
++p; do
while (p < nl && !isblank (*p)); ++p;
while (p < nl && !isblank (*p));
if (p == nl) if (p == nl)
{ {
/* It already ends a line. No fussing required. */ /* It already ends a line. No fussing required. */
@ -290,17 +290,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
else else
/* Output the first line so we can use the space. */ /* Output the first line so we can use the space. */
{ {
#ifdef USE_IN_LIBIO #ifdef _LIBC
if (_IO_fwide (fs->stream, 0) > 0) __fxprintf (fs->stream, "%.*s\n",
__fwprintf (fs->stream, L"%.*s\n", (int) (nl - fs->buf), fs->buf);
(int) (nl - fs->buf), fs->buf); #else
else if (nl > fs->buf)
fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
putc_unlocked ('\n', fs->stream);
#endif #endif
{
if (nl > fs->buf)
fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
putc_unlocked ('\n', fs->stream);
}
len += buf - fs->buf; len += buf - fs->buf;
nl = 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. */ /* Flush FS's buffer. */
__argp_fmtstream_update (fs); __argp_fmtstream_update (fs);
#ifdef USE_IN_LIBIO #ifdef _LIBC
if (_IO_fwide (fs->stream, 0) > 0) __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
{ wrote = fs->p - fs->buf;
__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); #else
wrote = fs->p - fs->buf; wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
}
else
#endif #endif
wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
if (wrote == fs->p - fs->buf) if (wrote == fs->p - fs->buf)
{ {
fs->p = fs->buf; fs->p = fs->buf;

View File

@ -1,5 +1,5 @@
/* Word-wrapping and line-truncating streams. /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 /* 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 don't have that. If the system does have it, it is just a wrapper for
@ -25,10 +25,6 @@
#ifndef _ARGP_FMTSTREAM_H #ifndef _ARGP_FMTSTREAM_H
#define _ARGP_FMTSTREAM_H #define _ARGP_FMTSTREAM_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -93,10 +89,6 @@ typedef FILE *argp_fmtstream_t;
#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */ #else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
/* Guess we have to define our own version. */ /* Guess we have to define our own version. */
#ifndef __const
#define __const const
#endif
struct argp_fmtstream 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 void argp_fmtstream_free (argp_fmtstream_t __fs);
extern ssize_t __argp_fmtstream_printf (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))); __attribute__ ((__format__ (printf, 2, 3)));
extern ssize_t argp_fmtstream_printf (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))); __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_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, 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, 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. */ /* Access macros for various bits of state. */
#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) #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_FS_EI size_t
__argp_fmtstream_write (argp_fmtstream_t __fs, __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)) 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_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); size_t __len = strlen (__str);
if (__len) if (__len)

View File

@ -15,10 +15,10 @@
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifdef HAVE_CONFIG_H
#include <config.h> # include <config.h>
#endif #endif
#define ARGP_FS_EI #define ARGP_FS_EI

View File

@ -1,5 +1,5 @@
/* Hierarchial argument parsing help output /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifndef _GNU_SOURCE
# define _GNU_SOURCE 1 # define _GNU_SOURCE 1
#endif #endif
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> # include <config.h>
#endif #endif
#include <alloca.h> #include <alloca.h>
@ -89,15 +89,15 @@ struct uparams
int dup_args_note; int dup_args_note;
/* Various output columns. */ /* Various output columns. */
int short_opt_col; int short_opt_col; /* column in which short options start */
int long_opt_col; int long_opt_col; /* column in which long options start */
int doc_opt_col; int doc_opt_col; /* column in which doc options start */
int opt_doc_col; int opt_doc_col; /* column in which option text starts */
int header_col; int header_col; /* column in which group headers are printed */
int usage_indent; int usage_indent; /* indentation of wrapped usage lines */
int rmargin; int rmargin; /* right margin used for wrapping */
int valid; /* True when the values in here are valid. */ int valid; /* True when the values in here are valid. */
}; };
/* This is a global variable, as user options are only ever read once. */ /* 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 } { 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 static void
fill_in_uparams (const struct argp_state *state) fill_in_uparams (const struct argp_state *state)
{ {
const char *var = getenv ("ARGP_HELP_FMT"); const char *var = getenv ("ARGP_HELP_FMT");
struct uparams new_params = uparams;
#define SKIPWS(p) do { while (isspace (*p)) p++; } while (0);
#define SKIPWS(p) do { while (isspace ((unsigned char) *p)) p++; } while (0);
if (var) if (var)
/* Parse var. */ {
while (*var) /* Parse var. */
{ while (*var)
SKIPWS (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 (isalpha (*var)) while (isalnum ((unsigned char) *arg) || *arg == '-' || *arg == '_')
{
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);
if (*arg == '\0' || *arg == ',')
unspec = 1;
else if (*arg == '=')
{
arg++; arg++;
SKIPWS (arg); var_len = arg - var;
}
SKIPWS (arg);
if (unspec)
{ if (*arg == '\0' || *arg == ',')
if (var[0] == 'n' && var[1] == 'o' && var[2] == '-') unspec = 1;
{ else if (*arg == '=')
val = 0;
var += 3;
var_len -= 3;
}
else
val = 1;
}
else if (isdigit (*arg))
{
val = atoi (arg);
while (isdigit (*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) arg++;
__argp_failure (state, 0, 0, SKIPWS (arg);
dgettext (state->root_argp->argp_domain, "\
%.*s: ARGP_HELP_FMT parameter requires a value"),
(int) var_len, var);
else
*(int *)((char *)&uparams + un->uparams_offs) = val;
break;
} }
if (! un->name)
__argp_failure (state, 0, 0, if (unspec)
dgettext (state->root_argp->argp_domain, "\ {
if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
{
val = 0;
var += 3;
var_len -= 3;
}
else
val = 1;
}
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"), %.*s: Unknown ARGP_HELP_FMT parameter"),
(int) var_len, var); (int) var_len, var);
var = arg; var = arg;
if (*var == ',') if (*var == ',')
var++; var++;
} }
else if (*var) else if (*var)
{ {
__argp_failure (state, 0, 0, __argp_failure (state, 0, 0,
dgettext (state->root_argp->argp_domain, dgettext (state->root_argp->argp_domain,
"Garbage in ARGP_HELP_FMT: %s"), var); "Garbage in ARGP_HELP_FMT: %s"), var);
break; break;
} }
} }
validate_uparams (state, &new_params);
}
} }
/* Returns true if OPT hasn't been marked invisible. Visibility only affects /* 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. */ /* The argp from which this option came. */
const struct argp *argp; const struct argp *argp;
/* Position in the array */
unsigned ord;
}; };
/* A cluster of entries to reflect the argp tree structure. */ /* 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) 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 /* If one cluster is deeper than the other, use its ancestor at the same
level, so that finding the common ancestor is straightforward. */ level, so that finding the common ancestor is straightforward.
while (cl1->depth < cl2->depth)
clN->depth > 0 means that clN->parent != NULL (see hol_add_cluster) */
while (cl1->depth > cl2->depth)
cl1 = cl1->parent; cl1 = cl1->parent;
while (cl2->depth < cl1->depth) while (cl2->depth > cl1->depth)
cl2 = cl2->parent; cl2 = cl2->parent;
/* Now reduce both clusters to their ancestors at the point where both have /* Now reduce both clusters to their ancestors at the point where both have
@ -685,17 +725,19 @@ canon_doc_option (const char **name)
else else
{ {
/* Skip initial whitespace. */ /* Skip initial whitespace. */
while (isspace (**name)) while (isspace ((unsigned char) **name))
(*name)++; (*name)++;
/* Decide whether this looks like an option (leading `-') or not. */ /* Decide whether this looks like an option (leading `-') or not. */
non_opt = (**name != '-'); non_opt = (**name != '-');
/* Skip until part of name used for sorting. */ /* Skip until part of name used for sorting. */
while (**name && !isalnum (**name)) while (**name && !isalnum ((unsigned char) **name))
(*name)++; (*name)++;
} }
return non_opt; 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 /* Order ENTRY1 & ENTRY2 by the order which they should appear in a help
listing. */ listing. */
static int 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 /* 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. */ in a cluster, then this is just the group within the cluster. */
int group1 = entry1->group, group2 = entry2->group; int group1 = entry1->group, group2 = entry2->group;
int rc;
if (entry1->cluster != entry2->cluster) 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); return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
else else
/* Both entries are in clusters, we can just compare the clusters. */ /* 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) else if (group1 == group2)
/* The entries are both in the same cluster and group, so compare them /* 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; return doc1 - doc2;
else if (!short1 && !short2 && long1 && long2) else if (!short1 && !short2 && long1 && long2)
/* Only long options. */ /* Only long options. */
return __strcasecmp (long1, long2); return (rc = __strcasecmp (long1, long2)) ?
rc : HOL_ENTRY_PTRCMP(entry1, entry2);
else else
/* Compare short/short, long/short, short/long, using the first /* Compare short/short, long/short, short/long, using the first
character of long options. Entries without *any* valid character of long options. Entries without *any* valid
@ -762,13 +807,15 @@ hol_entry_cmp (const struct hol_entry *entry1,
#endif #endif
/* Compare ignoring case, except when the options are both the /* Compare ignoring case, except when the options are both the
same letter, in which case lower-case always comes first. */ 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 else
/* Within the same cluster, but not the same group, so just compare /* Within the same cluster, but not the same group, so just compare
groups. */ 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. */ /* Version of hol_entry_cmp with correct signature for qsort. */
@ -785,8 +832,14 @@ static void
hol_sort (struct hol *hol) hol_sort (struct hol *hol)
{ {
if (hol->num_entries > 0) 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 /* 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); int old_wm = __argp_fmtstream_wmargin (stream);
/* PEST is a state block holding some of our variables that we'd like to /* PEST is a state block holding some of our variables that we'd like to
share with helper functions. */ 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)) if (! odoc (real))
for (opt = real, num = entry->num; num > 0; opt++, num--) for (opt = real, num = entry->num; num > 0; opt++, num--)
@ -1263,7 +1322,7 @@ usage_long_opt (const struct argp_option *opt,
if (! arg) if (! arg)
arg = real->arg; arg = real->arg;
if (! (flags & OPTION_NO_USAGE)) if (! (flags & OPTION_NO_USAGE) && !odoc (opt))
{ {
if (arg) if (arg)
{ {
@ -1434,46 +1493,51 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
{ {
const char *text; const char *text;
const char *inp_text; const char *inp_text;
size_t inp_text_len = 0;
const char *trans_text;
void *input = 0; void *input = 0;
int anything = 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; const struct argp_child *child = argp->children;
if (doc) if (argp->doc)
{ {
char *vt = strchr (doc, '\v'); char *vt = strchr (argp->doc, '\v');
inp_text = post ? (vt ? vt + 1 : 0) : doc; if (vt)
inp_text_limit = (!post && vt) ? (vt - doc) : 0; {
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 else
inp_text = 0; trans_text = inp_text = 0;
if (argp->help_filter) if (argp->help_filter)
/* We have to filter the doc strings. */ /* 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); input = __argp_input (argp, state);
text = text =
(*argp->help_filter) (post (*argp->help_filter) (post
? ARGP_KEY_HELP_POST_DOC ? ARGP_KEY_HELP_POST_DOC
: ARGP_KEY_HELP_PRE_DOC, : ARGP_KEY_HELP_PRE_DOC,
inp_text, input); trans_text, input);
} }
else else
text = (const char *) inp_text; text = (const char *) trans_text;
if (text) if (text)
{ {
if (pre_blank) if (pre_blank)
__argp_fmtstream_putc (stream, '\n'); __argp_fmtstream_putc (stream, '\n');
if (text == inp_text && inp_text_limit) __argp_fmtstream_puts (stream, text);
__argp_fmtstream_write (stream, inp_text, inp_text_limit);
else
__argp_fmtstream_puts (stream, text);
if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
__argp_fmtstream_putc (stream, '\n'); __argp_fmtstream_putc (stream, '\n');
@ -1481,9 +1545,10 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
anything = 1; anything = 1;
} }
if (text && text != inp_text) if (text && text != trans_text)
free ((char *) text); /* Free TEXT returned from the help filter. */ 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. */ free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */
if (post && argp->help_filter) 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, void __argp_help (const struct argp *argp, FILE *stream,
unsigned flags, char *name) 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 #ifdef weak_alias
weak_alias (__argp_help, argp_help) weak_alias (__argp_help, argp_help)
@ -1674,8 +1742,7 @@ char *
__argp_short_program_name (void) __argp_short_program_name (void)
{ {
# if HAVE_DECL_PROGRAM_INVOCATION_NAME # if HAVE_DECL_PROGRAM_INVOCATION_NAME
char *name = strrchr (program_invocation_name, '/'); return __argp_base_name (program_invocation_name);
return name ? name + 1 : program_invocation_name;
# else # else
/* FIXME: What now? Miles suggests that it is better to use NULL, /* FIXME: What now? Miles suggests that it is better to use NULL,
but currently the value is passed on directly to fputs_unlocked, 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; char *buf;
__asprintf (&buf, fmt, ap); if (__asprintf (&buf, fmt, ap) < 0)
buf = NULL;
__fwprintf (stream, L"%s: %s\n", __fwprintf (stream, L"%s: %s\n",
state ? state->name : __argp_short_program_name (), state ? state->name : __argp_short_program_name (),
@ -1817,7 +1885,8 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
{ {
char *buf; char *buf;
__asprintf (&buf, fmt, ap); if (__asprintf (&buf, fmt, ap) < 0)
buf = NULL;
__fwprintf (stream, L": %s", buf); __fwprintf (stream, L": %s", buf);
@ -1857,7 +1926,8 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
#endif #endif
#if !_LIBC #if !_LIBC
if (! s && ! (s = strerror (errnum))) if (! s && ! (s = strerror (errnum)))
s = "Unknown system error"; /* FIXME: translate this */ s = dgettext (state->root_argp->argp_domain,
"Unknown system error");
#endif #endif
fputs (s, stream); fputs (s, stream);
} }

View File

@ -1,5 +1,5 @@
/* Name frobnication for compiling argp outside of glibc /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #if !_LIBC
/* This code is written for inclusion in gnu-libc, and uses names in the /* This code is written for inclusion in gnu-libc, and uses names in the
@ -76,11 +76,6 @@
#undef __argp_fmtstream_wmargin #undef __argp_fmtstream_wmargin
#define __argp_fmtstream_wmargin 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 */ /* normal libc functions we call */
#undef __flockfile #undef __flockfile
#define __flockfile flockfile #define __flockfile flockfile
@ -141,14 +136,21 @@
# define putchar_unlocked(x) putchar (x) # define putchar_unlocked(x) putchar (x)
# endif # endif
extern char *__argp_basename (char *name);
#endif /* !_LIBC */ #endif /* !_LIBC */
#ifndef __set_errno #ifndef __set_errno
#define __set_errno(e) (errno = (e)) #define __set_errno(e) (errno = (e))
#endif #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 #if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
# define __argp_short_program_name() (program_invocation_short_name) # define __argp_short_program_name() (program_invocation_short_name)
#else #else

View File

@ -15,13 +15,14 @@
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifdef HAVE_CONFIG_H
#include <config.h> # include <config.h>
#endif #endif
#include <alloca.h> #include <alloca.h>
#include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -37,11 +38,14 @@
#else #else
# include "gettext.h" # include "gettext.h"
#endif #endif
#define N_(msgid) (msgid) #define N_(msgid) msgid
#include "argp.h" #include "argp.h"
#include "argp-namefrob.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. */ /* Getopt return values. */
#define KEY_END (-1) /* The end of the options. */ #define KEY_END (-1) /* The end of the options. */
#define KEY_ARG 1 /* A non-option argument. */ #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[] = static const struct argp_option argp_default_options[] =
{ {
{"help", '?', 0, 0, N_("Give this help list"), -1}, {"help", '?', 0, 0, N_("give this help list"), -1},
{"usage", OPT_USAGE, 0, 0, N_("Give a short usage message"), 0}, {"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}, {"program-name",OPT_PROGNAME,N_("NAME"), OPTION_HIDDEN, N_("set the program name"), 0},
{"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN, {"HANG", OPT_HANG, N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
N_("Hang for SECS seconds (default 3600)"), 0}, N_("hang for SECS seconds (default 3600)"), 0},
{NULL, 0, 0, 0, NULL, 0} {NULL, 0, 0, 0, NULL, 0}
}; };
@ -93,7 +97,7 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
break; break;
case OPT_USAGE: case OPT_USAGE:
__argp_state_help (state, state->out_stream, __argp_state_help (state, state->out_stream,
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
break; break;
case OPT_PROGNAME: /* Set the program name. */ 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.] */ to be that, so we have to be a bit careful here.] */
/* Update what we use for messages. */ /* Update what we use for messages. */
state->name = strrchr (arg, '/'); state->name = __argp_base_name (arg);
if (state->name)
state->name++;
else
state->name = arg;
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME #if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
program_invocation_short_name = state->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[] = 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} {NULL, 0, 0, 0, NULL, 0}
}; };
@ -462,6 +462,11 @@ parser_init (struct parser *parser, const struct argp *argp,
struct group *group; struct group *group;
struct parser_sizes szs; struct parser_sizes szs;
struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER; 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.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
szs.long_len = 0; szs.long_len = 0;
@ -472,22 +477,33 @@ parser_init (struct parser *parser, const struct argp *argp,
calc_sizes (argp, &szs); calc_sizes (argp, &szs);
/* Lengths of the various bits of storage used by PARSER. */ /* Lengths of the various bits of storage used by PARSER. */
#define GLEN (szs.num_groups + 1) * sizeof (struct group) glen = (szs.num_groups + 1) * sizeof (struct group);
#define CLEN (szs.num_child_inputs * sizeof (void *)) clen = szs.num_child_inputs * sizeof (void *);
#define LLEN ((szs.long_len + 1) * sizeof (struct option)) llen = (szs.long_len + 1) * sizeof (struct option);
#define SLEN (szs.short_len + 1) slen = szs.short_len + 1;
parser->storage = malloc (GLEN + CLEN + LLEN + SLEN); /* 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) if (! parser->storage)
return ENOMEM; return ENOMEM;
storage = parser->storage;
parser->groups = parser->storage; parser->groups = parser->storage;
parser->child_inputs = parser->storage + GLEN; parser->child_inputs = (void **) (storage + gsum);
parser->long_opts = parser->storage + GLEN + CLEN; parser->long_opts = (struct option *) (storage + csum);
parser->short_opts = parser->storage + GLEN + CLEN + LLEN; parser->short_opts = storage + lsum;
parser->opt_data = opt_data; 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); parser_convert (parser, argp, flags);
memset (&parser->state, 0, sizeof (struct argp_state)); 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]) if (parser->state.argv == argv && argv[0])
/* There's an argv[0]; use it for messages. */ /* There's an argv[0]; use it for messages. */
{ parser->state.name = __argp_base_name (argv[0]);
char *short_name = strrchr (argv[0], '/');
parser->state.name = short_name ? short_name + 1 : argv[0];
}
else else
parser->state.name = __argp_short_program_name (); 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). */ to be parsed (which in some cases isn't actually an error). */
int arg_ebadkey = 0; 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)) if (! (flags & ARGP_NO_HELP))
/* Add our own options. */ /* Add our own options. */
{ {

28
lib/argp-pin.c Normal file
View File

@ -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

View File

@ -1,5 +1,5 @@
/* Default definition for ARGP_PROGRAM_VERSION. /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 /* 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 --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. */ ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
const char *argp_program_version; const char *argp_program_version;

View File

@ -15,10 +15,10 @@
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifdef HAVE_CONFIG_H
#include <config.h> # include <config.h>
#endif #endif
#include "argp.h" #include "argp.h"

View File

@ -15,10 +15,10 @@
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifdef HAVE_CONFIG_H
#include <config.h> # include <config.h>
#endif #endif
#if defined _LIBC || defined HAVE_FEATURES_H #if defined _LIBC || defined HAVE_FEATURES_H

View File

@ -1,5 +1,5 @@
/* Hierarchial argument parsing, layered over getopt. /* 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. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifndef _ARGP_H
#define _ARGP_H #define _ARGP_H
@ -23,14 +23,11 @@
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include <getopt.h> #include <getopt.h>
#include <limits.h>
#define __need_error_t #define __need_error_t
#include <errno.h> #include <errno.h>
#ifndef __const
# define __const const
#endif
#ifndef __THROW #ifndef __THROW
# define __THROW # define __THROW
#endif #endif
@ -52,10 +49,12 @@
#endif #endif
/* GCC 2.95 and later have "__restrict"; C99 compilers have /* 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 #ifndef __restrict
# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) # if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
# if defined restrict || 199901L <= __STDC_VERSION__ # if 199901L <= __STDC_VERSION__
# define __restrict restrict # define __restrict restrict
# else # else
# define __restrict # define __restrict
@ -81,7 +80,7 @@ struct argp_option
{ {
/* The long option name. For more than one name for the same option, you /* The long option name. For more than one name for the same option, you
can use following options with the OPTION_ALIAS flag set. */ 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 /* What key is returned for this option. If > 0 and printable, then it's
also accepted as a short option. */ 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 /* 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. */ option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */
__const char *arg; const char *arg;
/* OPTION_ flags. */ /* OPTION_ flags. */
int 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 /* 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 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 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 `:'. */ group); in this usage, it's conventional to end the string with a `:'.
__const char *doc;
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 /* 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 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 /* An array of argp_option structures, terminated by an entry with both
NAME and KEY having a value of 0. */ 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 /* 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 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 contains newlines, the strings separated by them are considered
alternative usage patterns, and printed on separate lines (lines after alternative usage patterns, and printed on separate lines (lines after
the first are prefix by ` or: ' instead of `Usage:'). */ 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 /* 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 after the options in a long help message (separated by a vertical tab
`\v' character). */ `\v' character).
__const char *doc; 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 /* 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 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 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 their own argp structure, which you want to use in conjunction with your
own. */ 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 /* 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 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, 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 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. */ 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 /* If non-zero the strings used in the argp library are translated using
the domain described by this string. Otherwise the currently installed the domain described by this string. Otherwise the currently installed
@ -291,7 +295,7 @@ struct argp
struct argp_child struct argp_child
{ {
/* The child parser. */ /* The child parser. */
__const struct argp *argp; const struct argp *argp;
/* Flags for this child. */ /* Flags for this child. */
int flags; int flags;
@ -300,7 +304,7 @@ struct argp_child
child options. As a side-effect, a non-zero value forces the 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 options to be grouped together; to achieve this effect without actually
printing a header string, use a value of "". */ 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') /* 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 options in the parent argp; the values are the same as the GROUP field
@ -316,7 +320,7 @@ struct argp_child
struct argp_state struct argp_state
{ {
/* The top level ARGP being parsed. */ /* The top level ARGP being parsed. */
__const struct argp *root_argp; const struct argp *root_argp;
/* The argument vector being parsed. May be modified. */ /* The argument vector being parsed. May be modified. */
int argc; int argc;
@ -410,22 +414,36 @@ struct argp_state
routine returned a non-zero value, it is returned; otherwise 0 is 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 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. */ 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, extern error_t argp_parse (const struct argp *__restrict __argp,
int __argc, char **__restrict __argv, int /*argc*/, char **__restrict /*argv*/,
unsigned __flags, int *__restrict __arg_index, unsigned __flags, int *__restrict __arg_index,
void *__restrict __input); void *__restrict __input);
extern error_t __argp_parse (__const struct argp *__restrict __argp, extern error_t __argp_parse (const struct argp *__restrict __argp,
int __argc, char **__restrict __argv, int /*argc*/, char **__restrict /*argv*/,
unsigned __flags, int *__restrict __arg_index, unsigned __flags, int *__restrict __arg_index,
void *__restrict __input); void *__restrict __input);
/* Global variables. */ /* 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 /* 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 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 will print this string followed by a newline and exit (unless the
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ 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 /* 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 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 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 standard help messages), embedded in a sentence that says something like
`Report bugs to ADDR.'. */ `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. /* 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 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 /* Output a usage message for ARGP to STREAM. FLAGS are from the set
ARGP_HELP_*. */ ARGP_HELP_*. */
extern void argp_help (__const struct argp *__restrict __argp, extern void argp_help (const struct argp *__restrict __argp,
FILE *__restrict __stream, FILE *__restrict __stream,
unsigned __flags, char *__restrict __name); 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, FILE *__restrict __stream, unsigned __flags,
char *__name); 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 /* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are
from the set ARGP_HELP_*. */ 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, FILE *__restrict __stream,
unsigned int __flags); 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, FILE *__restrict __stream,
unsigned int __flags); unsigned int __flags);
/* Possibly output the standard usage message for ARGP to stderr and exit. */ /* 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 /* If appropriate, print the printf string FMT and following args, preceded
by the program name and `:', to stderr, and followed by a `Try ... --help' by the program name and `:', to stderr, and followed by a `Try ... --help'
message, then exit (1). */ message, then exit (1). */
extern void argp_error (__const struct argp_state *__restrict __state, extern void argp_error (const struct argp_state *__restrict __state,
__const char *__restrict __fmt, ...) const char *__restrict __fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3))); __attribute__ ((__format__ (__printf__, 2, 3)));
extern void __argp_error (__const struct argp_state *__restrict __state, extern void __argp_error (const struct argp_state *__restrict __state,
__const char *__restrict __fmt, ...) const char *__restrict __fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3))); __attribute__ ((__format__ (__printf__, 2, 3)));
/* Similar to the standard gnu error-reporting function error(), but will /* 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 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 errors*, and the former is for other problems that occur during
parsing but don't reflect a (syntactic) problem with the input. */ 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, int __status, int __errnum,
__const char *__restrict __fmt, ...) const char *__restrict __fmt, ...)
__attribute__ ((__format__ (__printf__, 4, 5))); __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, int __status, int __errnum,
__const char *__restrict __fmt, ...) const char *__restrict __fmt, ...)
__attribute__ ((__format__ (__printf__, 4, 5))); __attribute__ ((__format__ (__printf__, 4, 5)));
/* Returns true if the option OPT is a valid short option. */ /* 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 /* Returns true if the option OPT is in fact the last (unused) entry in an
options array. */ 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 /* Return the input field for ARGP in the parser corresponding to STATE; used
by the help routines. */ by the help routines. */
extern void *_argp_input (__const struct argp *__restrict __argp, extern void *_argp_input (const struct argp *__restrict __argp,
__const struct argp_state *__restrict __state) const struct argp_state *__restrict __state)
__THROW; __THROW;
extern void *__argp_input (__const struct argp *__restrict __argp, extern void *__argp_input (const struct argp *__restrict __argp,
__const struct argp_state *__restrict __state) const struct argp_state *__restrict __state)
__THROW; __THROW;
#ifdef __USE_EXTERN_INLINES #ifdef __USE_EXTERN_INLINES
@ -566,25 +584,25 @@ extern void *__argp_input (__const struct argp *__restrict __argp,
# endif # endif
ARGP_EI void 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_state_help (__state, stderr, ARGP_HELP_STD_USAGE);
} }
ARGP_EI int 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) if (__opt->flags & OPTION_DOC)
return 0; return 0;
else else
{ {
int __key = __opt->key; int __key = __opt->key;
return __key > 0 && isprint (__key); return __key > 0 && __key <= UCHAR_MAX && isprint (__key);
} }
} }
ARGP_EI int 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; return !__opt->key && !__opt->name && !__opt->doc && !__opt->group;
} }

View File

@ -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. Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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>
# include <config.h>
#endif
#include "dirname.h" #include "dirname.h"
#include <string.h> #include <string.h>
#include "xalloc.h"
#include "xstrndup.h"
/* In general, we can't use the builtin `basename' function if available, /* Return the address of the last file name component of NAME. If
since it has different meanings in different environments. NAME has no relative file name components because it is a file
In some environments the builtin `basename' modifies its argument. system root, return the empty string. */
Return the address of the last file name component of NAME. If
NAME has no file name components because it is all slashes, return
NAME if it is empty, the address of its last slash otherwise. */
char * char *
base_name (char const *name) last_component (char const *name)
{ {
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name); char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
char const *p; char const *p;
bool saw_slash = false;
while (ISSLASH (*base))
base++;
for (p = base; *p; p++) for (p = base; *p; p++)
{ {
if (ISSLASH (*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; base = p;
saw_slash = false;
} }
} }
return (char *) base; 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 /* In general, we can't use the builtin `basename' function if available,
redundant trailing slashes. */ 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 size_t
base_len (char const *name) base_len (char const *name)
{ {
size_t len; size_t len;
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
continue; 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; return len;
} }

View File

@ -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. Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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>
# include <config.h>
#endif
#include "dirname.h" #include "dirname.h"
#include <string.h> #include <string.h>
#include "xalloc.h" #include "xalloc.h"
/* Return the length of `dirname (PATH)', or zero if PATH is /* Return the length of the prefix of FILE that will be used by
in the working directory. Works properly even if dir_name. If FILE is in the working directory, this returns zero
there are trailing slashes (by effectively ignoring them). */ even though `dir_name (FILE)' will return ".". Works properly even
if there are trailing slashes (by effectively ignoring them). */
size_t 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; size_t length;
/* Strip the basename and any redundant slashes before it. */ /* Advance prefix_length beyond important leading slashes. */
for (length = base_name (path) - path; prefix_length < length; length--) prefix_length += (prefix_length != 0
if (! ISSLASH (path[length - 1])) ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
return length; && ISSLASH (file[prefix_length]))
: (ISSLASH (file[0])
? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
&& ISSLASH (file[1]) && ! ISSLASH (file[2])
? 2 : 1))
: 0));
/* But don't strip the only slash from "/". */ /* Strip the basename and any redundant slashes before it. */
return prefix_length + ISSLASH (path[prefix_length]); for (length = last_component (file) - file;
prefix_length < length; length--)
if (! ISSLASH (file[length - 1]))
break;
return length;
} }
/* Return the leading directories part of PATH,
allocated with xmalloc. /* In general, we can't use the builtin `dirname' function if available,
Works properly even if there are trailing slashes since it has different meanings in different environments.
(by effectively ignoring them). */ In some environments the builtin `dirname' modifies its argument.
Return the leading directories part of FILE, allocated with xmalloc.
Works properly even if there are trailing slashes (by effectively
ignoring them). Unlike POSIX dirname(), FILE cannot be NULL.
If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
lstat (base_name (FILE)); } will access the same file. Likewise,
if the sequence { chdir (dir_name (FILE));
rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
to "foo" in the same directory FILE was in. */
char * char *
dir_name (char const *path) dir_name (char const *file)
{ {
size_t length = dir_len (path); size_t length = dir_len (file);
bool append_dot = (length == FILE_SYSTEM_PREFIX_LEN (path)); bool append_dot = (length == 0
char *newpath = xmalloc (length + append_dot + 1); || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
memcpy (newpath, path, length); && 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) if (append_dot)
newpath[length++] = '.'; dir[length++] = '.';
newpath[length] = 0; dir[length] = '\0';
return newpath; return dir;
} }
#ifdef TEST_DIRNAME
/*
Run the test like this (expect no output):
gcc -DHAVE_CONFIG_H -DTEST_DIRNAME -I.. -O -Wall \
basename.c dirname.c xmalloc.c error.c
sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out
If it's been built on a DOS or Windows platforms, run another test like
this (again, expect no output):
sed -n '/^BEGIN-DOS-DATA$/,/^END-DOS-DATA$/p' dirname.c|grep -v DATA|./a.out
BEGIN-DATA
foo//// .
bar/foo//// bar
foo/ .
/ /
. .
a .
END-DATA
BEGIN-DOS-DATA
c:///// c:/
c:/ c:/
c:/. c:/
c:foo c:.
c:foo/bar c:foo
END-DOS-DATA
*/
# define MAX_BUFF_LEN 1024
# include <stdio.h>
char *program_name;
int
main (int argc, char *argv[])
{
char buff[MAX_BUFF_LEN + 1];
program_name = argv[0];
buff[MAX_BUFF_LEN] = 0;
while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
{
char path[MAX_BUFF_LEN];
char expected_result[MAX_BUFF_LEN];
char const *result;
sscanf (buff, "%s %s", path, expected_result);
result = dir_name (path);
if (strcmp (result, expected_result))
printf ("%s: got %s, expected %s\n", path, result, expected_result);
}
return 0;
}
#endif

View File

@ -1,6 +1,6 @@
/* Take file names apart into directory and base names. /* 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 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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_ #ifndef DIRNAME_H_
# define DIRNAME_H_ 1 # define DIRNAME_H_ 1
@ -31,17 +31,40 @@
# endif # endif
# ifndef FILE_SYSTEM_PREFIX_LEN # 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 # 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)) # define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
char *base_name (char const *path); char *base_name (char const *file);
char *dir_name (char const *path); char *dir_name (char const *file);
size_t base_len (char const *path); size_t base_len (char const *file);
size_t dir_len (char const *path); 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_ */ #endif /* not DIRNAME_H_ */

View File

@ -1,5 +1,5 @@
/* Error handler for noninteractive utilities /* 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 file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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>. */ /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#ifdef HAVE_CONFIG_H #if !_LIBC
# include <config.h> # include <config.h>
#endif #endif
@ -29,13 +29,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef _LIBC #if !_LIBC && ENABLE_NLS
# include <libintl.h>
#else
# include "gettext.h" # include "gettext.h"
#endif #endif
#ifdef _LIBC #ifdef _LIBC
# include <libintl.h>
# include <stdbool.h>
# include <stdint.h>
# include <wchar.h> # include <wchar.h>
# define mbsrtowcs __mbsrtowcs # define mbsrtowcs __mbsrtowcs
#endif #endif
@ -61,6 +62,7 @@ unsigned int error_message_count;
# define program_name program_invocation_name # define program_name program_invocation_name
# include <errno.h> # include <errno.h>
# include <limits.h>
# include <libio/libioP.h> # include <libio/libioP.h>
/* In GNU libc we want do not want to use the common name `error' directly. /* 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 (); char *strerror_r ();
# endif # endif
# ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
# endif
/* The calling program should define program_name and set it to the /* The calling program should define program_name and set it to the
name of the executing program. */ name of the executing program. */
extern char *program_name; extern char *program_name;
# if HAVE_STRERROR_R || defined strerror_r # if HAVE_STRERROR_R || defined strerror_r
# define __strerror_r strerror_r # define __strerror_r strerror_r
# endif # endif /* HAVE_STRERROR_R || defined strerror_r */
#endif /* not _LIBC */ #endif /* not _LIBC */
static void static void
print_errno_message (int errnum) print_errno_message (int errnum)
{ {
char const *s = NULL; char const *s;
#if defined HAVE_STRERROR_R || _LIBC #if defined HAVE_STRERROR_R || _LIBC
char errbuf[1024]; char errbuf[1024];
@ -115,23 +113,23 @@ print_errno_message (int errnum)
# else # else
if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
s = errbuf; s = errbuf;
else
s = 0;
# endif # endif
#else
s = strerror (errnum);
#endif #endif
#if !_LIBC #if !_LIBC
if (! s && ! (s = strerror (errnum))) if (! s)
s = _("Unknown system error"); s = _("Unknown system error");
#endif #endif
#if _LIBC #if _LIBC
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, ": %s", s);
{ #else
__fwprintf (stderr, L": %s", s);
return;
}
#endif
fprintf (stderr, ": %s", s); fprintf (stderr, ": %s", s);
#endif
} }
static void static void
@ -142,26 +140,65 @@ error_tail (int status, int errnum, const char *message, va_list args)
{ {
# define ALLOCA_LIMIT 2000 # define ALLOCA_LIMIT 2000
size_t len = strlen (message) + 1; size_t len = strlen (message) + 1;
const wchar_t *wmessage = L"out of memory"; wchar_t *wmessage = NULL;
wchar_t *wbuf = (len < ALLOCA_LIMIT mbstate_t st;
? alloca (len * sizeof *wbuf) size_t res;
: len <= SIZE_MAX / sizeof *wbuf const char *tmp;
? malloc (len * sizeof *wbuf) bool use_malloc = false;
: NULL);
if (wbuf) while (1)
{ {
size_t res; if (__libc_use_alloca (len * sizeof (wchar_t)))
mbstate_t st; wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
const char *tmp = message; 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)); memset (&st, '\0', sizeof (st));
res = mbsrtowcs (wbuf, &tmp, len, &st); tmp = message;
wmessage = res == (size_t) -1 ? L"???" : wbuf;
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); __vfwprintf (stderr, wmessage, args);
if (! (len < ALLOCA_LIMIT))
free (wbuf); if (use_malloc)
free (wmessage);
} }
else else
#endif #endif
@ -172,11 +209,10 @@ error_tail (int status, int errnum, const char *message, va_list args)
if (errnum) if (errnum)
print_errno_message (errnum); print_errno_message (errnum);
#if _LIBC #if _LIBC
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "\n");
putwc (L'\n', stderr); #else
else putc ('\n', stderr);
#endif #endif
putc ('\n', stderr);
fflush (stderr); fflush (stderr);
if (status) if (status)
exit (status); exit (status);
@ -209,11 +245,10 @@ error (int status, int errnum, const char *message, ...)
else else
{ {
#if _LIBC #if _LIBC
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s: ", program_name);
__fwprintf (stderr, L"%s: ", program_name); #else
else fprintf (stderr, "%s: ", program_name);
#endif #endif
fprintf (stderr, "%s: ", program_name);
} }
va_start (args, message); va_start (args, message);
@ -269,22 +304,19 @@ error_at_line (int status, int errnum, const char *file_name,
else else
{ {
#if _LIBC #if _LIBC
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s:", program_name);
__fwprintf (stderr, L"%s: ", program_name); #else
else fprintf (stderr, "%s:", program_name);
#endif #endif
fprintf (stderr, "%s:", program_name);
} }
if (file_name != NULL)
{
#if _LIBC #if _LIBC
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
__fwprintf (stderr, L"%s:%d: ", file_name, line_number); file_name, line_number);
else #else
fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
file_name, line_number);
#endif #endif
fprintf (stderr, "%s:%d: ", file_name, line_number);
}
va_start (args, message); va_start (args, message);
error_tail (status, errnum, message, args); error_tail (status, errnum, message, args);

View File

@ -1,5 +1,5 @@
/* Declaration for error-reporting function /* 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 file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifndef _ERROR_H
#define _ERROR_H 1 #define _ERROR_H 1
#ifndef __attribute__ #ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */ /* 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 */ # define __attribute__(Spec) /* empty */
# endif # endif
/* The __-protected variants of `format' and `printf' attributes /* The __-protected variants of `format' and `printf' attributes

View File

@ -1,6 +1,6 @@
/* Failure exit status /* 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 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 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 You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. along with this program; see the file COPYING.
If not, write to the Free Software Foundation, 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>
# include <config.h>
#endif
#include "exitfail.h" #include "exitfail.h"
#include "exit.h"
#include <stdlib.h>
int volatile exit_failure = EXIT_FAILURE; int volatile exit_failure = EXIT_FAILURE;

View File

@ -15,6 +15,6 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. along with this program; see the file COPYING.
If not, write to the Free Software Foundation, 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; extern int volatile exit_failure;

27
lib/fatal.c Normal file
View File

@ -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);
}

View File

@ -1,7 +1,7 @@
/* An interface to read and write that retries (if necessary) until complete. /* An interface to read and write that retries (if necessary) until complete.
Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 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 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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>
# include <config.h>
#endif
/* Specification. */ /* Specification. */
#ifdef FULL_READ #ifdef FULL_READ
@ -62,7 +60,7 @@ size_t
full_rw (int fd, const void *buf, size_t count) full_rw (int fd, const void *buf, size_t count)
{ {
size_t total = 0; size_t total = 0;
const char *ptr = buf; const char *ptr = (const char *) buf;
while (count > 0) while (count > 0)
{ {

View File

@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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> #include <stddef.h>

View File

@ -2,7 +2,7 @@
NOTE: getopt is now part of the C library, so if you don't know what 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 "Keep this file name-space clean" means, talk to drepper@gnu.org
before changing it! 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. Free Software Foundation, Inc.
This file is part of the GNU C Library. 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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>. #ifndef _LIBC
Ditto for AIX 3.2 and <stdlib.h>. */
#ifndef _NO_PROTO
# define _NO_PROTO
#endif
#ifdef HAVE_CONFIG_H
# include <config.h> # include <config.h>
#endif #endif
#include "getopt.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.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 <string.h> #include <string.h>
#include <unistd.h>
#ifdef VMS #ifdef __VMS
# include <unixlib.h> # include <unixlib.h>
#endif #endif
@ -76,7 +64,6 @@
GNU application programs can use a third alternative mode in which GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */ they can distinguish the relative order of options and other arguments. */
#include "getopt.h"
#include "getopt_int.h" #include "getopt_int.h"
/* For communication from `getopt' to the caller. /* For communication from `getopt' to the caller.
@ -118,16 +105,9 @@ int optopt = '?';
static struct _getopt_data getopt_data; static struct _getopt_data getopt_data;
#ifndef __GNU_LIBRARY__ #if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV
/* Avoid depending on library functions or files
whose names are inconsistent. */
#ifndef getenv
extern char *getenv (); extern char *getenv ();
#endif #endif
#endif /* not __GNU_LIBRARY__ */
#ifdef _LIBC #ifdef _LIBC
/* Stored original parameters. /* Stored original parameters.
@ -556,10 +536,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2; int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s", buf);
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2; ((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr); _IO_funlockfile (stderr);
@ -634,10 +611,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
((_IO_FILE *) stderr)->_flags2 ((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL; |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s", buf);
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2; ((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr); _IO_funlockfile (stderr);
@ -674,10 +648,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
((_IO_FILE *) stderr)->_flags2 ((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL; |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s", buf);
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2; ((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr); _IO_funlockfile (stderr);
@ -751,10 +722,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2; int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s", buf);
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2; ((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr); _IO_funlockfile (stderr);
@ -817,10 +785,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2; int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s", buf);
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2; ((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr); _IO_funlockfile (stderr);
@ -868,10 +833,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2; int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s", buf);
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2; ((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr); _IO_funlockfile (stderr);
@ -940,10 +902,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2; int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s", buf);
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2; ((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr); _IO_funlockfile (stderr);
@ -985,10 +944,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
((_IO_FILE *) stderr)->_flags2 ((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL; |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s", buf);
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2; ((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr); _IO_funlockfile (stderr);
@ -1027,10 +983,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
((_IO_FILE *) stderr)->_flags2 ((_IO_FILE *) stderr)->_flags2
|= _IO_FLAGS2_NOTCANCEL; |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s", buf);
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2; ((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr); _IO_funlockfile (stderr);
@ -1101,10 +1054,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int old_flags2 = ((_IO_FILE *) stderr)->_flags2; int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
if (_IO_fwide (stderr, 0) > 0) __fxprintf (NULL, "%s", buf);
__fwprintf (stderr, L"%s", buf);
else
fputs (buf, stderr);
((_IO_FILE *) stderr)->_flags2 = old_flags2; ((_IO_FILE *) stderr)->_flags2 = old_flags2;
_IO_funlockfile (stderr); _IO_funlockfile (stderr);

View File

@ -1,5 +1,5 @@
/* getopt_long and getopt_long_only entry points for GNU getopt. /* 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. Free Software Foundation, Inc.
This file is part of the GNU C Library. 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifdef _LIBC
# include <getopt.h> # include <getopt.h>
#else #else
# include <config.h>
# include "getopt.h" # include "getopt.h"
#endif #endif
#include "getopt_int.h" #include "getopt_int.h"

View File

@ -1,5 +1,5 @@
/* Declarations for getopt. /* 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. Free Software Foundation, Inc.
This file is part of the GNU C Library. 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifndef _GETOPT_H
@ -34,9 +34,7 @@
#if defined __GETOPT_PREFIX && !defined __need_getopt #if defined __GETOPT_PREFIX && !defined __need_getopt
# include <stdlib.h> # include <stdlib.h>
# include <stdio.h> # include <stdio.h>
# if HAVE_UNISTD_H # include <unistd.h>
# include <unistd.h>
# endif
# undef __need_getopt # undef __need_getopt
# undef getopt # undef getopt
# undef getopt_long # undef getopt_long
@ -67,14 +65,14 @@
but it caused redefinition warnings if both unistd.h and getopt.h were but it caused redefinition warnings if both unistd.h and getopt.h were
included, since unistd.h includes getopt.h having previously defined included, since unistd.h includes getopt.h having previously defined
__need_getopt. __need_getopt.
The only place where __getopt_argv_const is used is in definitions The only place where __getopt_argv_const is used is in definitions
of getopt_long and getopt_long_only below, but these are visible 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 only if __need_getopt is not defined, so it is quite safe to rewrite
the conditional as follows: the conditional as follows:
*/ */
#if !defined __need_getopt #if !defined __need_getopt
# if defined __GETOPT_PREFIX # if defined __GETOPT_PREFIX
# define __getopt_argv_const /* empty */ # define __getopt_argv_const /* empty */
# else # else
# define __getopt_argv_const const # define __getopt_argv_const const
@ -103,7 +101,7 @@
# endif # endif
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -198,9 +196,10 @@ struct option
scanning, explicitly telling `getopt' that there are no more scanning, explicitly telling `getopt' that there are no more
options. options.
If OPTS begins with `--', then non-option arguments are treated as If OPTS begins with `-', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU arguments to the option '\1'. This behavior is specific to the GNU
`getopt'. */ `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) extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
__THROW; __THROW;
@ -217,7 +216,7 @@ extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -15,7 +15,7 @@
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1 #define _GETOPT_INT_H 1

View File

@ -1,5 +1,5 @@
/* Convenience header for conditional use of GNU <libintl.h>. /* 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 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 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 You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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 #ifndef _LIBGETTEXT_H
#define _LIBGETTEXT_H 1 #define _LIBGETTEXT_H 1
@ -24,6 +24,18 @@
/* Get declarations of GNU message catalog functions. */ /* Get declarations of GNU message catalog functions. */
# include <libintl.h> # 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 #else
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
@ -36,23 +48,38 @@
# include <locale.h> # include <locale.h>
#endif #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. /* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings The casts to 'const char *' serve the purpose of producing warnings
for invalid uses of the value returned from these functions. for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */ contain "#define const". */
# define gettext(Msgid) ((const char *) (Msgid)) # define gettext(Msgid) ((const char *) (Msgid))
# define dgettext(Domainname, Msgid) ((const char *) (Msgid)) # define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) # define dcgettext(Domainname, Msgid, Category) \
((void) (Category), dgettext (Domainname, Msgid))
# define ngettext(Msgid1, Msgid2, N) \ # 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) \ # 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) \ # 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 textdomain(Domainname) ((const char *) (Domainname))
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) # define bindtextdomain(Domainname, Dirname) \
# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) ((void) (Domainname), (const char *) (Dirname))
# define bind_textdomain_codeset(Domainname, Codeset) \
((void) (Domainname), (const char *) (Codeset))
#endif #endif
@ -65,4 +92,179 @@
initializer for static 'char[]' or 'const char[]' variables. */ initializer for static 'char[]' or 'const char[]' variables. */
#define gettext_noop(String) String #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 */ #endif /* _LIBGETTEXT_H */

1048
lib/hash.c Normal file

File diff suppressed because it is too large Load Diff

88
lib/hash.h Normal file
View File

@ -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

78
lib/intprops.h Normal file
View File

@ -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)

51
lib/inttostr.c Normal file
View File

@ -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;
}

View File

@ -1,5 +1,7 @@
/* exit() function. /* inttostr.h -- convert integers to printable strings
Copyright (C) 1995, 2001 Free Software Foundation, Inc.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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 /* Written by Paul Eggert */
#define _EXIT_H
/* Get exit() declaration. */ #include <stdint.h>
#include <stdlib.h> #include <sys/types.h>
/* Some systems do not define EXIT_*, even with STDC_HEADERS. */ #include "intprops.h"
#ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
#endif
#endif /* _EXIT_H */ char *offtostr (off_t, char *);
char *imaxtostr (intmax_t, char *);
char *umaxtostr (uintmax_t, char *);
char *uinttostr (unsigned int, char *);

View File

@ -1,5 +1,5 @@
/* Copy memory area and return pointer after last written byte. /* 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 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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. */ /* Specification. */
#include "mempcpy.h"
#include <string.h> #include <string.h>
/* Copy N bytes of SRC to DEST, return pointer to bytes after the /* Copy N bytes of SRC to DEST, return pointer to bytes after the

365
lib/paxerror.c Normal file
View File

@ -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);
}

28
lib/paxexit.c Normal file
View File

@ -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);
}

115
lib/paxlib.h Normal file
View File

@ -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

156
lib/paxnames.c Normal file
View File

@ -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;
}

41
lib/quote.c Normal file
View File

@ -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);
}

View File

@ -1,5 +1,7 @@
/* Searching in a string. /* quote.h - prototypes for quote.c
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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_STRCHRNUL
/* Get strchrnul() declaration. */ char const *quote_n (int n, char const *name);
#include <string.h> char const *quote (char const *name);
#else
/* Find the first occurrence of C in S or the final NUL byte. */
extern char *strchrnul (const char *s, int c_in);
#endif

697
lib/quotearg.c Normal file
View File

@ -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, ':');
}

140
lib/quotearg.h Normal file
View File

@ -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_ */

View File

@ -15,7 +15,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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_command;
extern char *rmt_dev_name__; extern char *rmt_dev_name__;

View File

@ -1,7 +1,7 @@
/* Functions for communicating with a remote tape drive. /* Functions for communicating with a remote tape drive.
Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004 Free Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004,
Software Foundation, Inc. 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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 /* 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*. which rdump and rrestore use. Unfortunately, the man page is *WRONG*.
@ -33,6 +33,8 @@
code, courtesy of Dan Kegel. */ code, courtesy of Dan Kegel. */
#include "system.h" #include "system.h"
#include "system-ioctl.h"
#include <safe-read.h> #include <safe-read.h>
#include <full-write.h> #include <full-write.h>
@ -58,7 +60,7 @@
#endif #endif
#include <rmt.h> #include <rmt.h>
#include <localedir.h> #include <rmt-command.h>
/* Exit status if exec errors. */ /* Exit status if exec errors. */
#define EXIT_ON_EXEC_ERROR 128 #define EXIT_ON_EXEC_ERROR 128
@ -340,9 +342,7 @@ encode_oflag (char *buf, int oflag)
#ifdef O_NOCTTY #ifdef O_NOCTTY
if (oflag & O_NOCTTY) strcat (buf, "|O_NOCTTY"); if (oflag & O_NOCTTY) strcat (buf, "|O_NOCTTY");
#endif #endif
#ifdef O_NONBLOCK
if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK"); if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK");
#endif
#ifdef O_RSYNC #ifdef O_RSYNC
if (oflag & O_RSYNC) strcat (buf, "|O_RSYNC"); if (oflag & O_RSYNC) strcat (buf, "|O_RSYNC");
#endif #endif
@ -358,7 +358,7 @@ encode_oflag (char *buf, int oflag)
remote pipe number plus BIAS. REMOTE_SHELL may be overridden. On remote pipe number plus BIAS. REMOTE_SHELL may be overridden. On
error, return -1. */ error, return -1. */
int 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) const char *remote_shell)
{ {
int remote_pipe_number; /* pseudo, biased file descriptor */ int remote_pipe_number; /* pseudo, biased file descriptor */

View File

@ -1,7 +1,7 @@
/* An interface to read and write that retries after interrupts. /* An interface to read and write that retries after interrupts.
Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004 Free Software Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004, 2005, 2006 Free
Foundation, Inc. Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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>
# include <config.h>
#endif
/* Specification. */ /* Specification. */
#ifdef SAFE_WRITE #ifdef SAFE_WRITE
@ -30,9 +28,7 @@
/* Get ssize_t. */ /* Get ssize_t. */
#include <sys/types.h> #include <sys/types.h>
#if HAVE_UNISTD_H #include <unistd.h>
# include <unistd.h>
#endif
#include <errno.h> #include <errno.h>

View File

@ -1,5 +1,5 @@
/* An interface to read() that retries after interrupts. /* 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 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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> #include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SAFE_READ_ERROR ((size_t) -1) #define SAFE_READ_ERROR ((size_t) -1)
/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted. /* 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 Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR
upon error. */ upon error. */
extern size_t safe_read (int fd, void *buf, size_t count); extern size_t safe_read (int fd, void *buf, size_t count);
#ifdef __cplusplus
}
#endif

View File

@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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 #define SAFE_WRITE
#include "safe-read.c" #include "safe-read.c"

View File

@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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> #include <stddef.h>

View File

@ -1,7 +1,7 @@
/* savedir.c -- save the list of files in a directory in a string /* savedir.c -- save the list of files in a directory in a string
Copyright 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free Copyright (C) 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
Software Foundation, Inc. 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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>. */ /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#if HAVE_CONFIG_H #include <config.h>
# include <config.h>
#endif
#include "savedir.h" #include "savedir.h"
@ -29,68 +27,62 @@
#include <errno.h> #include <errno.h>
#if HAVE_DIRENT_H #include <dirent.h>
# include <dirent.h> #ifndef _D_EXACT_NAMLEN
#else # define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)
# define dirent direct
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#ifdef CLOSEDIR_VOID
/* Fake a return value. */
# define CLOSEDIR(d) (closedir (d), 0)
#else
# define CLOSEDIR(d) closedir (d)
#endif #endif
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "openat.h"
#include "xalloc.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 #ifndef NAME_SIZE_DEFAULT
# define NAME_SIZE_DEFAULT 512 # define NAME_SIZE_DEFAULT 512
#endif #endif
char * /* The results of opendir() in this file are not used with dirfd and fchdir,
savedir (const char *dir) 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; char *name_space;
size_t allocated = NAME_SIZE_DEFAULT; size_t allocated = NAME_SIZE_DEFAULT;
size_t used = 0; size_t used = 0;
int save_errno; int save_errno;
dirp = opendir (dir);
if (dirp == NULL) if (dirp == NULL)
return NULL; return NULL;
name_space = xmalloc (allocated); name_space = xmalloc (allocated);
errno = 0; for (;;)
while ((dp = readdir (dirp)) != NULL)
{ {
struct dirent const *dp;
char const *entry;
errno = 0;
dp = readdir (dirp);
if (! dp)
break;
/* Skip "", ".", and "..". "" is returned by at least one buggy /* Skip "", ".", and "..". "" is returned by at least one buggy
implementation: Solaris 2.4 readdir on NFS file systems. */ 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') 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) if (used + entry_size < used)
xalloc_die (); xalloc_die ();
if (allocated <= used + entry_size) if (allocated <= used + entry_size)
@ -111,7 +103,7 @@ savedir (const char *dir)
} }
name_space[used] = '\0'; name_space[used] = '\0';
save_errno = errno; save_errno = errno;
if (CLOSEDIR (dirp) != 0) if (closedir (dirp) != 0)
save_errno = errno; save_errno = errno;
if (save_errno != 0) if (save_errno != 0)
{ {
@ -121,3 +113,25 @@ savedir (const char *dir)
} }
return name_space; 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));
}

View File

@ -1,6 +1,6 @@
/* Save the list of files in a directory in a string. /* 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 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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>. */ /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#if !defined SAVEDIR_H_ #if !defined SAVEDIR_H_
# define SAVEDIR_H_ # define SAVEDIR_H_
char *savedir (const char *dir); char *savedir (char const *dir);
char *fdsavedir (int fd);
#endif #endif

View File

@ -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 */

View File

@ -1,5 +1,5 @@
/* Searching in a string. /* 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 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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. */ /* Specification. */
#include "strchrnul.h" #include <string.h>
/* Find the first occurrence of C in S or the final NUL byte. */ /* Find the first occurrence of C in S or the final NUL byte. */
char * char *

View File

@ -1,5 +1,6 @@
/* stripslash.c -- remove redundant trailing slashes from a file name /* 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 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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>
# include <config.h>
#endif
#include "dirname.h" #include "dirname.h"
/* Remove trailing slashes from PATH. /* Remove trailing slashes from FILE. Return true if a trailing slash
Return true if a trailing slash was removed. was removed. This is useful when using file name completion from a
This is useful when using filename completion from a shell that shell that adds a "/" after directory names (such as tcsh and
adds a "/" after directory names (such as tcsh and bash), because bash), because on symlinks to directories, several system calls
the Unix rename and rmdir system calls return an "Invalid argument" error have different semantics according to whether a trailing slash is
when given a path that ends in "/" (except for the root directory). */ present. */
bool bool
strip_trailing_slashes (char *path) strip_trailing_slashes (char *file)
{ {
char *base = base_name (path); char *base = last_component (file);
char *base_lim = base + base_len (base); char *base_lim;
bool had_slash = (*base_lim != '\0'); 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'; *base_lim = '\0';
return had_slash; return had_slash;
} }

View File

@ -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. Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2005, 2006, 2007
Bugs can be reported to bug-glibc@prep.ai.mit.edu. Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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 <stdlib.h>
#include <string.h> #include <string.h>
#ifndef HAVE_DECL_STRNLEN #include <stdlib.h>
"this configure-time declaration test was not run"
#endif
#if !HAVE_DECL_STRNLEN
size_t strnlen ();
#endif
#undef __strndup
#undef strndup
#ifndef weak_alias
# define __strndup strndup
#endif
char * char *
__strndup (const char *s, size_t n) strndup (char const *s, size_t n)
{ {
size_t len = strnlen (s, n); size_t len = strnlen (s, n);
char *new = malloc (len + 1); char *new = malloc (len + 1);
@ -50,6 +35,3 @@ __strndup (const char *s, size_t n)
new[len] = '\0'; new[len] = '\0';
return memcpy (new, s, len); return memcpy (new, s, len);
} }
#ifdef weak_alias
weak_alias (__strndup, strndup)
#endif

View File

@ -1,6 +1,6 @@
/* Find the length of STRING, but scan at most MAXLEN characters. /* Find the length of STRING, but scan at most MAXLEN characters.
Copyright (C) 1996, 1997, 1998, 2000-2003 Free Software Foundation, Inc. Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library. Written by Simon Josefsson.
This program is free software; you can redistribute it and/or modify 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, 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>
# include <config.h>
#endif
#undef strnlen
#include <string.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. /* Find the length of STRING, but scan at most MAXLEN characters.
If no '\0' terminator is found in that many characters, return MAXLEN. */ If no '\0' terminator is found in that many characters, return MAXLEN. */
size_t size_t
__strnlen (const char *string, size_t maxlen) strnlen (const char *string, size_t maxlen)
{ {
const char *end = memchr (string, '\0', maxlen); const char *end = memchr (string, '\0', maxlen);
return end ? (size_t) (end - string) : maxlen; return end ? (size_t) (end - string) : maxlen;
} }
#ifdef weak_alias
weak_alias (__strnlen, strnlen)
#endif

55
lib/system-ioctl.h Normal file
View File

@ -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

View File

@ -1,7 +1,7 @@
/* System dependent definitions for GNU tar. /* System dependent definitions for GNU tar.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 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 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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 #if HAVE_CONFIG_H
# include <config.h> # include <config.h>
@ -109,10 +108,19 @@ extern int errno;
#ifndef O_TRUNC #ifndef O_TRUNC
# define O_TRUNC 32 /* truncate file on open */ # define O_TRUNC 32 /* truncate file on open */
#endif #endif
/* MS-DOG forever, with my love! */
#ifndef O_BINARY #ifndef O_BINARY
# define O_BINARY 0 # define O_BINARY 0
#endif #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. */ /* Declare file status routines and bits. */
@ -252,9 +260,7 @@ extern int errno;
#define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX) #define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
/* Include <unistd.h> before any preprocessor test of _POSIX_VERSION. */ /* Include <unistd.h> before any preprocessor test of _POSIX_VERSION. */
#if HAVE_UNISTD_H #include <unistd.h>
# include <unistd.h>
#endif
#ifndef SEEK_SET #ifndef SEEK_SET
# define SEEK_SET 0 # define SEEK_SET 0
@ -282,6 +288,9 @@ extern int errno;
#if MAJOR_IN_MKDEV #if MAJOR_IN_MKDEV
# include <sys/mkdev.h> # include <sys/mkdev.h>
# if !defined(makedev) && defined(mkdev)
# define makedev(a,b) mkdev((a),(b))
# endif
# define GOT_MAJOR # define GOT_MAJOR
#endif #endif
@ -377,45 +386,12 @@ extern int errno;
#endif #endif
#ifndef ST_NBLOCKSIZE #ifndef ST_NBLOCKSIZE
#define ST_NBLOCKSIZE 512 # define ST_NBLOCKSIZE 512
#endif #endif
/* This is a real challenge to properly get MTIO* symbols :-(. ISC uses #define ST_IS_SPARSE(st) \
<sys/gentape.h>. SCO and BSDi uses <sys/tape.h>; BSDi also requires (ST_NBLOCKS (st) \
<sys/tprintf.h> and <sys/device.h> for defining tp_dev and tpr_t. It < ((st).st_size / ST_NBLOCKSIZE + ((st).st_size % ST_NBLOCKSIZE != 0)))
seems that the rest use <sys/mtio.h>, which itself requires other files,
depending on systems. Pyramid defines _IOW in <sgtty.h>, for example. */
#if HAVE_SYS_GENTAPE_H
# include <sys/gentape.h>
#else
# if HAVE_SYS_TAPE_H
# if HAVE_SYS_DEVICE_H
# include <sys/device.h>
# endif
# if HAVE_SYS_PARAM_H
# include <sys/param.h>
# endif
# if HAVE_SYS_BUF_H
# include <sys/buf.h>
# endif
# if HAVE_SYS_TPRINTF_H
# include <sys/tprintf.h>
# endif
# include <sys/tape.h>
# else
# if HAVE_SYS_MTIO_H
# include <sys/ioctl.h>
# if HAVE_SGTTY_H
# include <sgtty.h>
# endif
# if HAVE_SYS_IO_TRIOCTL_H
# include <sys/io/trioctl.h>
# endif
# include <sys/mtio.h>
# endif
# endif
#endif
/* Declare standard functions. */ /* Declare standard functions. */
@ -435,7 +411,6 @@ char *getenv ();
#endif #endif
#if WITH_DMALLOC #if WITH_DMALLOC
# undef HAVE_DECL_VALLOC
# define DMALLOC_FUNC_CHECK # define DMALLOC_FUNC_CHECK
# include <dmalloc.h> # include <dmalloc.h>
#endif #endif
@ -446,28 +421,11 @@ char *getenv ();
# define MB_LEN_MAX 1 # define MB_LEN_MAX 1
#endif #endif
#if HAVE_INTTYPES_H #include <inttypes.h>
# include <inttypes.h>
#endif
/* These macros work even on ones'-complement hosts (!). #include <intprops.h>
The extra casts work around common compiler bugs. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
#define TYPE_MINIMUM(t) (TYPE_SIGNED (t) \
? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
: (t) 0)
#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
/* Bound on length of the string representing an integer value of type t. #define UINTMAX_STRSIZE_BOUND INT_BUFSIZE_BOUND (uintmax_t)
Subtract one for the sign bit if t is signed;
302 / 1000 is log10 (2) rounded up;
add one for integer division truncation;
add one more for a minus sign if t is signed. */
#define INT_STRLEN_BOUND(t) \
((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
+ 1 + TYPE_SIGNED (t))
#define UINTMAX_STRSIZE_BOUND (INT_STRLEN_BOUND (uintmax_t) + 1)
/* Prototypes for external functions. */ /* Prototypes for external functions. */
@ -479,16 +437,9 @@ char *getenv ();
#endif #endif
#include <time.h> #include <time.h>
#if defined(HAVE_SYS_TIME_H) && defined(TIME_WITH_SYS_TIME) #ifdef TIME_WITH_SYS_TIME
# include <sys/time.h> # include <sys/time.h>
#endif #endif
#if ! HAVE_DECL_TIME
time_t time ();
#endif
#ifdef HAVE_UTIME_H
# include <utime.h>
#endif
/* Library modules. */ /* Library modules. */

3
lib/umaxtostr.c Normal file
View File

@ -0,0 +1,3 @@
#define inttostr umaxtostr
#define inttype uintmax_t
#include "inttostr.c"

View File

@ -14,12 +14,12 @@
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, 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. */ /* Written by Jim Meyering. */
#ifndef UNLOCKED_IO_H #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 /* These are wrappers for functions/macros from the GNU C library, and
from other C libraries supporting POSIX's optional thread-safe functions. from other C libraries supporting POSIX's optional thread-safe functions.
@ -32,106 +32,106 @@
the *_unlocked functions directly. On hosts that lack those the *_unlocked functions directly. On hosts that lack those
functions, invoke the non-thread-safe versions instead. */ functions, invoke the non-thread-safe versions instead. */
#include <stdio.h> # include <stdio.h>
#if HAVE_DECL_CLEARERR_UNLOCKED # if HAVE_DECL_CLEARERR_UNLOCKED
# undef clearerr # undef clearerr
# define clearerr(x) clearerr_unlocked (x) # define clearerr(x) clearerr_unlocked (x)
#else # else
# define clearerr_unlocked(x) clearerr (x) # define clearerr_unlocked(x) clearerr (x)
#endif # endif
#if HAVE_DECL_FEOF_UNLOCKED # if HAVE_DECL_FEOF_UNLOCKED
# undef feof # undef feof
# define feof(x) feof_unlocked (x) # define feof(x) feof_unlocked (x)
#else # else
# define feof_unlocked(x) feof (x) # define feof_unlocked(x) feof (x)
#endif # endif
#if HAVE_DECL_FERROR_UNLOCKED # if HAVE_DECL_FERROR_UNLOCKED
# undef ferror # undef ferror
# define ferror(x) ferror_unlocked (x) # define ferror(x) ferror_unlocked (x)
#else # else
# define ferror_unlocked(x) ferror (x) # define ferror_unlocked(x) ferror (x)
#endif # endif
#if HAVE_DECL_FFLUSH_UNLOCKED # if HAVE_DECL_FFLUSH_UNLOCKED
# undef fflush # undef fflush
# define fflush(x) fflush_unlocked (x) # define fflush(x) fflush_unlocked (x)
#else # else
# define fflush_unlocked(x) fflush (x) # define fflush_unlocked(x) fflush (x)
#endif # endif
#if HAVE_DECL_FGETS_UNLOCKED # if HAVE_DECL_FGETS_UNLOCKED
# undef fgets # undef fgets
# define fgets(x,y,z) fgets_unlocked (x,y,z) # define fgets(x,y,z) fgets_unlocked (x,y,z)
#else # else
# define fgets_unlocked(x,y,z) fgets (x,y,z) # define fgets_unlocked(x,y,z) fgets (x,y,z)
#endif # endif
#if HAVE_DECL_FPUTC_UNLOCKED # if HAVE_DECL_FPUTC_UNLOCKED
# undef fputc # undef fputc
# define fputc(x,y) fputc_unlocked (x,y) # define fputc(x,y) fputc_unlocked (x,y)
#else # else
# define fputc_unlocked(x,y) fputc (x,y) # define fputc_unlocked(x,y) fputc (x,y)
#endif # endif
#if HAVE_DECL_FPUTS_UNLOCKED # if HAVE_DECL_FPUTS_UNLOCKED
# undef fputs # undef fputs
# define fputs(x,y) fputs_unlocked (x,y) # define fputs(x,y) fputs_unlocked (x,y)
#else # else
# define fputs_unlocked(x,y) fputs (x,y) # define fputs_unlocked(x,y) fputs (x,y)
#endif # endif
#if HAVE_DECL_FREAD_UNLOCKED # if HAVE_DECL_FREAD_UNLOCKED
# undef fread # undef fread
# define fread(w,x,y,z) fread_unlocked (w,x,y,z) # define fread(w,x,y,z) fread_unlocked (w,x,y,z)
#else # else
# define fread_unlocked(w,x,y,z) fread (w,x,y,z) # define fread_unlocked(w,x,y,z) fread (w,x,y,z)
#endif # endif
#if HAVE_DECL_FWRITE_UNLOCKED # if HAVE_DECL_FWRITE_UNLOCKED
# undef fwrite # undef fwrite
# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z) # define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
#else # else
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) # define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
#endif # endif
#if HAVE_DECL_GETC_UNLOCKED # if HAVE_DECL_GETC_UNLOCKED
# undef getc # undef getc
# define getc(x) getc_unlocked (x) # define getc(x) getc_unlocked (x)
#else # else
# define getc_unlocked(x) getc (x) # define getc_unlocked(x) getc (x)
#endif # endif
#if HAVE_DECL_GETCHAR_UNLOCKED # if HAVE_DECL_GETCHAR_UNLOCKED
# undef getchar # undef getchar
# define getchar() getchar_unlocked () # define getchar() getchar_unlocked ()
#else # else
# define getchar_unlocked() getchar () # define getchar_unlocked() getchar ()
#endif # endif
#if HAVE_DECL_PUTC_UNLOCKED # if HAVE_DECL_PUTC_UNLOCKED
# undef putc # undef putc
# define putc(x,y) putc_unlocked (x,y) # define putc(x,y) putc_unlocked (x,y)
#else # else
# define putc_unlocked(x,y) putc (x,y) # define putc_unlocked(x,y) putc (x,y)
#endif # endif
#if HAVE_DECL_PUTCHAR_UNLOCKED # if HAVE_DECL_PUTCHAR_UNLOCKED
# undef putchar # undef putchar
# define putchar(x) putchar_unlocked (x) # define putchar(x) putchar_unlocked (x)
#else # else
# define putchar_unlocked(x) putchar (x) # define putchar_unlocked(x) putchar (x)
#endif # endif
#undef flockfile # undef flockfile
#define flockfile(x) ((void) 0) # define flockfile(x) ((void) 0)
#undef ftrylockfile # undef ftrylockfile
#define ftrylockfile(x) 0 # define ftrylockfile(x) 0
#undef funlockfile # undef funlockfile
#define funlockfile(x) ((void) 0) # define funlockfile(x) ((void) 0)
#endif /* UNLOCKED_IO_H */ #endif /* UNLOCKED_IO_H */

189
lib/utimens.c Normal file
View File

@ -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);
}

3
lib/utimens.h Normal file
View File

@ -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]);

View File

@ -1,6 +1,6 @@
/* Report a memory allocation failure and exit. /* 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. Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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>
# include <config.h>
#endif
#include "xalloc.h" #include "xalloc.h"
@ -30,7 +28,6 @@
#include "gettext.h" #include "gettext.h"
#define _(msgid) gettext (msgid) #define _(msgid) gettext (msgid)
#define N_(msgid) msgid
void void
xalloc_die (void) xalloc_die (void)

View File

@ -1,7 +1,7 @@
/* xalloc.h -- malloc with out-of-memory checking /* xalloc.h -- malloc with out-of-memory checking
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 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 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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_ #ifndef XALLOC_H_
# define XALLOC_H_ # define XALLOC_H_
@ -46,13 +46,10 @@ extern "C" {
extern void xalloc_die (void) ATTRIBUTE_NORETURN; extern void xalloc_die (void) ATTRIBUTE_NORETURN;
void *xmalloc (size_t s); void *xmalloc (size_t s);
void *xnmalloc (size_t n, size_t s);
void *xzalloc (size_t s); void *xzalloc (size_t s);
void *xcalloc (size_t n, size_t s); void *xcalloc (size_t n, size_t s);
void *xrealloc (void *p, 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 *x2realloc (void *p, size_t *pn);
void *x2nrealloc (void *p, size_t *pn, size_t s);
void *xmemdup (void const *p, size_t s); void *xmemdup (void const *p, size_t s);
char *xstrdup (char const *str); char *xstrdup (char const *str);
@ -71,8 +68,203 @@ char *xstrdup (char const *str);
# define xalloc_oversized(n, s) \ # define xalloc_oversized(n, s) \
((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) ((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 # ifdef __cplusplus
} }
/* C++ does not allow conversions from void * to other pointer types
without a cast. Use templates to work around the problem when
possible. */
template <typename T> inline T *
xrealloc (T *p, size_t s)
{
return (T *) xrealloc ((void *) p, s);
}
template <typename T> inline T *
xnrealloc (T *p, size_t n, size_t s)
{
return (T *) xnrealloc ((void *) p, n, s);
}
template <typename T> inline T *
x2realloc (T *p, size_t *pn)
{
return (T *) x2realloc ((void *) p, pn);
}
template <typename T> inline T *
x2nrealloc (T *p, size_t *pn, size_t s)
{
return (T *) x2nrealloc ((void *) p, pn, s);
}
template <typename T> inline T *
xmemdup (T const *p, size_t s)
{
return (T *) xmemdup ((void const *) p, s);
}
# endif # endif

View File

@ -1,7 +1,8 @@
/* xmalloc.c -- malloc with out of memory checking /* xmalloc.c -- malloc with out of memory checking
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 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 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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>
# include <config.h>
#if ! HAVE_INLINE
# define static_inline
#endif #endif
#include "xalloc.h" #include "xalloc.h"
#undef static_inline
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -30,148 +33,36 @@
# define SIZE_MAX ((size_t) -1) # define SIZE_MAX ((size_t) -1)
#endif #endif
/* Allocate an array of N objects, each with S bytes of memory, /* 1 if calloc is known to be compatible with GNU calloc. This
dynamically, with error checking. S must be nonzero. */ matters if we are not also using the calloc module, which defines
HAVE_CALLOC and supports the GNU API even on non-GNU platforms. */
static inline void * #if defined HAVE_CALLOC || defined __GLIBC__
xnmalloc_inline (size_t n, size_t s) enum { HAVE_GNU_CALLOC = 1 };
{ #else
void *p; enum { HAVE_GNU_CALLOC = 0 };
if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0)) #endif
xalloc_die ();
return p;
}
void *
xnmalloc (size_t n, size_t s)
{
return xnmalloc_inline (n, s);
}
/* Allocate N bytes of memory dynamically, with error checking. */ /* Allocate N bytes of memory dynamically, with error checking. */
void * void *
xmalloc (size_t n) xmalloc (size_t n)
{ {
return xnmalloc_inline (n, 1); void *p = malloc (n);
} if (!p && n != 0)
/* Change the size of an allocated block of memory P to an array of N
objects each of S bytes, with error checking. S must be nonzero. */
static inline void *
xnrealloc_inline (void *p, size_t n, size_t s)
{
if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0))
xalloc_die (); xalloc_die ();
return p; 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, /* Change the size of an allocated block of memory P to N bytes,
with error checking. */ with error checking. */
void * void *
xrealloc (void *p, size_t n) xrealloc (void *p, size_t n)
{ {
return xnrealloc_inline (p, n, 1); p = realloc (p, n);
} if (!p && n != 0)
xalloc_die ();
return p;
/* If P is null, allocate a block of at least *PN such objects;
otherwise, reallocate P so that it contains more than *PN objects
each of S bytes. *PN must be nonzero unless P is null, and S must
be nonzero. Set *PN to the new number of objects, and return the
pointer to the new block. *PN is never set to zero, and the
returned pointer is never null.
Repeated reallocations are guaranteed to make progress, either by
allocating an initial block with a nonzero size, or by allocating a
larger block.
In the following implementation, nonzero sizes are doubled so that
repeated reallocations have O(N log N) overall cost rather than
O(N**2) cost, but the specification for this function does not
guarantee that sizes are doubled.
Here is an example of use:
int *p = NULL;
size_t used = 0;
size_t allocated = 0;
void
append_int (int value)
{
if (used == allocated)
p = x2nrealloc (p, &allocated, sizeof *p);
p[used++] = value;
}
This causes x2nrealloc to allocate a block of some nonzero size the
first time it is called.
To have finer-grained control over the initial size, set *PN to a
nonzero value before calling this function with P == NULL. For
example:
int *p = NULL;
size_t used = 0;
size_t allocated = 0;
size_t allocated1 = 1000;
void
append_int (int value)
{
if (used == allocated)
{
p = x2nrealloc (p, &allocated1, sizeof *p);
allocated = allocated1;
}
p[used++] = value;
}
*/
static inline void *
x2nrealloc_inline (void *p, size_t *pn, size_t s)
{
size_t n = *pn;
if (! p)
{
if (! n)
{
/* The approximate size to use for initial small allocation
requests, when the invoking code specifies an old size of
zero. 64 bytes is the largest "small" request for the
GNU C library malloc. */
enum { DEFAULT_MXFAST = 64 };
n = DEFAULT_MXFAST / s;
n += !n;
}
}
else
{
if (SIZE_MAX / 2 / s < n)
xalloc_die ();
n *= 2;
}
*pn = n;
return xrealloc (p, n * s);
}
void *
x2nrealloc (void *p, size_t *pn, size_t s)
{
return x2nrealloc_inline (p, pn, s);
} }
/* If P is null, allocate a block of at least *PN bytes; otherwise, /* 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 * void *
x2realloc (void *p, size_t *pn) 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. /* Allocate S bytes of zeroed memory dynamically, with error checking.
@ -204,8 +95,11 @@ xcalloc (size_t n, size_t s)
{ {
void *p; void *p;
/* Test for overflow, since some calloc implementations don't have /* Test for overflow, since some calloc implementations don't have
proper overflow checks. */ proper overflow checks. But omit overflow and size-zero tests if
if (xalloc_oversized (n, s) || (! (p = calloc (n, s)) && n != 0)) 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 (); xalloc_die ();
return p; return p;
} }

View File

@ -1,5 +1,6 @@
/* Copy memory area and return pointer after last written byte. /* Duplicate a bounded initial segment of a string, with out-of-memory
Copyright (C) 2003, 2004 Free Software Foundation, Inc. checking.
Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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 mempcpy #include <config.h>
# if HAVE_MEMPCPY /* Specification. */
#include "xstrndup.h"
/* Get mempcpy() declaration. */ #include <string.h>
# include <string.h> #include "xalloc.h"
# else /* 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
/* Get size_t */ STRING. */
# include <stddef.h> char *
xstrndup (const char *string, size_t n)
/* Copy N bytes of SRC to DEST, return pointer to bytes after the {
last written byte. */ char *s = strndup (string, n);
extern void *mempcpy (void *dest, const void *src, size_t n); if (! s)
xalloc_die ();
# endif return s;
}
#endif

View File

@ -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. Copyright (C) 2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, 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_STRNDUP
/* Get strndup() declaration. */
#include <string.h>
#else
#include <stddef.h> #include <stddef.h>
/* Return a newly allocated copy of at most N bytes of STRING. */ /* Return a newly allocated copy of at most N bytes of STRING.
extern char *strndup (const char *string, size_t n); In other words, return a copy of the initial segment of length N of
STRING. */
#endif extern char *xstrndup (const char *string, size_t n);

View File

@ -1,5 +1,6 @@
/* copyin.c - extract or list a cpio archive /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#include <system.h> #include <system.h>
@ -27,14 +29,14 @@
#include "defer.h" #include "defer.h"
#include <rmt.h> #include <rmt.h>
#ifndef FNM_PATHNAME #ifndef FNM_PATHNAME
#include <fnmatch.h> # include <fnmatch.h>
#endif #endif
#ifndef HAVE_LCHOWN #ifndef HAVE_LCHOWN
#define lchown chown # define lchown(f,u,g) 0
#endif #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); int in_file_des);
void void
@ -47,7 +49,7 @@ warn_junk_bytes (long bytes_skipped)
static int 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) FILE *rename_in)
{ {
char *str_res; /* Result for string function. */ char *str_res; /* Result for string function. */
@ -125,7 +127,7 @@ tape_skip_padding (int in_file_des, int offset)
static void 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) if (verbose_flag)
{ {
@ -176,15 +178,15 @@ list_file(struct new_cpio_header* file_hdr, int in_file_des)
#endif #endif
if (crc != file_hdr->c_chksum) 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_hdr->c_name, crc, file_hdr->c_chksum);
} }
} }
} }
static int static int
try_existing_file(struct new_cpio_header* file_hdr, int in_file_des, try_existing_file (struct cpio_file_stat* file_hdr, int in_file_des,
int *existing_dir) int *existing_dir)
{ {
struct stat file_stat; struct stat file_stat;
@ -238,7 +240,7 @@ struct deferment *deferments = NULL;
go on one list, although we could optimize this if necessary. */ go on one list, although we could optimize this if necessary. */
static void static void
defer_copyin (struct new_cpio_header *file_hdr) defer_copyin (struct cpio_file_stat *file_hdr)
{ {
struct deferment *d; struct deferment *d;
d = create_deferment (file_hdr); 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. */ list and create any which are links to this file. */
static void 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;
struct deferment *d_prev; struct deferment *d_prev;
@ -299,7 +301,7 @@ create_defered_links (struct new_cpio_header *file_hdr)
then create the other deferred links. */ then create the other deferred links. */
static int 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) int in_file_des)
{ {
struct deferment *d; struct deferment *d;
@ -307,7 +309,6 @@ create_defered_links_to_skipped (struct new_cpio_header *file_hdr,
int ino; int ino;
int maj; int maj;
int min; int min;
int link_res;
if (file_hdr->c_filesize == 0) if (file_hdr->c_filesize == 0)
{ {
/* The file doesn't have any data attached to it so we don't have /* 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; struct deferment *d;
int link_res; int link_res;
int out_file_des; 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) for (d = deferments; d != NULL; d = d->next)
{ {
/* Debian hack: A line, which could cause an endless loop, was /* Debian hack: A line, which could cause an endless loop, was
@ -385,34 +383,20 @@ create_final_defers ()
} }
if (out_file_des < 0) if (out_file_des < 0)
{ {
error (0, errno, "%s", d->header.c_name); open_error (d->header.c_name);
continue; continue;
} }
if (close (out_file_des) < 0) set_perms (out_file_des, &d->header);
error (0, errno, "%s", d->header.c_name);
if (close (out_file_des) < 0)
close_error (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);
}
} }
} }
static void 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. */ 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_toss_input (in_file_des, file_hdr->c_filesize);
tape_skip_padding (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 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) 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_toss_input (in_file_des, file_hdr->c_filesize);
tape_skip_padding (in_file_des, file_hdr->c_filesize); tape_skip_padding (in_file_des, file_hdr->c_filesize);
return; return;
@ -541,7 +525,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
if (archive_format == arf_crcascii) if (archive_format == arf_crcascii)
{ {
if (crc != file_hdr->c_chksum) 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_hdr->c_name, crc, file_hdr->c_chksum);
} }
tape_skip_padding (in_file_des, file_hdr->c_filesize); 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); write (out_file_des, "", 1);
delayed_seek_count = 0; delayed_seek_count = 0;
} }
set_perms (out_file_des, file_hdr);
if (close (out_file_des) < 0) 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 (archive_format == arf_crcascii)
{ {
if (crc != file_hdr->c_chksum) 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_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); tape_skip_padding (in_file_des, file_hdr->c_filesize);
if (file_hdr->c_nlink > 1 if (file_hdr->c_nlink > 1
&& (archive_format == arf_newascii || archive_format == arf_crcascii) ) && (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 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. */ int res; /* Result of various function calls. */
#ifdef HPUX_CDF #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, because the directory exists. If that's the case,
don't complain about it. */ don't complain about it. */
struct stat file_stat; struct stat file_stat;
if ( (errno != EEXIST) || if (errno != EEXIST)
(lstat (file_hdr->c_name, &file_stat) != 0) ||
!(S_ISDIR (file_stat.st_mode) ) )
{ {
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; 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; set_perms (-1, file_hdr);
if (utime (file_hdr->c_name, &times) < 0)
error (0, errno, "%s", file_hdr->c_name);
}
} }
static void 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. */ int res; /* Result of various function calls. */
@ -752,32 +702,27 @@ copyin_device(struct new_cpio_header* file_hdr)
} }
if (res < 0) if (res < 0)
{ {
error (0, errno, "%s", file_hdr->c_name); mknod_error (file_hdr->c_name);
return; return;
} }
if (!no_chown_flag) if (!no_chown_flag)
if ((chown (file_hdr->c_name, {
set_owner_flag ? set_owner : file_hdr->c_uid, uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid;
set_group_flag ? set_group : file_hdr->c_gid) < 0) gid_t gid = set_group_flag ? set_group : file_hdr->c_gid;
&& errno != EPERM) if ((chown (file_hdr->c_name, uid, gid) < 0)
error (0, errno, "%s", file_hdr->c_name); && errno != EPERM)
chown_error_details (file_hdr->c_name, uid, gid);
}
/* chown may have turned off some permissions we wanted. */ /* chown may have turned off some permissions we wanted. */
if (chmod (file_hdr->c_name, file_hdr->c_mode) < 0) 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) if (retain_time_flag)
{ set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime,
struct utimbuf times; /* For setting file times. */ file_hdr->c_mtime);
/* 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);
}
} }
static void 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. */ char *link_name = NULL; /* Name of hard and symbolic links. */
int res; /* Result of various function calls. */ 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) 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); free (link_name);
return; return;
} }
if (!no_chown_flag) if (!no_chown_flag)
if ((lchown (file_hdr->c_name, {
set_owner_flag ? set_owner : file_hdr->c_uid, uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid;
set_group_flag ? set_group : file_hdr->c_gid) < 0) gid_t gid = set_group_flag ? set_group : file_hdr->c_gid;
&& errno != EPERM) if ((lchown (file_hdr->c_name, uid, gid) < 0)
{ && errno != EPERM)
error (0, errno, "%s", file_hdr->c_name); chown_error_details (file_hdr->c_name, uid, gid);
} }
free (link_name); free (link_name);
} }
static void 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; 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) switch (file_hdr->c_mode & CP_IFMT)
{ {
case CP_IFREG: case CP_IFREG:
copyin_regular_file(file_hdr, in_file_des); copyin_regular_file (file_hdr, in_file_des);
break; break;
case CP_IFDIR: case CP_IFDIR:
copyin_directory(file_hdr, existing_dir); copyin_directory (file_hdr, existing_dir);
break; break;
case CP_IFCHR: case CP_IFCHR:
@ -850,12 +796,12 @@ copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
#ifdef CP_IFIFO #ifdef CP_IFIFO
case CP_IFIFO: case CP_IFIFO:
#endif #endif
copyin_device(file_hdr); copyin_device (file_hdr);
break; break;
#ifdef CP_IFLNK #ifdef CP_IFLNK
case CP_IFLNK: case CP_IFLNK:
copyin_link(file_hdr, in_file_des); copyin_link (file_hdr, in_file_des);
break; break;
#endif #endif
@ -876,7 +822,7 @@ static time_t current_time;
this file is a symbolic link to. */ this file is a symbolic link to. */
void 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 mbuf[11];
char tbuf[40]; char tbuf[40];
@ -897,7 +843,7 @@ long_format (struct new_cpio_header *file_hdr, char *link_name)
} }
tbuf[16] = '\0'; tbuf[16] = '\0';
printf ("%s %3u ", mbuf, file_hdr->c_nlink); printf ("%s %3lu ", mbuf, file_hdr->c_nlink);
if (numeric_uid) if (numeric_uid)
printf ("%-8u %-8u ", (unsigned int) file_hdr->c_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 if ((file_hdr->c_mode & CP_IFMT) == CP_IFCHR
|| (file_hdr->c_mode & CP_IFMT) == CP_IFBLK) || (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); file_hdr->c_rdev_min);
else else
printf ("%8lu ", file_hdr->c_filesize); printf ("%8"PRIuMAX" ", (uintmax_t) file_hdr->c_filesize);
printf ("%s ", tbuf + 4); printf ("%s ", tbuf + 4);
@ -997,7 +943,7 @@ read_pattern_file ()
pattern_fp = fopen (pattern_file_name, "r"); pattern_fp = fopen (pattern_file_name, "r");
if (pattern_fp == NULL) 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) while (ds_fgetstr (pattern_fp, &pattern_name, '\n') != NULL)
{ {
if (new_num_patterns >= max_new_patterns) if (new_num_patterns >= max_new_patterns)
@ -1011,7 +957,7 @@ read_pattern_file ()
++new_num_patterns; ++new_num_patterns;
} }
if (ferror (pattern_fp) || fclose (pattern_fp) == EOF) 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) for (i = 0; i < num_patterns; ++i)
new_save_patterns[i] = save_patterns[i]; new_save_patterns[i] = save_patterns[i];
@ -1020,6 +966,52 @@ read_pattern_file ()
num_patterns = new_num_patterns; 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. */ descriptor IN_DES into FILE_HDR. */
void 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. */ long bytes_skipped = 0; /* Bytes of junk found before magic number. */
/* Search for a valid 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; 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) while (1)
{ {
if (append_flag) if (append_flag)
last_header_start = input_bytes - io_block_size last_header_start = input_bytes - io_block_size
+ (in_buff - input_buffer) - 6; + (in_buff - input_buffer) - 6;
if (archive_format == arf_newascii if (archive_format == arf_newascii
&& !strncmp ((char *) file_hdr, "070701", 6)) && !strncmp (magic.str, "070701", 6))
{ {
if (bytes_skipped > 0) if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped); warn_junk_bytes (bytes_skipped);
file_hdr->c_magic = 070701;
read_in_new_ascii (file_hdr, in_des); read_in_new_ascii (file_hdr, in_des);
break; break;
} }
if (archive_format == arf_crcascii if (archive_format == arf_crcascii
&& !strncmp ((char *) file_hdr, "070702", 6)) && !strncmp (magic.str, "070702", 6))
{ {
if (bytes_skipped > 0) if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped); warn_junk_bytes (bytes_skipped);
file_hdr->c_magic = 070702;
read_in_new_ascii (file_hdr, in_des); read_in_new_ascii (file_hdr, in_des);
break; break;
} }
if ( (archive_format == arf_oldascii || archive_format == arf_hpoldascii) if ( (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
&& !strncmp ((char *) file_hdr, "070707", 6)) && !strncmp (magic.str, "070707", 6))
{ {
if (bytes_skipped > 0) if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped); warn_junk_bytes (bytes_skipped);
file_hdr->c_magic = 070707;
read_in_old_ascii (file_hdr, in_des); read_in_old_ascii (file_hdr, in_des);
break; break;
} }
if ( (archive_format == arf_binary || archive_format == arf_hpbinary) if ( (archive_format == arf_binary || archive_format == arf_hpbinary)
&& (file_hdr->c_magic == 070707 && (magic.num == 070707
|| file_hdr->c_magic == swab_short ((unsigned short) 070707))) || magic.num == swab_short ((unsigned short) 070707)))
{ {
/* Having to skip 1 byte because of word alignment is normal. */ /* Having to skip 1 byte because of word alignment is normal. */
if (bytes_skipped > 0) if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped); warn_junk_bytes (bytes_skipped);
file_hdr->c_magic = 070707;
read_in_binary (file_hdr, in_des); read_in_binary (file_hdr, &magic.old_header, in_des);
break; break;
} }
bytes_skipped++; bytes_skipped++;
bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5); memmove (magic.str, magic.str + 1, 5);
tape_buffered_read ((char *) file_hdr + 5, in_des, 1L); 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. */ already filled in. */
void 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 dev;
unsigned long rdev;
tape_buffered_read (ascii_header, in_des, 70L); tape_buffered_read (ascii_header.c_dev, in_des,
ascii_header[70] = '\0'; sizeof ascii_header - sizeof ascii_header.c_magic);
sscanf (ascii_header, dev = FROM_OCTAL (ascii_header.c_dev);
"%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);
file_hdr->c_dev_maj = major (dev); file_hdr->c_dev_maj = major (dev);
file_hdr->c_dev_min = minor (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. */ /* Read file name from input. */
if (file_hdr->c_name != NULL) if (file_hdr->c_name != NULL)
free (file_hdr->c_name); 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. */ already filled in. */
void 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]; struct new_ascii_header ascii_header;
tape_buffered_read (ascii_header, in_des, 104L); tape_buffered_read (ascii_header.c_ino, in_des,
ascii_header[104] = '\0'; sizeof ascii_header - sizeof ascii_header.c_magic);
sscanf (ascii_header,
"%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx", file_hdr->c_ino = FROM_HEX (ascii_header.c_ino);
&file_hdr->c_ino, &file_hdr->c_mode, &file_hdr->c_uid, file_hdr->c_mode = FROM_HEX (ascii_header.c_mode);
&file_hdr->c_gid, &file_hdr->c_nlink, &file_hdr->c_mtime, file_hdr->c_uid = FROM_HEX (ascii_header.c_uid);
&file_hdr->c_filesize, &file_hdr->c_dev_maj, &file_hdr->c_dev_min, file_hdr->c_gid = FROM_HEX (ascii_header.c_gid);
&file_hdr->c_rdev_maj, &file_hdr->c_rdev_min, &file_hdr->c_namesize, file_hdr->c_nlink = FROM_HEX (ascii_header.c_nlink);
&file_hdr->c_chksum); 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. */ /* Read file name from input. */
if (file_hdr->c_name != NULL) if (file_hdr->c_name != NULL)
free (file_hdr->c_name); 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. */ number, device, and inode number), which are already filled in. */
void 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 tape_buffered_read (((char *) short_hdr) + 6, in_des,
it into the argument long header. */ sizeof *short_hdr - 6 /* = 20 */);
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);
/* If the magic number is byte swapped, fix the header. */ /* If the magic number is byte swapped, fix the header. */
if (file_hdr->c_magic == swab_short ((unsigned short) 070707)) 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); swab_array ((char *) &short_hdr, 13);
} }
file_hdr->c_dev_maj = major (short_hdr.c_dev); file_hdr->c_dev_maj = major (short_hdr->c_dev);
file_hdr->c_dev_min = minor (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_ino = short_hdr->c_ino;
file_hdr->c_mode = short_hdr.c_mode; file_hdr->c_mode = short_hdr->c_mode;
file_hdr->c_uid = short_hdr.c_uid; file_hdr->c_uid = short_hdr->c_uid;
file_hdr->c_gid = short_hdr.c_gid; file_hdr->c_gid = short_hdr->c_gid;
file_hdr->c_nlink = short_hdr.c_nlink; file_hdr->c_nlink = short_hdr->c_nlink;
file_hdr->c_rdev_maj = major (short_hdr.c_rdev); file_hdr->c_rdev_maj = major (short_hdr->c_rdev);
file_hdr->c_rdev_min = minor (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 file_hdr->c_mtime = (unsigned long) short_hdr->c_mtimes[0] << 16
| short_hdr.c_mtimes[1]; | short_hdr->c_mtimes[1];
file_hdr->c_namesize = short_hdr.c_namesize; file_hdr->c_namesize = short_hdr->c_namesize;
file_hdr->c_filesize = (unsigned long) short_hdr.c_filesizes[0] << 16 file_hdr->c_filesize = (unsigned long) short_hdr->c_filesizes[0] << 16
| short_hdr.c_filesizes[1]; | short_hdr->c_filesizes[1];
/* Read file name from input. */ /* Read file name from input. */
if (file_hdr->c_name != NULL) if (file_hdr->c_name != NULL)
@ -1342,15 +1352,18 @@ void
process_copy_in () process_copy_in ()
{ {
char done = false; /* True if trailer reached. */ char done = false; /* True if trailer reached. */
FILE *tty_in; /* Interactive file for rename option. */ FILE *tty_in = NULL; /* Interactive file for rename option. */
FILE *tty_out; /* Interactive file for rename option. */ FILE *tty_out = NULL; /* Interactive file for rename option. */
FILE *rename_in; /* Batch file for rename option. */ FILE *rename_in = NULL; /* Batch file for rename option. */
struct stat file_stat; /* Output file stat record. */ 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. */ int in_file_des; /* Input file descriptor. */
char skip_file; /* Flag for use with patterns. */ char skip_file; /* Flag for use with patterns. */
int i; /* Loop index variable. */ int i; /* Loop index variable. */
umask (0); /* Reset umask to preserve modes of
created files */
/* Initialize the copy in. */ /* Initialize the copy in. */
if (pattern_file_name) if (pattern_file_name)
{ {
@ -1418,7 +1431,7 @@ process_copy_in ()
#ifdef DEBUG_CPIO #ifdef DEBUG_CPIO
if (debug_flag) if (debug_flag)
{ {
struct new_cpio_header *h; struct cpio_file_stat *h;
h = &file_hdr; h = &file_hdr;
fprintf (stderr, fprintf (stderr,
"magic = 0%o, ino = %d, mode = 0%o, uid = %d, gid = %d\n", "magic = 0%o, ino = %d, mode = 0%o, uid = %d, gid = %d\n",
@ -1437,37 +1450,15 @@ process_copy_in ()
} }
#endif #endif
/* Is this the header for the TRAILER file? */ /* 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; done = true;
break; break;
} }
/* Do we have to ignore absolute paths, and if so, does the filename cpio_safer_name_suffix (file_hdr.c_name, false, !no_abs_paths_flag,
have an absolute path? */ false);
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));
}
}
/* Does the file name match one of the given patterns? */ /* Does the file name match one of the given patterns? */
if (num_patterns <= 0) if (num_patterns <= 0)
skip_file = false; skip_file = false;
@ -1530,7 +1521,7 @@ process_copy_in ()
tape_skip_padding (in_file_des, file_hdr.c_filesize); tape_skip_padding (in_file_des, file_hdr.c_filesize);
if (crc != file_hdr.c_chksum) 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_hdr.c_name, crc, file_hdr.c_chksum);
} }
/* Debian hack: -v and -V now work with --only-verify-crc. /* Debian hack: -v and -V now work with --only-verify-crc.

View File

@ -1,5 +1,6 @@
/* copyout.c - create a cpio archive /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#include <system.h> #include <system.h>
@ -26,14 +28,15 @@
#include "extern.h" #include "extern.h"
#include "defer.h" #include "defer.h"
#include <rmt.h> #include <rmt.h>
#include <paxlib.h>
/* Read FILE_SIZE bytes of FILE_NAME from IN_FILE_DES and /* Read FILE_SIZE bytes of FILE_NAME from IN_FILE_DES and
compute and return a checksum for them. */ 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) read_for_checksum (int in_file_des, int file_size, char *file_name)
{ {
unsigned long crc; unsigned int crc;
char buf[BUFSIZ]; char buf[BUFSIZ];
int bytes_left; int bytes_left;
int bytes_read; int bytes_read;
@ -65,13 +68,8 @@ read_for_checksum (int in_file_des, int file_size, char *file_name)
static void static void
tape_clear_rest_of_block (int out_file_des) tape_clear_rest_of_block (int out_file_des)
{ {
while (output_size < io_block_size) write_nuls_to_file (io_block_size - output_size, out_file_des,
{ tape_buffered_write);
if ((io_block_size - output_size) > 512)
tape_buffered_write (zeros_512, out_file_des, 512);
else
tape_buffered_write (zeros_512, out_file_des, io_block_size - output_size);
}
} }
/* Write NULs on OUT_FILE_DES to move from OFFSET (the current location) /* 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 static void
tape_pad_output (int out_file_des, int offset) tape_pad_output (int out_file_des, int offset)
{ {
int pad; size_t pad;
if (archive_format == arf_newascii || archive_format == arf_crcascii) if (archive_format == arf_newascii || archive_format == arf_crcascii)
pad = (4 - (offset % 4)) % 4; pad = (4 - (offset % 4)) % 4;
@ -92,7 +90,7 @@ tape_pad_output (int out_file_des, int offset)
pad = 0; pad = 0;
if (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. */ already been defered. */
static int 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; struct deferment *d;
int ino; 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? */ we already seen and defered all of the other links? */
static int static int
last_link (struct new_cpio_header *file_hdr) last_link (struct cpio_file_stat *file_hdr)
{ {
int other_files_sofar; int other_files_sofar;
@ -150,7 +148,7 @@ last_link (struct new_cpio_header *file_hdr)
list. */ list. */
static void static void
add_link_defer (struct new_cpio_header *file_hdr) add_link_defer (struct cpio_file_stat *file_hdr)
{ {
struct deferment *d; struct deferment *d;
d = create_deferment (file_hdr); 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 /* 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. 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 Write the other links into the archive, and remove them from the
deferouts list. */ deferouts list. */
static void 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;
struct deferment *d_prev; 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. */ for writeout_final_defers() to call. */
static void 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; int in_file_des;
struct new_cpio_header file_hdr; struct cpio_file_stat file_hdr;
struct utimbuf times; /* For setting file times. */
/* Initialize this in case it has members we don't know to set. */
bzero (&times, sizeof (struct utimbuf));
file_hdr = *header; file_hdr = *header;
@ -222,7 +217,7 @@ writeout_defered_file (struct new_cpio_header *header, int out_file_des)
O_RDONLY | O_BINARY, 0); O_RDONLY | O_BINARY, 0);
if (in_file_des < 0) if (in_file_des < 0)
{ {
error (0, errno, "%s", header->c_name); open_error (header->c_name);
return; return;
} }
@ -231,8 +226,10 @@ writeout_defered_file (struct new_cpio_header *header, int out_file_des)
file_hdr.c_filesize, file_hdr.c_filesize,
header->c_name); header->c_name);
write_out_header (&file_hdr, out_file_des); if (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); 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); warn_if_file_changed(header->c_name, file_hdr.c_filesize, file_hdr.c_mtime);
if (archive_format == arf_tar || archive_format == arf_ustar) 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); 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) if (reset_time_flag)
{ set_file_times (in_file_des, file_hdr.c_name, file_hdr.c_mtime,
times.actime = file_hdr.c_mtime; file_hdr.c_mtime);
times.modtime = file_hdr.c_mtime; if (close (in_file_des) < 0)
/* Debian hack: Silently ignore EROFS because reading the file close_error (header->c_name);
won't have upset its timestamp if it's on a read-only
filesystem. This has been submitted as a suggestion to
"bug-gnu-utils@prep.ai.mit.edu". -BEM */
if (utime (file_hdr.c_name, &times) < 0
&& errno != EROFS)
error (0, errno, "%s", file_hdr.c_name);
}
return;
} }
/* When writing newc and crc format archives we defer multiply linked /* When writing newc and crc format archives we defer multiply linked
@ -279,7 +266,7 @@ writeout_final_defers (int out_des)
} }
else else
{ {
struct new_cpio_header file_hdr; struct cpio_file_stat file_hdr;
file_hdr = d->header; file_hdr = d->header;
file_hdr.c_filesize = 0; file_hdr.c_filesize = 0;
write_out_header (&file_hdr, out_des); write_out_header (&file_hdr, out_des);
@ -288,154 +275,317 @@ writeout_final_defers (int 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
to_ascii_or_warn (char *where, uintmax_t n, size_t digits,
unsigned logbase,
const char *filename, const char *fieldname)
{
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))
{
field_width_error (filename, fieldname);
return 1;
}
return 0;
}
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:
#endif
#ifdef CP_IFIFO
case CP_IFIFO:
#endif
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;
}
}
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)
{
field_width_error (file_hdr->c_name, _("name size"));
return 1;
}
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)
{
field_width_error (file_hdr->c_name, _("file size"));
return 1;
}
/* Output the file header. */
tape_buffered_write ((char *) &short_hdr, out_des, 26);
/* Write file name to output. */
tape_buffered_write (file_hdr->c_name, out_des, file_hdr->c_namesize);
tape_pad_output (out_des, file_hdr->c_namesize + 26);
return 0;
}
/* Write out header FILE_HDR, including the file name, to file /* Write out header FILE_HDR, including the file name, to file
descriptor OUT_DES. */ descriptor OUT_DES. */
void int
write_out_header (struct new_cpio_header *file_hdr, int out_des) write_out_header (struct cpio_file_stat *file_hdr, int out_des)
{ {
if (archive_format == arf_newascii || archive_format == arf_crcascii) dev_t dev;
dev_t rdev;
switch (archive_format)
{ {
char ascii_header[112]; case arf_newascii:
char *magic_string; return write_out_new_ascii_header ("070701", file_hdr, out_des);
if (archive_format == arf_crcascii) case arf_crcascii:
magic_string = "070702"; return write_out_new_ascii_header ("070702", file_hdr, out_des);
else
magic_string = "070701"; case arf_oldascii:
sprintf (ascii_header, return write_out_old_ascii_header (makedev (file_hdr->c_dev_maj,
"%6s%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx", file_hdr->c_dev_min),
magic_string, makedev (file_hdr->c_rdev_maj,
file_hdr->c_ino, file_hdr->c_mode, file_hdr->c_uid, file_hdr->c_rdev_min),
file_hdr->c_gid, file_hdr->c_nlink, file_hdr->c_mtime, file_hdr, out_des);
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, case arf_hpoldascii:
file_hdr->c_chksum); hp_compute_dev (file_hdr, &dev, &rdev);
tape_buffered_write (ascii_header, out_des, 110L); return write_out_old_ascii_header (dev, rdev, file_hdr, out_des);
/* Write file name to output. */ case arf_tar:
tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize); case arf_ustar:
tape_pad_output (out_des, file_hdr->c_namesize + 110); if (is_tar_filename_too_long (file_hdr->c_name))
}
else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
{
char ascii_header[78];
dev_t dev;
dev_t rdev;
if (archive_format == arf_oldascii)
{ {
dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min); error (0, 0, _("%s: file name too long"), file_hdr->c_name);
rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min); return 1;
}
else
{
/* HP/UX cpio creates archives that look just like ordinary archives,
but for devices it sets major = 0, minor = 1, and puts the
actual major/minor number in the filesize field. */
switch (file_hdr->c_mode & CP_IFMT)
{
case CP_IFCHR:
case CP_IFBLK:
#ifdef CP_IFSOCK
case CP_IFSOCK:
#endif
#ifdef CP_IFIFO
case CP_IFIFO:
#endif
file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
file_hdr->c_rdev_min);
rdev = 1;
break;
default:
dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
break;
}
} }
write_out_tar_header (file_hdr, out_des); /* FIXME: No error checking */
return 0;
if ((warn_option & CPIO_WARN_TRUNCATE) && (file_hdr->c_ino >> 16) != 0) case arf_binary:
error (0, 0, _("%s: truncating inode number"), file_hdr->c_name); return write_out_binary_header (makedev (file_hdr->c_rdev_maj,
file_hdr->c_rdev_min),
file_hdr, out_des);
/* Debian hack: The type of dev_t has changed in glibc. Fixed output case arf_hpbinary:
to ensure that a long int is passed to sprintf. This has been hp_compute_dev (file_hdr, &dev, &rdev);
reported to "bug-gnu-utils@prep.ai.mit.edu". (1998/5/26) -BEM */ /* FIXME: dev ignored. Should it be? */
sprintf (ascii_header, return write_out_binary_header (rdev, file_hdr, out_des);
"%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. */ default:
tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize); abort ();
} }
else if (archive_format == arf_tar || archive_format == arf_ustar) }
{
write_out_tar_header (file_hdr, out_des);
}
else
{
struct old_cpio_header short_hdr;
short_hdr.c_magic = 070707; static void
short_hdr.c_dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min); assign_string (char **pvar, char *value)
{
if ((warn_option & CPIO_WARN_TRUNCATE) && (file_hdr->c_ino >> 16) != 0) char *p = xrealloc (*pvar, strlen (value) + 1);
error (0, 0, _("%s: truncating inode number"), file_hdr->c_name); strcpy (p, value);
*pvar = p;
short_hdr.c_ino = file_hdr->c_ino & 0xFFFF;
short_hdr.c_mode = file_hdr->c_mode & 0xFFFF;
short_hdr.c_uid = file_hdr->c_uid & 0xFFFF;
short_hdr.c_gid = file_hdr->c_gid & 0xFFFF;
short_hdr.c_nlink = file_hdr->c_nlink & 0xFFFF;
if (archive_format != arf_hpbinary)
short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
else
{
switch (file_hdr->c_mode & CP_IFMT)
{
/* HP/UX cpio creates archives that look just like ordinary
archives, but for devices it sets major = 0, minor = 1, and
puts the actual major/minor number in the filesize field. */
case CP_IFCHR:
case CP_IFBLK:
#ifdef CP_IFSOCK
case CP_IFSOCK:
#endif
#ifdef CP_IFIFO
case CP_IFIFO:
#endif
file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
file_hdr->c_rdev_min);
short_hdr.c_rdev = makedev (0, 1);
break;
default:
short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj,
file_hdr->c_rdev_min);
break;
}
}
short_hdr.c_mtimes[0] = file_hdr->c_mtime >> 16;
short_hdr.c_mtimes[1] = file_hdr->c_mtime & 0xFFFF;
short_hdr.c_namesize = file_hdr->c_namesize & 0xFFFF;
short_hdr.c_filesizes[0] = file_hdr->c_filesize >> 16;
short_hdr.c_filesizes[1] = file_hdr->c_filesize & 0xFFFF;
/* Output the file header. */
tape_buffered_write ((char *) &short_hdr, out_des, 26L);
/* Write file name to output. */
tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
tape_pad_output (out_des, file_hdr->c_namesize + 26);
}
} }
/* Read a list of file names from the standard input /* Read a list of file names from the standard input
@ -447,17 +597,14 @@ process_copy_out ()
{ {
int res; /* Result of functions. */ int res; /* Result of functions. */
dynamic_string input_name; /* Name of file read from stdin. */ 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 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 in_file_des; /* Source file descriptor. */
int out_file_des; /* Output file descriptor. */ int out_file_des; /* Output file descriptor. */
char *p; char *orig_file_name = NULL;
/* Initialize the copy out. */ /* Initialize the copy out. */
ds_init (&input_name, 128); 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; file_hdr.c_magic = 070707;
/* Check whether the output file might be a tape. */ /* Check whether the output file might be a tape. */
@ -497,55 +644,11 @@ process_copy_out ()
/* Process next file. */ /* Process next file. */
if ((*xstat) (input_name.ds_string, &file_stat) < 0) if ((*xstat) (input_name.ds_string, &file_stat) < 0)
error (0, errno, "%s", input_name.ds_string); stat_error (input_name.ds_string);
else else
{ {
/* Set values in output header. */ /* Set values in output header. */
file_hdr.c_dev_maj = major (file_stat.st_dev); stat_to_cpio (&file_hdr, &file_stat);
file_hdr.c_dev_min = minor (file_stat.st_dev);
file_hdr.c_ino = file_stat.st_ino;
/* For POSIX systems that don't define the S_IF macros,
we can't assume that S_ISfoo means the standard Unix
S_IFfoo bit(s) are set. So do it manually, with a
different name. Bleah. */
file_hdr.c_mode = (file_stat.st_mode & 07777);
if (S_ISREG (file_stat.st_mode))
file_hdr.c_mode |= CP_IFREG;
else if (S_ISDIR (file_stat.st_mode))
file_hdr.c_mode |= CP_IFDIR;
#ifdef S_ISBLK
else if (S_ISBLK (file_stat.st_mode))
file_hdr.c_mode |= CP_IFBLK;
#endif
#ifdef S_ISCHR
else if (S_ISCHR (file_stat.st_mode))
file_hdr.c_mode |= CP_IFCHR;
#endif
#ifdef S_ISFIFO
else if (S_ISFIFO (file_stat.st_mode))
file_hdr.c_mode |= CP_IFIFO;
#endif
#ifdef S_ISLNK
else if (S_ISLNK (file_stat.st_mode))
file_hdr.c_mode |= CP_IFLNK;
#endif
#ifdef S_ISSOCK
else if (S_ISSOCK (file_stat.st_mode))
file_hdr.c_mode |= CP_IFSOCK;
#endif
#ifdef S_ISNWK
else if (S_ISNWK (file_stat.st_mode))
file_hdr.c_mode |= CP_IFNWK;
#endif
file_hdr.c_uid = file_stat.st_uid;
file_hdr.c_gid = file_stat.st_gid;
file_hdr.c_nlink = file_stat.st_nlink;
file_hdr.c_rdev_maj = major (file_stat.st_rdev);
file_hdr.c_rdev_min = minor (file_stat.st_rdev);
file_hdr.c_mtime = file_stat.st_mtime;
file_hdr.c_filesize = file_stat.st_size;
file_hdr.c_chksum = 0;
file_hdr.c_tar_linkname = NULL;
if (archive_format == arf_tar || archive_format == arf_ustar) if (archive_format == arf_tar || archive_format == arf_ustar)
{ {
@ -562,17 +665,12 @@ process_copy_out ()
} }
} }
/* Strip leading `./' from the filename. */ assign_string (&orig_file_name, input_name.ds_string);
p = input_name.ds_string; cpio_safer_name_suffix (input_name.ds_string, false,
while (*p == '.' && *(p + 1) == '/') !no_abs_paths_flag, true);
{
++p;
while (*p == '/')
++p;
}
#ifndef HPUX_CDF #ifndef HPUX_CDF
file_hdr.c_name = p; file_hdr.c_name = input_name.ds_string;
file_hdr.c_namesize = strlen (p) + 1; file_hdr.c_namesize = strlen (input_name.ds_string) + 1;
#else #else
if ( (archive_format != arf_tar) && (archive_format != arf_ustar) ) 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 properly recreate the directory as hidden (in case the
files of a directory go into the archive before the files of a directory go into the archive before the
directory itself (e.g from "find ... -depth ... | cpio")). */ 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; file_hdr.c_namesize = strlen (file_hdr.c_name) + 1;
} }
else else
@ -589,18 +687,11 @@ process_copy_out ()
/* We don't mark CDF's in tar files. We assume the "hidden" /* We don't mark CDF's in tar files. We assume the "hidden"
directory will always go into the archive before any of directory will always go into the archive before any of
its files. */ its files. */
file_hdr.c_name = p; file_hdr.c_name = input_name.ds_string;
file_hdr.c_namesize = strlen (p) + 1; file_hdr.c_namesize = strlen (input_name.ds_string) + 1;
} }
#endif #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. */ /* Copy the named file to the output. */
switch (file_hdr.c_mode & CP_IFMT) switch (file_hdr.c_mode & CP_IFMT)
{ {
@ -613,7 +704,8 @@ process_copy_out ()
file_hdr.c_dev_min))) file_hdr.c_dev_min)))
{ {
file_hdr.c_tar_linkname = otherfile; 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; break;
} }
} }
@ -630,50 +722,45 @@ process_copy_out ()
break; break;
} }
} }
in_file_des = open (input_name.ds_string, in_file_des = open (orig_file_name,
O_RDONLY | O_BINARY, 0); O_RDONLY | O_BINARY, 0);
if (in_file_des < 0) if (in_file_des < 0)
{ {
error (0, errno, "%s", input_name.ds_string); open_error (orig_file_name);
continue; continue;
} }
if (archive_format == arf_crcascii) if (archive_format == arf_crcascii)
file_hdr.c_chksum = read_for_checksum (in_file_des, file_hdr.c_chksum = read_for_checksum (in_file_des,
file_hdr.c_filesize, file_hdr.c_filesize,
input_name.ds_string); orig_file_name);
write_out_header (&file_hdr, out_file_des); if (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); continue;
warn_if_file_changed(input_name.ds_string, file_hdr.c_filesize, 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); file_hdr.c_mtime);
if (archive_format == arf_tar || archive_format == arf_ustar) 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); file_hdr.c_dev_min);
tape_pad_output (out_file_des, file_hdr.c_filesize); 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) if (reset_time_flag)
{ set_file_times (in_file_des,
times.actime = file_stat.st_atime; orig_file_name,
times.modtime = file_stat.st_mtime; file_stat.st_atime, file_stat.st_mtime);
/* Debian hack: Silently ignore EROFS because if (close (in_file_des) < 0)
reading the file won't have upset its timestamp close_error (orig_file_name);
if it's on a read-only filesystem. This has been
submitted as a suggestion to
"bug-gnu-utils@prep.ai.mit.edu". -BEM */
if (utime (file_hdr.c_name, &times) < 0
&& errno != EROFS)
error (0, errno, "%s", file_hdr.c_name);
}
break; break;
case CP_IFDIR: case CP_IFDIR:
file_hdr.c_filesize = 0; file_hdr.c_filesize = 0;
write_out_header (&file_hdr, out_file_des); if (write_out_header (&file_hdr, out_file_des))
continue;
break; break;
case CP_IFCHR: case CP_IFCHR:
@ -687,7 +774,7 @@ process_copy_out ()
if (archive_format == arf_tar) if (archive_format == arf_tar)
{ {
error (0, 0, _("%s not dumped: not a regular file"), error (0, 0, _("%s not dumped: not a regular file"),
file_hdr.c_name); orig_file_name);
continue; continue;
} }
else if (archive_format == arf_ustar) 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 = (file_stat.st_mode & 07777);
file_hdr.c_mode |= CP_IFREG; file_hdr.c_mode |= CP_IFREG;
file_hdr.c_tar_linkname = otherfile; 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; 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_dev_maj, file_hdr.c_dev_min);
} }
file_hdr.c_filesize = 0; file_hdr.c_filesize = 0;
write_out_header (&file_hdr, out_file_des); if (write_out_header (&file_hdr, out_file_des))
continue;
break; break;
#ifdef CP_IFLNK #ifdef CP_IFLNK
@ -718,14 +807,18 @@ process_copy_out ()
char *link_name = (char *) xmalloc (file_stat.st_size + 1); char *link_name = (char *) xmalloc (file_stat.st_size + 1);
int link_size; int link_size;
link_size = readlink (input_name.ds_string, link_name, link_size = readlink (orig_file_name, link_name,
file_stat.st_size); file_stat.st_size);
if (link_size < 0) if (link_size < 0)
{ {
error (0, errno, "%s", input_name.ds_string); readlink_warn (orig_file_name);
free (link_name); free (link_name);
continue; 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; file_hdr.c_filesize = link_size;
if (archive_format == arf_tar || archive_format == arf_ustar) if (archive_format == arf_tar || archive_format == arf_ustar)
{ {
@ -738,12 +831,14 @@ process_copy_out ()
{ {
link_name[link_size] = '\0'; link_name[link_size] = '\0';
file_hdr.c_tar_linkname = link_name; 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 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_buffered_write (link_name, out_file_des, link_size);
tape_pad_output (out_file_des, link_size); tape_pad_output (out_file_des, link_size);
} }
@ -753,16 +848,18 @@ process_copy_out ()
#endif #endif
default: 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) if (verbose_flag)
fprintf (stderr, "%s\n", input_name.ds_string); fprintf (stderr, "%s\n", orig_file_name);
if (dot_flag) if (dot_flag)
fputc ('.', stderr); fputc ('.', stderr);
} }
} }
free (orig_file_name);
writeout_final_defers(out_file_des); writeout_final_defers(out_file_des);
/* The collection is complete; append the trailer. */ /* The collection is complete; append the trailer. */
file_hdr.c_ino = 0; file_hdr.c_ino = 0;
@ -779,14 +876,11 @@ process_copy_out ()
file_hdr.c_filesize = 0; file_hdr.c_filesize = 0;
file_hdr.c_namesize = 11; 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) if (archive_format != arf_tar && archive_format != arf_ustar)
write_out_header (&file_hdr, out_file_des); write_out_header (&file_hdr, out_file_des);
else else
{ write_nuls_to_file (1024, out_file_des, tape_buffered_write);
tape_buffered_write (zeros_512, out_file_des, 512);
tape_buffered_write (zeros_512, out_file_des, 512);
}
/* Fill up the output block. */ /* Fill up the output block. */
tape_clear_rest_of_block (out_file_des); tape_clear_rest_of_block (out_file_des);

View File

@ -1,5 +1,6 @@
/* copypass.c - cpio copy pass sub-function. /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#include <system.h> #include <system.h>
@ -24,11 +26,23 @@
#include "cpiohdr.h" #include "cpiohdr.h"
#include "dstring.h" #include "dstring.h"
#include "extern.h" #include "extern.h"
#include "paxlib.h"
#ifndef HAVE_LCHOWN #ifndef HAVE_LCHOWN
#define lchown chown # define lchown chown
#endif #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'. /* Copy files listed on the standard input into directory `directory_name'.
If `link_flag', link instead of copying. */ If `link_flag', link instead of copying. */
@ -40,7 +54,6 @@ process_copy_pass ()
int dirname_len; /* Length of `directory_name'. */ int dirname_len; /* Length of `directory_name'. */
int res; /* Result of functions. */ int res; /* Result of functions. */
char *slash; /* For moving past slashes in input name. */ 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 in_file_stat; /* Stat record for input file. */
struct stat out_file_stat; /* Stat record for output file. */ struct stat out_file_stat; /* Stat record for output file. */
int in_file_des; /* Input file descriptor. */ int in_file_des; /* Input file descriptor. */
@ -51,6 +64,9 @@ process_copy_pass ()
int cdf_char; int cdf_char;
#endif #endif
umask (0); /* Reset umask to preserve modes of
created files */
/* Initialize the copy pass. */ /* Initialize the copy pass. */
dirname_len = strlen (directory_name); dirname_len = strlen (directory_name);
ds_init (&input_name, 128); ds_init (&input_name, 128);
@ -58,8 +74,6 @@ process_copy_pass ()
strcpy (output_name.ds_string, directory_name); strcpy (output_name.ds_string, directory_name);
output_name.ds_string[dirname_len] = '/'; output_name.ds_string[dirname_len] = '/';
output_is_seekable = true; 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. */ /* Copy files with names read from stdin. */
while (ds_fgetstr (stdin, &input_name, name_end) != NULL) 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) 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; continue;
} }
@ -150,7 +164,7 @@ process_copy_pass ()
O_RDONLY | O_BINARY, 0); O_RDONLY | O_BINARY, 0);
if (in_file_des < 0) if (in_file_des < 0)
{ {
error (0, errno, "%s", input_name.ds_string); open_error (input_name.ds_string);
continue; continue;
} }
out_file_des = open (output_name.ds_string, out_file_des = open (output_name.ds_string,
@ -163,7 +177,7 @@ process_copy_pass ()
} }
if (out_file_des < 0) if (out_file_des < 0)
{ {
error (0, errno, "%s", output_name.ds_string); open_error (output_name.ds_string);
close (in_file_des); close (in_file_des);
continue; continue;
} }
@ -179,43 +193,28 @@ process_copy_pass ()
write (out_file_des, "", 1); write (out_file_des, "", 1);
delayed_seek_count = 0; delayed_seek_count = 0;
} }
if (close (in_file_des) < 0)
error (0, errno, "%s", input_name.ds_string);
if (close (out_file_des) < 0)
error (0, errno, "%s", output_name.ds_string);
/* Set the attributes of the new file. */ set_copypass_perms (out_file_des,
if (!no_chown_flag) output_name.ds_string, &in_file_stat);
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) if (reset_time_flag)
{ {
times.actime = in_file_stat.st_atime; set_file_times (in_file_des,
times.modtime = in_file_stat.st_mtime; input_name.ds_string,
/* Debian hack: Silently ignore EROFS because in_file_stat.st_atime,
reading the file won't have upset its timestamp in_file_stat.st_mtime);
if it's on a read-only filesystem. This has been set_file_times (out_file_des,
submitted as a suggestion to output_name.ds_string,
"bug-gnu-utils@prep.ai.mit.edu". -BEM */ in_file_stat.st_atime,
if (utime (input_name.ds_string, &times) < 0 in_file_stat.st_mtime);
&& errno != EROFS) }
error (0, errno, "%s", input_name.ds_string);
if (utime (output_name.ds_string, &times) < 0 if (close (in_file_des) < 0)
&& errno != EROFS) close_error (input_name.ds_string);
error (0, errno, "%s", output_name.ds_string);
} if (close (out_file_des) < 0)
if (retain_time_flag) close_error (output_name.ds_string);
{
times.actime = times.modtime = in_file_stat.st_mtime;
if (utime (output_name.ds_string, &times) < 0)
error (0, errno, "%s", output_name.ds_string);
}
warn_if_file_changed(input_name.ds_string, in_file_stat.st_size, warn_if_file_changed(input_name.ds_string, in_file_stat.st_size,
in_file_stat.st_mtime); in_file_stat.st_mtime);
} }
@ -261,31 +260,11 @@ process_copy_pass ()
(lstat (output_name.ds_string, &out_file_stat) != 0) || (lstat (output_name.ds_string, &out_file_stat) != 0) ||
!(S_ISDIR (out_file_stat.st_mode) ) ) !(S_ISDIR (out_file_stat.st_mode) ) )
{ {
error (0, errno, "%s", output_name.ds_string); stat_error (output_name.ds_string);
continue; continue;
} }
} }
if (!no_chown_flag) set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
if ((chown (output_name.ds_string,
set_owner_flag ? set_owner : in_file_stat.st_uid,
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
/* chown may have turned off some permissions we wanted. */
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
error (0, errno, "%s", output_name.ds_string);
#ifdef HPUX_CDF
if (cdf_flag)
/* Once we "hide" the directory with the chmod(),
we have to refer to it using name+ isntead of name. */
output_name.ds_string [cdf_char] = '+';
#endif
if (retain_time_flag)
{
times.actime = times.modtime = in_file_stat.st_mtime;
if (utime (output_name.ds_string, &times) < 0)
error (0, errno, "%s", output_name.ds_string);
}
} }
else if (S_ISCHR (in_file_stat.st_mode) || else if (S_ISCHR (in_file_stat.st_mode) ||
S_ISBLK (in_file_stat.st_mode) || S_ISBLK (in_file_stat.st_mode) ||
@ -321,24 +300,10 @@ process_copy_pass ()
} }
if (res < 0) if (res < 0)
{ {
error (0, errno, "%s", output_name.ds_string); mknod_error (output_name.ds_string);
continue; continue;
} }
if (!no_chown_flag) set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
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);
}
} }
} }
@ -353,7 +318,7 @@ process_copy_pass ()
in_file_stat.st_size); in_file_stat.st_size);
if (link_size < 0) if (link_size < 0)
{ {
error (0, errno, "%s", input_name.ds_string); readlink_error (input_name.ds_string);
free (link_name); free (link_name);
continue; continue;
} }
@ -369,18 +334,20 @@ process_copy_pass ()
} }
if (res < 0) if (res < 0)
{ {
error (0, errno, "%s", output_name.ds_string); symlink_error (output_name.ds_string, link_name);
free (link_name); free (link_name);
continue; continue;
} }
/* Set the attributes of the new link. */ /* Set the attributes of the new link. */
if (!no_chown_flag) if (!no_chown_flag)
if ((lchown (output_name.ds_string, {
set_owner_flag ? set_owner : in_file_stat.st_uid, uid_t uid = set_owner_flag ? set_owner : in_file_stat.st_uid;
set_group_flag ? set_group : in_file_stat.st_gid) < 0) gid_t gid = set_group_flag ? set_group : in_file_stat.st_gid;
&& errno != EPERM) if ((lchown (output_name.ds_string, uid, gid) < 0)
error (0, errno, "%s", output_name.ds_string); && errno != EPERM)
chown_error_details (output_name.ds_string, uid, gid);
}
free (link_name); free (link_name);
} }
#endif #endif

View File

@ -1,5 +1,5 @@
/* Extended cpio format from POSIX.1. /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#ifndef _CPIO_H #ifndef _CPIO_H
@ -25,6 +26,8 @@
and variable length file data. and variable length file data.
A header for a filename "TRAILER!!!" indicates the end of the archive. */ 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 /* All the fields in the header are ISO 646 (approximately ASCII) strings
of octal numbers, left padded, not NUL terminated. of octal numbers, left padded, not NUL terminated.

View File

@ -1,5 +1,5 @@
/* Extended cpio header from POSIX.1. /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#ifndef _CPIOHDR_H #ifndef _CPIOHDR_H
@ -34,9 +35,21 @@ struct old_cpio_header
unsigned short c_mtimes[2]; unsigned short c_mtimes[2];
unsigned short c_namesize; unsigned short c_namesize;
unsigned short c_filesizes[2]; 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: /* "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. */ A header for a filename "TRAILER!!!" indicates the end of the archive. */
/* All the fields in the header are ISO 646 (approximately ASCII) strings /* 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 struct new_ascii_header
c_magic 6 "070701" for "new" portable format {
"070702" for CRC format char c_magic[6]; /* "070701" for "new" portable format
c_ino 8 "070702" for CRC format */
c_mode 8 char c_ino[8];
c_uid 8 char c_mode[8];
c_gid 8 char c_uid[8];
c_nlink 8 char c_gid[8];
c_mtime 8 char c_nlink[8];
c_filesize 8 must be 0 for FIFOs and directories char c_mtime[8];
c_maj 8 char c_filesize[8]; /* must be 0 for FIFOs and directories */
c_min 8 char c_dev_maj[8];
c_rmaj 8 only valid for chr and blk special files char c_dev_min[8];
c_rmin 8 only valid for chr and blk special files char c_rdev_maj[8]; /* only valid for chr and blk special files */
c_namesize 8 count includes terminating NUL in pathname char c_rdev_min[8]; /* only valid for chr and blk special files */
c_chksum 8 0 for "new" portable format; for CRC format char c_namesize[8]; /* count includes terminating NUL in pathname */
the sum of all the bytes in the file */ 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 short c_magic;
unsigned long c_ino; ino_t c_ino;
unsigned long c_mode; mode_t c_mode;
unsigned long c_uid; uid_t c_uid;
unsigned long c_gid; gid_t c_gid;
unsigned long c_nlink; size_t c_nlink;
unsigned long c_mtime; time_t c_mtime;
unsigned long c_filesize; off_t c_filesize;
long c_dev_maj; long c_dev_maj;
long c_dev_min; long c_dev_min;
long c_rdev_maj; long c_rdev_maj;
long c_rdev_min; long c_rdev_min;
unsigned long c_namesize; size_t c_namesize;
unsigned long c_chksum; unsigned long c_chksum;
char *c_name; char *c_name;
char *c_tar_linkname; char *c_tar_linkname;
}; };
#endif /* cpiohdr.h */ #endif /* cpiohdr.h */

View File

@ -1,5 +1,5 @@
/* defer.c - handle "defered" links in newc and crc archives /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#include <system.h> #include <system.h>
@ -24,7 +25,7 @@
#include "defer.h" #include "defer.h"
struct deferment * struct deferment *
create_deferment (struct new_cpio_header *file_hdr) create_deferment (struct cpio_file_stat *file_hdr)
{ {
struct deferment *d; struct deferment *d;
d = (struct deferment *) xmalloc (sizeof (struct deferment) ); d = (struct deferment *) xmalloc (sizeof (struct deferment) );

View File

@ -1,5 +1,5 @@
/* defer.h /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
struct deferment struct deferment
{ {
struct deferment *next; struct deferment *next;
struct new_cpio_header header; struct cpio_file_stat header;
}; };
struct deferment *create_deferment P_((struct new_cpio_header *file_hdr)); struct deferment *create_deferment (struct cpio_file_stat *file_hdr);
void free_deferment P_((struct deferment *d)); void free_deferment (struct deferment *d);

View File

@ -11,9 +11,10 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#if defined(HAVE_CONFIG_H) #if defined(HAVE_CONFIG_H)
# include <config.h> # include <config.h>
@ -27,13 +28,8 @@
#endif #endif
#include "dstring.h" #include "dstring.h"
#if __STDC__ char *xmalloc (unsigned n);
# define P_(s) s char *xrealloc (char *p, unsigned n);
#else
# define P_(s) ()
#endif
char *xmalloc P_((unsigned n));
char *xrealloc P_((char *p, unsigned n));
/* Initialiaze dynamic string STRING with space for SIZE characters. */ /* Initialiaze dynamic string STRING with space for SIZE characters. */

View File

@ -11,9 +11,10 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#ifndef NULL #ifndef NULL
#define NULL 0 #define NULL 0

View File

@ -1,5 +1,5 @@
/* extern.h - External declarations for cpio. Requires system.h. /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 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 enum archive_format
{ {
arf_unknown, arf_binary, arf_oldascii, arf_newascii, arf_crcascii, arf_unknown, arf_binary, arf_oldascii, arf_newascii, arf_crcascii,
arf_tar, arf_ustar, arf_hpoldascii, arf_hpbinary arf_tar, arf_ustar, arf_hpoldascii, arf_hpbinary
}; };
extern enum archive_format archive_format; extern enum archive_format archive_format;
extern int reset_time_flag; extern int reset_time_flag;
extern int io_block_size; extern int io_block_size;
@ -66,7 +72,7 @@ extern char *new_media_message_after_number;
extern int archive_des; extern int archive_des;
extern char *archive_name; extern char *archive_name;
extern char *rsh_command_option; extern char *rsh_command_option;
extern unsigned long crc; extern unsigned int crc;
extern int delayed_seek_count; extern int delayed_seek_count;
#ifdef DEBUG_CPIO #ifdef DEBUG_CPIO
extern int debug_flag; extern int debug_flag;
@ -81,7 +87,6 @@ extern long long input_bytes, output_bytes;
#else #else
extern long input_bytes, output_bytes; extern long input_bytes, output_bytes;
#endif #endif
extern char zeros_512[];
extern char *directory_name; extern char *directory_name;
extern char **save_patterns; extern char **save_patterns;
extern int num_patterns; extern int num_patterns;
@ -94,38 +99,35 @@ extern char *program_name;
extern int (*xstat) (); extern int (*xstat) ();
extern void (*copy_function) (); extern void (*copy_function) ();
#if defined PROTOTYPES || (defined __STDC__ && __STDC__)
# define P_(s) s
#else
# define P_(s) ()
#endif
/* copyin.c */ /* copyin.c */
void warn_junk_bytes P_((long bytes_skipped)); void warn_junk_bytes (long bytes_skipped);
void read_in_header P_((struct new_cpio_header *file_hdr, int in_des)); /* FIXME: make read_* static in copyin.c */
void read_in_old_ascii P_((struct new_cpio_header *file_hdr, int in_des)); void read_in_header (struct cpio_file_stat *file_hdr, int in_des);
void read_in_new_ascii P_((struct new_cpio_header *file_hdr, int in_des)); void read_in_old_ascii (struct cpio_file_stat *file_hdr, int in_des);
void read_in_binary P_((struct new_cpio_header *file_hdr, int in_des)); void read_in_new_ascii (struct cpio_file_stat *file_hdr, int in_des);
void swab_array P_((char *arg, int count)); void read_in_binary (struct cpio_file_stat *file_hdr,
void process_copy_in P_((void)); struct old_cpio_header *short_hdr, int in_des);
void long_format P_((struct new_cpio_header *file_hdr, char *link_name)); void swab_array (char *arg, int count);
void print_name_with_quoting P_((char *p)); 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 */ /* copyout.c */
void write_out_header P_((struct new_cpio_header *file_hdr, int out_des)); int write_out_header (struct cpio_file_stat *file_hdr, int out_des);
void process_copy_out P_((void)); void process_copy_out (void);
/* copypass.c */ /* copypass.c */
void process_copy_pass P_((void)); void process_copy_pass (void);
int link_to_maj_min_ino P_((char *file_name, int st_dev_maj, int link_to_maj_min_ino (char *file_name, int st_dev_maj,
int st_dev_min, int st_ino)); int st_dev_min, int st_ino);
int link_to_name P_((char *link_name, char *link_target)); int link_to_name (char *link_name, char *link_target);
/* dirname.c */ /* dirname.c */
char *dirname P_((char *path)); char *dirname (char *path);
/* filemode.c */ /* filemode.c */
void mode_string P_((unsigned int mode, char *str)); void mode_string (unsigned int mode, char *str);
/* idcache.c */ /* idcache.c */
#ifndef __MSDOS__ #ifndef __MSDOS__
@ -136,61 +138,63 @@ gid_t *getgidbyname ();
#endif #endif
/* main.c */ /* main.c */
void process_args P_((int argc, char *argv[])); void process_args (int argc, char *argv[]);
void initialize_buffers P_((void)); void initialize_buffers (void);
/* makepath.c */ /* makepath.c */
int make_path P_((char *argpath, int mode, int parent_mode, int make_path (char *argpath, int mode, int parent_mode,
uid_t owner, gid_t group, char *verbose_fmt_string)); uid_t owner, gid_t group, char *verbose_fmt_string);
/* tar.c */ /* tar.c */
void write_out_tar_header P_((struct new_cpio_header *file_hdr, int out_des)); void write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des);
int null_block P_((long *block, int size)); int null_block (long *block, int size);
void read_in_tar_header P_((struct new_cpio_header *file_hdr, int in_des)); void read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des);
int otoa P_((char *s, unsigned long *n)); int otoa (char *s, unsigned long *n);
int is_tar_header P_((char *buf)); int is_tar_header (char *buf);
int is_tar_filename_too_long P_((char *name)); int is_tar_filename_too_long (char *name);
/* userspec.c */ /* userspec.c */
#ifndef __MSDOS__ #ifndef __MSDOS__
char *parse_user_spec P_((char *name, uid_t *uid, gid_t *gid, char *parse_user_spec (char *name, uid_t *uid, gid_t *gid,
char **username, char **groupname)); char **username, char **groupname);
#endif #endif
/* util.c */ /* util.c */
void tape_empty_output_buffer P_((int out_des)); void tape_empty_output_buffer (int out_des);
void disk_empty_output_buffer P_((int out_des)); void disk_empty_output_buffer (int out_des);
void swahw_array P_((char *ptr, int count)); void swahw_array (char *ptr, int count);
void tape_buffered_write P_((char *in_buf, int out_des, long num_bytes)); void tape_buffered_write (char *in_buf, int out_des, off_t num_bytes);
void tape_buffered_read P_((char *in_buf, int in_des, long num_bytes)); void tape_buffered_read (char *in_buf, int in_des, off_t num_bytes);
int tape_buffered_peek P_((char *peek_buf, int in_des, int num_bytes)); int tape_buffered_peek (char *peek_buf, int in_des, int num_bytes);
void tape_toss_input P_((int in_des, long num_bytes)); void tape_toss_input (int in_des, off_t num_bytes);
void copy_files_tape_to_disk P_((int in_des, int out_des, long num_bytes)); void copy_files_tape_to_disk (int in_des, int out_des, off_t 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_tape (int in_des, int out_des, off_t num_bytes, char *filename);
void copy_files_disk_to_disk P_((int in_des, int out_des, long 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 P_((char *file_name, unsigned long old_file_size, void warn_if_file_changed (char *file_name, unsigned long old_file_size,
unsigned long old_file_mtime)); off_t old_file_mtime);
void create_all_directories P_((char *name)); void create_all_directories (char *name);
void prepare_append P_((int out_file_des)); void prepare_append (int out_file_des);
char *find_inode_file P_((unsigned long node_num, char *find_inode_file (unsigned long node_num,
unsigned long major_num, unsigned long minor_num)); unsigned long major_num, unsigned long minor_num);
void add_inode P_((unsigned long node_num, char *file_name, void add_inode (unsigned long node_num, char *file_name,
unsigned long major_num, unsigned long minor_num)); unsigned long major_num, unsigned long minor_num);
int open_archive P_((char *file)); int open_archive (char *file);
void tape_offline P_((int tape_des)); void tape_offline (int tape_des);
void get_next_reel P_((int tape_des)); void get_next_reel (int tape_des);
void set_new_media_message P_((char *message)); void set_new_media_message (char *message);
#if defined(__MSDOS__) && !defined(__GNUC__) #if defined(__MSDOS__) && !defined(__GNUC__)
int chown P_((char *path, int owner, int group)); int chown (char *path, int owner, int group);
#endif #endif
#ifdef __TURBOC__ #ifdef __TURBOC__
int utime P_((char *filename, struct utimbuf *utb)); int utime (char *filename, struct utimbuf *utb);
#endif #endif
#ifdef HPUX_CDF #ifdef HPUX_CDF
char *add_cdf_double_slashes P_((char *filename)); char *add_cdf_double_slashes (char *filename);
#endif #endif
void write_nuls_to_file (off_t num_bytes, int out_des,
#define DISK_IO_BLOCK_SIZE (512) void (*writer) (char *in_buf,
int out_des, off_t num_bytes));
#define DISK_IO_BLOCK_SIZE 512
/* FIXME: Move to system.h? */ /* FIXME: Move to system.h? */
#ifndef SYMLINK_USES_UMASK #ifndef SYMLINK_USES_UMASK
@ -198,3 +202,20 @@ char *add_cdf_double_slashes P_((char *filename));
#else #else
# define UMASKED_SYMLINK(name1,name2,mode) umasked_symlink(name1,name2,mode) # define UMASKED_SYMLINK(name1,name2,mode) umasked_symlink(name1,name2,mode)
#endif /* SYMLINK_USES_UMASK */ #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)

View File

@ -11,9 +11,10 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>

View File

@ -11,9 +11,10 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
/* Include sys/types.h and sys/stat.h before this file. */ /* Include sys/types.h and sys/stat.h before this file. */

View File

@ -1,5 +1,5 @@
/* global.c - global variables and initial values for cpio. /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#include <system.h> #include <system.h>
@ -139,7 +140,7 @@ char *archive_name = NULL;
char *rsh_command_option = NULL; char *rsh_command_option = NULL;
/* CRC checksum. */ /* CRC checksum. */
unsigned long crc; unsigned int crc;
/* Input and output buffers. */ /* Input and output buffers. */
char *input_buffer, *output_buffer; char *input_buffer, *output_buffer;
@ -165,9 +166,6 @@ long long input_bytes, output_bytes;
long input_bytes, output_bytes; long input_bytes, output_bytes;
#endif #endif
/* 512 bytes of 0; used for various padding operations. */
char zeros_512[512];
/* Saving of argument values for later reference. */ /* Saving of argument values for later reference. */
char *directory_name = NULL; char *directory_name = NULL;
char **save_patterns; char **save_patterns;

View File

@ -11,9 +11,10 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>

View File

@ -1,5 +1,6 @@
/* main.c - main program and argument processing for cpio. /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
/* Written by Phil Nelson <phil@cs.wwu.edu>, /* Written by Phil Nelson <phil@cs.wwu.edu>,
David MacKenzie <djm@gnu.ai.mit.edu>, David MacKenzie <djm@gnu.ai.mit.edu>,
@ -21,6 +23,7 @@
and Sergey Poznyakoff <gray@mirddin.farlep.net> */ and Sergey Poznyakoff <gray@mirddin.farlep.net> */
#include <system.h> #include <system.h>
#include <paxlib.h>
#include <stdio.h> #include <stdio.h>
#include <getopt.h> #include <getopt.h>
@ -29,7 +32,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#ifdef HAVE_LOCALE_H #ifdef HAVE_LOCALE_H
# include <locale.h> # include <locale.h>
#endif #endif
#include "filetypes.h" #include "filetypes.h"
@ -37,10 +40,11 @@
#include "dstring.h" #include "dstring.h"
#include "extern.h" #include "extern.h"
#include <rmt.h> #include <rmt.h>
#include <localedir.h> #include <rmt-command.h>
enum cpio_options { enum cpio_options {
NO_ABSOLUTE_FILENAMES_OPTION=256, NO_ABSOLUTE_FILENAMES_OPTION=256,
ABSOLUTE_FILENAMES_OPTION,
NO_PRESERVE_OWNER_OPTION, NO_PRESERVE_OWNER_OPTION,
ONLY_VERIFY_CRC_OPTION, ONLY_VERIFY_CRC_OPTION,
RENAME_BATCH_FILE_OPTION, RENAME_BATCH_FILE_OPTION,
@ -50,8 +54,9 @@ enum cpio_options {
FORCE_LOCAL_OPTION, FORCE_LOCAL_OPTION,
DEBUG_OPTION, DEBUG_OPTION,
BLOCK_SIZE_OPTION, BLOCK_SIZE_OPTION,
TO_STDOUT_OPTION, TO_STDOUT_OPTION,
HANG_OPTION,
USAGE_OPTION, USAGE_OPTION,
LICENSE_OPTION, LICENSE_OPTION,
VERSION_OPTION VERSION_OPTION
@ -71,129 +76,156 @@ Examples:\n\
/* Print usage error message and exit with error. */ /* 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) \ #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[] = { static struct argp_option options[] = {
/* ********** */
#define GRID 10
{NULL, 0, NULL, 0, {NULL, 0, NULL, 0,
N_("Main operation mode:"), 10}, N_("Main operation mode:"), GRID },
{"create", 'o', 0, 0, {"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, {"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, {"pass-through", 'p', 0, 0,
N_("Run in copy-pass mode"), 10}, N_("Run in copy-pass mode"), GRID },
{"list", 't', 0, 0, {"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
{NULL, 0, NULL, 0,
N_("Operation modifiers valid in any mode:"), 100},
{"file", 'F', N_("[[USER@]HOST:]FILE-NAME"), 0,
N_("Use this FILE-NAME instead of standard input or output. Optional USER and HOST specify the user and host names in case of a remote archive"), 110},
{"force-local", FORCE_LOCAL_OPTION, 0, 0,
N_("Archive file is local, even if its name contains colons"), 110},
{"format", 'H', N_("FORMAT"), 0,
N_("Use given archive FORMAT"), 110},
{NULL, 'B', NULL, 0,
N_("Set the I/O block size to 5120 bytes"), 110},
{"block-size", BLOCK_SIZE_OPTION, N_("BLOCK-SIZE"), 0,
N_("Set the I/O block size to BLOCK-SIZE * 512 bytes"), 110},
{NULL, 'c', NULL, 0,
N_("Use the old portable (ASCII) archive format"), 0},
{"dot", 'V', NULL, 0,
N_("Print a \".\" for each file processed"), 110},
{"io-size", 'C', N_("NUMBER"), 0,
N_("Set the I/O block size to the given NUMBER of bytes"), 110},
{"message", 'M', N_("STRING"), 0,
N_("Print STRING when the end of a volume of the backup media is reached"),
110},
{"nonmatching", 'f', 0, 0,
N_("Only copy files that do not match any of the given patterns"), 110},
{"numeric-uid-gid", 'n', 0, 0,
N_("In the verbose table of contents listing, show numeric UID and GID"),
110},
{"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
N_("Use remote COMMAND instead of rsh"), 110},
{"quiet", QUIET_OPTION, NULL, 0,
N_("Do not print the number of blocks copied"), 110},
{"verbose", 'v', NULL, 0,
N_("Verbosely list the files processed"), 110},
#ifdef DEBUG_CPIO
{"debug", DEBUG_OPTION, NULL, 0,
N_("Enable debugging info"), 110},
#endif
{"warning", 'W', N_("FLAG"), 0,
N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), 110 },
/* ********** */
{NULL, 0, NULL, 0,
N_("Operation modifiers valid only in copy-in mode:"), 200},
{"pattern-file", 'E', N_("FILE"), 0,
N_("In copy-in mode, read additional patterns specifying filenames to extract or list from FILE"), 210},
{"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
N_("Create all files relative to the current directory"), 210},
{"only-verify-crc", ONLY_VERIFY_CRC_OPTION, 0, 0,
N_("When reading a CRC format archive in copy-in mode, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
{"rename", 'r', 0, 0,
N_("Interactively rename files"), 210},
{"rename-batch-file", RENAME_BATCH_FILE_OPTION, N_("FILE"), OPTION_HIDDEN,
"", 210},
{"swap", 'b', NULL, 0,
N_("Swap both halfwords of words and bytes of halfwords in the data. Equivalent to -sS"), 210},
{"swap-bytes", 's', NULL, 0,
N_("Swap the bytes of each halfword in the files"), 210},
{"swap-halfwords", 'S', NULL, 0,
N_("Swap the halfwords of each word (4 bytes) in the files"),
210},
{"to-stdout", TO_STDOUT_OPTION, NULL, 0,
N_("Extract files to standard output"), 210},
/* ********** */
{NULL, 0, NULL, 0,
N_("Operation modifiers valid only in copy-out mode:"), 300},
{"append", 'A', 0, 0,
N_("Append to an existing archive."), 310 },
{NULL, 'O', N_("[[USER@]HOST:]FILE-NAME"), 0,
N_("Archive filename to use instead of standard output. Optional USER and HOST specify the user and host names in case of a remote archive"), 310},
/* ********** */ /* ********** */
#define GRID 100
{NULL, 0, NULL, 0, {NULL, 0, NULL, 0,
N_("Operation modifiers valid only in copy-pass mode:"), 400}, N_("Operation modifiers valid in any mode:"), GRID },
{"file", 'F', N_("[[USER@]HOST:]FILE-NAME"), 0,
N_("Use this FILE-NAME instead of standard input or output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
{"force-local", FORCE_LOCAL_OPTION, 0, 0,
N_("Archive file is local, even if its name contains colons"), GRID+1 },
{"format", 'H', N_("FORMAT"), 0,
N_("Use given archive FORMAT"), GRID+1 },
{NULL, 'B', NULL, 0,
N_("Set the I/O block size to 5120 bytes"), GRID+1 },
{"block-size", BLOCK_SIZE_OPTION, N_("BLOCK-SIZE"), 0,
N_("Set the I/O block size to BLOCK-SIZE * 512 bytes"), GRID+1 },
{NULL, 'c', NULL, 0,
N_("Use the old portable (ASCII) archive format"), GRID+1 },
{"dot", 'V', NULL, 0,
N_("Print a \".\" for each file processed"), GRID+1 },
{"io-size", 'C', N_("NUMBER"), 0,
N_("Set the I/O block size to the given NUMBER of bytes"), GRID+1 },
{"message", 'M', N_("STRING"), 0,
N_("Print STRING when the end of a volume of the backup media is reached"),
GRID+1 },
{"nonmatching", 'f', 0, 0,
N_("Only copy files that do not match any of the given patterns"), GRID+1 },
{"numeric-uid-gid", 'n', 0, 0,
N_("In the verbose table of contents listing, show numeric UID and GID"),
GRID+1 },
{"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
N_("Use remote COMMAND instead of rsh"), GRID+1 },
{"quiet", QUIET_OPTION, NULL, 0,
N_("Do not print the number of blocks copied"), GRID+1 },
{"verbose", 'v', NULL, 0,
N_("Verbosely list the files processed"), GRID+1 },
#ifdef DEBUG_CPIO
{"debug", DEBUG_OPTION, NULL, 0,
N_("Enable debugging info"), GRID+1 },
#endif
{"warning", 'W', N_("FLAG"), 0,
N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), GRID+1 },
#undef GRID
/* ********** */
#define GRID 200
{NULL, 0, NULL, 0,
N_("Operation modifiers valid only in copy-in mode:"), GRID },
{"pattern-file", 'E', N_("FILE"), 0,
N_("Read additional patterns specifying filenames to extract or list from FILE"), 210},
{"only-verify-crc", ONLY_VERIFY_CRC_OPTION, 0, 0,
N_("When reading a CRC format archive, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
{"rename", 'r', 0, 0,
N_("Interactively rename files"), GRID+1 },
{"rename-batch-file", RENAME_BATCH_FILE_OPTION, N_("FILE"), OPTION_HIDDEN,
"", GRID+1 },
{"swap", 'b', NULL, 0,
N_("Swap both halfwords of words and bytes of halfwords in the data. Equivalent to -sS"), GRID+1 },
{"swap-bytes", 's', NULL, 0,
N_("Swap the bytes of each halfword in the files"), GRID+1 },
{"swap-halfwords", 'S', NULL, 0,
N_("Swap the halfwords of each word (4 bytes) in the files"),
GRID+1 },
{"to-stdout", TO_STDOUT_OPTION, NULL, 0,
N_("Extract files to standard output"), GRID+1 },
#undef GRID
/* ********** */
#define GRID 300
{NULL, 0, NULL, 0,
N_("Operation modifiers valid only in copy-out mode:"), GRID },
{"append", 'A', 0, 0,
N_("Append to an existing archive."), GRID+1 },
{NULL, 'O', N_("[[USER@]HOST:]FILE-NAME"), 0,
N_("Archive filename to use instead of standard output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
#undef GRID
/* ********** */
#define GRID 400
{NULL, 0, NULL, 0,
N_("Operation modifiers valid only in copy-pass mode:"), GRID},
{"link", 'l', 0, 0, {"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, {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, {"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, {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, {"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, {"owner", 'R', N_("[USER][:.][GROUP]"), 0,
N_("Set the ownership of all files created to the specified USER and/or GROUP"), 510}, N_("Set the ownership of all files created to the specified USER and/or GROUP"), GRID+1 },
{"sparse", SPARSE_OPTION, NULL, 0,
N_("Write files with large blocks of zeros as sparse files"), 510},
{"reset-access-time", 'a', NULL, 0, {"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, {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, {"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, {"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, {"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, {"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, {NULL, 0, NULL, 0,
N_("Informative options:"), 700 }, N_("Informative options:"), GRID },
{"help", '?', 0, 0, N_("Give this help list"), -1}, {"help", '?', 0, 0, N_("Give this help list"), -1},
{"usage", USAGE_OPTION, 0, 0, N_("Give a short usage message"), -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}, {"version", VERSION_OPTION, 0, 0, N_("Print program version"), -1},
/* FIXME -V (--dot) conflicts with the default short option for /* FIXME -V (--dot) conflicts with the default short option for
--version */ --version */
{"HANG", HANG_OPTION, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
N_("hang for SECS seconds (default 3600)"), 0},
#undef GRID
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
@ -224,8 +258,8 @@ license ()
" GNU General Public License for more details.\n" " GNU General Public License for more details.\n"
"\n" "\n"
" You should have received a copy of the GNU General Public License\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" " along with GNU cpio; if not, write to the Free Software Foundation,\n"
" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\n")); " Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n\n"));
exit (0); exit (0);
} }
@ -269,6 +303,7 @@ warn_control (char *arg)
static error_t static error_t
parse_opt (int key, char *arg, struct argp_state *state) parse_opt (int key, char *arg, struct argp_state *state)
{ {
static volatile int _argp_hang;
switch (key) switch (key)
{ {
case '0': /* Read null-terminated filenames. */ 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. */ case 'c': /* Use the old portable ASCII format. */
if (archive_format != arf_unknown) if (archive_format != arf_unknown)
USAGE_ERROR ((0, 0, _("Archive format multiply defined"))); error (0, EXIT_FAILURE, _("Archive format multiply defined"));
#ifdef SVR4_COMPAT #ifdef SVR4_COMPAT
archive_format = arf_newascii; /* -H newc. */ archive_format = arf_newascii; /* -H newc. */
#else #else
@ -333,7 +368,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'H': /* Header format name. */ case 'H': /* Header format name. */
if (archive_format != arf_unknown) 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")) if (!strcasecmp (arg, "crc"))
archive_format = arf_crcascii; archive_format = arf_crcascii;
else if (!strcasecmp (arg, "newc")) 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. */ case 'i': /* Copy-in mode. */
if (copy_function != 0) if (copy_function != 0)
USAGE_ERROR ((0, 0, _("Mode already defined"))); error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
copy_function = process_copy_in; copy_function = process_copy_in;
break; break;
@ -394,17 +429,21 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case NO_ABSOLUTE_FILENAMES_OPTION: /* --no-absolute-filenames */ case NO_ABSOLUTE_FILENAMES_OPTION: /* --no-absolute-filenames */
no_abs_paths_flag = true; no_abs_paths_flag = true;
break; break;
case ABSOLUTE_FILENAMES_OPTION: /* --absolute-filenames */
no_abs_paths_flag = false;
break;
case NO_PRESERVE_OWNER_OPTION: /* --no-preserve-owner */ case NO_PRESERVE_OWNER_OPTION: /* --no-preserve-owner */
if (set_owner_flag || set_group_flag) if (set_owner_flag || set_group_flag)
USAGE_ERROR ((0, 0, error (PAXEXIT_FAILURE, 0,
_("--no-preserve-owner cannot be used with --owner"))); _("--no-preserve-owner cannot be used with --owner"));
no_chown_flag = true; no_chown_flag = true;
break; break;
case 'o': /* Copy-out mode. */ case 'o': /* Copy-out mode. */
if (copy_function != 0) if (copy_function != 0)
USAGE_ERROR ((0, 0, _("Mode already defined"))); error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
copy_function = process_copy_out; copy_function = process_copy_out;
break; break;
@ -418,7 +457,7 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case 'p': /* Copy-pass mode. */ case 'p': /* Copy-pass mode. */
if (copy_function != 0) if (copy_function != 0)
USAGE_ERROR ((0, 0, _("Mode already defined"))); error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
copy_function = process_copy_pass; copy_function = process_copy_pass;
break; break;
@ -440,25 +479,26 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case 'R': /* Set the owner. */ case 'R': /* Set the owner. */
if (no_chown_flag) if (no_chown_flag)
USAGE_ERROR ((0, 0, error (PAXEXIT_FAILURE, 0,
_("--owner cannot be used with --no-preserve-owner"))); _("--owner cannot be used with --no-preserve-owner"));
{ else
char *e, *u, *g; {
char *e, *u, *g;
e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
if (e) e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
error (2, 0, "%s: %s", arg, e); if (e)
if (u) error (PAXEXIT_FAILURE, 0, "%s: %s", arg, e);
{ if (u)
free (u); {
set_owner_flag = true; free (u);
} set_owner_flag = true;
if (g) }
{ if (g)
free (g); {
set_group_flag = true; free (g);
} set_group_flag = true;
} }
}
break; break;
case 's': /* Swap bytes. */ case 's': /* Swap bytes. */
@ -507,6 +547,12 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case TO_STDOUT_OPTION: case TO_STDOUT_OPTION:
to_stdout_option = true; to_stdout_option = true;
break; break;
case HANG_OPTION:
_argp_hang = atoi (arg ? arg : "3600");
while (_argp_hang-- > 0)
sleep (1);
break;
case '?': case '?':
argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP); argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
@ -552,9 +598,9 @@ process_args (int argc, char *argv[])
int index; int index;
if (argc < 2) if (argc < 2)
USAGE_ERROR ((0, 0, error (PAXEXIT_FAILURE, 0,
_("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"), _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
program_name, program_name)); program_name, program_name);
xstat = lstat; xstat = lstat;
@ -568,9 +614,9 @@ process_args (int argc, char *argv[])
if (table_flag) if (table_flag)
copy_function = process_copy_in; copy_function = process_copy_in;
else else
USAGE_ERROR ((0, 0, error (PAXEXIT_FAILURE, 0,
_("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"), _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
program_name, program_name)); program_name, program_name);
} }
/* Work around for pcc bug. */ /* Work around for pcc bug. */
@ -584,7 +630,6 @@ process_args (int argc, char *argv[])
CHECK_USAGE(reset_time_flag, "--reset", "--extract"); CHECK_USAGE(reset_time_flag, "--reset", "--extract");
CHECK_USAGE(xstat != lstat, "--dereference", "--extract"); CHECK_USAGE(xstat != lstat, "--dereference", "--extract");
CHECK_USAGE(append_flag, "--append", "--extract"); CHECK_USAGE(append_flag, "--append", "--extract");
CHECK_USAGE(sparse_flag, "--sparse", "--extract");
CHECK_USAGE(output_archive_name, "-O", "--extract"); CHECK_USAGE(output_archive_name, "-O", "--extract");
if (to_stdout_option) if (to_stdout_option)
{ {
@ -597,7 +642,8 @@ process_args (int argc, char *argv[])
} }
if (archive_name && input_archive_name) 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) if (archive_format == arf_crcascii)
crc_i_flag = true; crc_i_flag = true;
@ -609,7 +655,7 @@ process_args (int argc, char *argv[])
else if (copy_function == copy_out) else if (copy_function == copy_out)
{ {
if (index != argc) if (index != argc)
USAGE_ERROR ((0, 0, _("Too many arguments"))); error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
archive_des = 1; archive_des = 1;
CHECK_USAGE(create_dir_flag, "--make-directories", "--create"); 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(table_flag, "--list", "--create");
CHECK_USAGE(unconditional_flag, "--unconditional", "--create"); CHECK_USAGE(unconditional_flag, "--unconditional", "--create");
CHECK_USAGE(link_flag, "--link", "--create"); CHECK_USAGE(link_flag, "--link", "--create");
CHECK_USAGE(sparse_flag, "--sparse", "--create");
CHECK_USAGE(retain_time_flag, "--preserve-modification-time", CHECK_USAGE(retain_time_flag, "--preserve-modification-time",
"--create"); "--create");
CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--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_bytes_flag, "--swap-bytes (--swap)", "--create");
CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)", CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
"--create"); "--create");
CHECK_USAGE(to_stdout_option, "--to-stdout", "--create"); CHECK_USAGE(to_stdout_option, "--to-stdout", "--create");
if (append_flag && !(archive_name || output_archive_name)) if (append_flag && !(archive_name || output_archive_name))
USAGE_ERROR ((0, 0, error (PAXEXIT_FAILURE, 0,
_("--append is used but no archive file name is given (use -F or -O options"))); _("--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(rename_batch_file, "--rename-batch-file", "--create");
CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames", "--create");
CHECK_USAGE(input_archive_name, "-I", "--create"); CHECK_USAGE(input_archive_name, "-I", "--create");
if (archive_name && output_archive_name) 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) if (archive_format == arf_unknown)
archive_format = arf_binary; archive_format = arf_binary;
@ -644,12 +690,14 @@ process_args (int argc, char *argv[])
else else
{ {
/* Copy pass. */ /* Copy pass. */
if (index != argc - 1) if (index < argc - 1)
USAGE_ERROR ((0, 0, _("Too many arguments"))); error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
else if (index > argc - 1)
error (PAXEXIT_FAILURE, 0, _("Not enough arguments"));
if (archive_format != arf_unknown) if (archive_format != arf_unknown)
USAGE_ERROR((0, 0, error (PAXEXIT_FAILURE, 0,
_("Archive format is not specified in copy-pass mode (use --format option)"))); _("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_bytes_flag, "--swap-bytes (--swap)", "--pass-through");
CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)", 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(rename_batch_file, "--rename-batch-file", "--pass-through");
CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames", CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames",
"--pass-through"); "--pass-through");
CHECK_USAGE(no_abs_paths_flag, "--absolute-pathnames",
"--pass-through");
CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through"); CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through");
directory_name = argv[index]; directory_name = argv[index];
@ -668,11 +718,12 @@ process_args (int argc, char *argv[])
if (archive_name) if (archive_name)
{ {
if (copy_function != copy_in && copy_function != copy_out) if (copy_function != copy_in && copy_function != copy_out)
USAGE_ERROR ((0, 0, error (PAXEXIT_FAILURE, 0,
_("-F can be used only with --create or --extract"))); _("-F can be used only with --create or --extract"));
archive_des = open_archive (archive_name); archive_des = open_archive (archive_name);
if (archive_des < 0) 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. /* Prevent SysV non-root users from giving away files inadvertantly.
@ -725,33 +776,19 @@ initialize_buffers ()
out_buff = output_buffer; out_buff = output_buffer;
output_size = 0; output_size = 0;
output_bytes = 0; output_bytes = 0;
/* Clear the block of zeros. */
bzero (zeros_512, 512);
} }
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
#ifdef HAVE_LOCALE_H
setlocale (LC_ALL, ""); setlocale (LC_ALL, "");
#endif
bindtextdomain (PACKAGE, LOCALEDIR); bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE); textdomain (PACKAGE);
program_name = argv[0]; 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); process_args (argc, argv);
initialize_buffers (); initialize_buffers ();
(*copy_function) (); (*copy_function) ();

View File

@ -1,5 +1,5 @@
/* makepath.c -- Ensure that a directory path exists. /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu> and /* Written by David MacKenzie <djm@gnu.ai.mit.edu> and
Jim Meyering <meyering@cs.utexas.edu>. */ Jim Meyering <meyering@cs.utexas.edu>. */
@ -23,46 +24,11 @@
come together again in the future. */ come together again in the future. */
#include <system.h> #include <system.h>
#include <paxlib.h>
#ifdef __GNUC__
#define alloca __builtin_alloca
#else
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#else
#ifdef _AIX
#pragma alloca
#else
char *alloca ();
#endif
#endif
#endif
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.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. /* Ensure that the directory ARGPATH exists.
Remove any trailing slashes from ARGPATH before calling this function. Remove any trailing slashes from ARGPATH before calling this function.
@ -126,7 +92,7 @@ make_path (char *argpath,
slash = dirpath; slash = dirpath;
while (*slash == '/') while (*slash == '/')
slash++; slash++;
while ((slash = index (slash, '/'))) while ((slash = strchr (slash, '/')))
{ {
#ifdef HPUX_CDF #ifdef HPUX_CDF
int iscdf; int iscdf;
@ -164,7 +130,7 @@ make_path (char *argpath,
#endif #endif
) )
{ {
error (0, errno, "%s", dirpath); chown_error_details (dirpath, owner, group);
retval = 1; retval = 1;
} }
if (re_protect) if (re_protect)
@ -231,23 +197,23 @@ make_path (char *argpath,
#endif #endif
) )
{ {
error (0, errno, "%s", dirpath); chown_error_details (dirpath, owner, group);
retval = 1; retval = 1;
} }
} }
/* chown may have turned off some permission bits we wanted. */ /* chown may have turned off some permission bits we wanted. */
if ((mode & 07000) != 0 && chmod (dirpath, mode)) if ((mode & 07000) != 0 && chmod (dirpath, mode))
{ {
error (0, errno, "%s", dirpath); chmod_error_details (dirpath, mode);
retval = 1; retval = 1;
} }
/* If the mode for leading directories didn't include owner "wx" /* If the mode for leading directories didn't include owner "wx"
privileges, we have to reset their protections to the correct privileges, we have to reset their protections to the correct
value. */ value. */
for (p = leading_dirs; p != NULL; p = p->next) for (p = leading_dirs; p != NULL; p = p->next)
{ {
*(p->dirname_end) = '\0'; *p->dirname_end = '\0';
#if 0 #if 0
/* cpio always calls make_path with parent mode 0700, so /* cpio always calls make_path with parent mode 0700, so
we don't have to do this. If we ever do have to do this, we 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. */ bit so we don't break HP CDF's. */
if (chmod (dirpath, parent_mode)) if (chmod (dirpath, parent_mode))
{ {
error (0, errno, "%s", dirpath); chmod_error_details (dirpath, parent_mode);
retval = 1; retval = 1;
} }
#endif #endif
@ -286,12 +252,12 @@ make_path (char *argpath,
#endif #endif
) )
{ {
error (0, errno, "%s", dirpath); chown_error_details (dirpath, owner, group);
retval = 1; retval = 1;
} }
if (chmod (dirpath, mode)) if (chmod (dirpath, mode))
{ {
error (0, errno, "%s", dirpath); chmod_error_details (dirpath, mode);
retval = 1; retval = 1;
} }
} }

View File

@ -1,5 +1,5 @@
/* tar.c - read in write tar headers for cpio /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#include <system.h> #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, /* Compute and return a checksum for TAR_HDR,
counting the checksum bytes as if they were spaces. */ counting the checksum bytes as if they were spaces. */
unsigned long unsigned int
tar_checksum (struct tar_header *tar_hdr) tar_checksum (struct tar_header *tar_hdr)
{ {
unsigned long sum = 0; unsigned int sum = 0;
char *p = (char *) tar_hdr; char *p = (char *) tar_hdr;
char *q = p + TARRECORDSIZE; char *q = p + TARRECORDSIZE;
int i; int i;
@ -136,13 +137,13 @@ tar_checksum (struct tar_header *tar_hdr)
descriptor OUT_DES. */ descriptor OUT_DES. */
void 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; int name_len;
union tar_record tar_rec; union tar_record tar_rec;
struct tar_header *tar_hdr = (struct tar_header *) &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, /* process_copy_out must ensure that file_hdr->c_name is short enough,
or we will lose here. */ or we will lose here. */
@ -254,7 +255,7 @@ null_block (long *block, int size)
into FILE_HDR. */ into FILE_HDR. */
void 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; long bytes_skipped = 0;
int warned = false; 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)) if (null_block ((long *) &tar_rec, TARRECORDSIZE))
#endif #endif
{ {
file_hdr->c_name = "TRAILER!!!"; file_hdr->c_name = CPIO_TRAILER_NAME;
return; return;
} }
#if 0 #if 0
@ -290,7 +291,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
while (1) 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)) 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")); error (0, 0, _("invalid header: checksum error"));
warned = true; warned = true;
} }
bcopy (((char *) &tar_rec) + 1, (char *) &tar_rec, memmove (&tar_rec, ((char *) &tar_rec) + 1, TARRECORDSIZE - 1);
TARRECORDSIZE - 1);
tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1); tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
++bytes_skipped; ++bytes_skipped;
continue; continue;
@ -319,7 +319,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
else else
file_hdr->c_name = stash_tar_filename (tar_hdr->prefix, tar_hdr->name); file_hdr->c_name = stash_tar_filename (tar_hdr->prefix, tar_hdr->name);
file_hdr->c_nlink = 1; 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; file_hdr->c_mode = file_hdr->c_mode & 07777;
/* Debian hack: This version of cpio uses the -n flag also to extract /* 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 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))) && (uidp = getuidbyname (tar_hdr->uname)))
file_hdr->c_uid = *uidp; file_hdr->c_uid = *uidp;
else 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 if (archive_format == arf_ustar && !numeric_uid
&& (gidp = getgidbyname (tar_hdr->gname))) && (gidp = getgidbyname (tar_hdr->gname)))
file_hdr->c_gid = *gidp; file_hdr->c_gid = *gidp;
else else
otoa (tar_hdr->gid, &file_hdr->c_gid); file_hdr->c_gid = FROM_OCTAL (tar_hdr->gid);
otoa (tar_hdr->size, &file_hdr->c_filesize); file_hdr->c_filesize = FROM_OCTAL (tar_hdr->size);
otoa (tar_hdr->mtime, &file_hdr->c_mtime); file_hdr->c_mtime = FROM_OCTAL (tar_hdr->mtime);
otoa (tar_hdr->devmajor, (unsigned long *) &file_hdr->c_rdev_maj); file_hdr->c_rdev_maj = FROM_OCTAL (tar_hdr->devmajor);
otoa (tar_hdr->devminor, (unsigned long *) &file_hdr->c_rdev_min); file_hdr->c_rdev_min = FROM_OCTAL (tar_hdr->devminor);
file_hdr->c_tar_linkname = NULL; file_hdr->c_tar_linkname = NULL;
switch (tar_hdr->typeflag) 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); 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 /* Return
2 if BUF is a valid POSIX tar header (the checksum is correct 2 if BUF is a valid POSIX tar header (the checksum is correct
and it has the "ustar" magic string), 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; struct tar_header *tar_hdr = (struct tar_header *) buf;
unsigned long chksum; unsigned long chksum;
otoa (tar_hdr->chksum, &chksum); chksum = FROM_OCTAL (tar_hdr->chksum);
if (chksum != tar_checksum (tar_hdr)) if (chksum != tar_checksum (tar_hdr))
return 0; return 0;
@ -473,7 +453,6 @@ is_tar_filename_too_long (char *name)
{ {
int whole_name_len; int whole_name_len;
int prefix_name_len; int prefix_name_len;
char *p;
whole_name_len = strlen (name); whole_name_len = strlen (name);
if (whole_name_len <= TARNAMESIZE) if (whole_name_len <= TARNAMESIZE)

View File

@ -14,10 +14,10 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public You should have received a copy of the GNU Library General
License along with this library; see the file COPYING.LIB. If Public License along with this library; see the file COPYING.LIB.
not, write to the Free Software Foundation, Inc., If not, write to the Free Software Foundation, Inc., 51 Franklin
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#ifndef _TAR_H #ifndef _TAR_H

View File

@ -11,9 +11,10 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#ifndef _TARHDR_H #ifndef _TARHDR_H

View File

@ -1,5 +1,6 @@
/* userspec.c -- Parse a user and group string. /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
@ -72,7 +74,7 @@ extern struct group *getgrgid (gid_t gid);
otherwise return 0. */ otherwise return 0. */
static int static int
isnumber (const char *str) isnumber_p (const char *str)
{ {
for (; *str; str++) for (; *str; str++)
if (!isdigit (*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); V_STRDUP (spec, spec_arg);
/* Find the separator if there is one. */ /* Find the separator if there is one. */
separator = index (spec, ':'); separator = strchr (spec, ':');
if (separator == NULL) if (separator == NULL)
separator = index (spec, '.'); separator = strchr (spec, '.');
/* Replace separator with a NUL. */ /* Replace separator with a NUL. */
if (separator != NULL) if (separator != NULL)
@ -136,7 +138,7 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
if (pwd == NULL) if (pwd == NULL)
{ {
if (!isnumber (u)) if (!isnumber_p (u))
error_msg = _("invalid user"); error_msg = _("invalid user");
else else
{ {
@ -182,7 +184,7 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
grp = getgrnam (g); grp = getgrnam (g);
if (grp == NULL) if (grp == NULL)
{ {
if (!isnumber (g)) if (!isnumber_p (g))
error_msg = _("invalid group"); error_msg = _("invalid group");
else else
*gid = atoi (g); *gid = atoi (g);

View File

@ -1,5 +1,6 @@
/* util.c - Several utility routines for cpio. /* 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 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public
with this program; if not, write to the Free Software Foundation, Inc., License along with this program; if not, write to the Free
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#include <system.h> #include <system.h>
@ -23,15 +25,21 @@
#include "cpiohdr.h" #include "cpiohdr.h"
#include "dstring.h" #include "dstring.h"
#include "extern.h" #include "extern.h"
#include <paxlib.h>
#include "filetypes.h"
#include <safe-read.h>
#include <full-write.h>
#include <rmt.h> #include <rmt.h>
#include <hash.h>
#include <utimens.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#ifdef HAVE_SYS_MTIO_H #ifdef HAVE_SYS_MTIO_H
#ifdef HAVE_SYS_IO_TRIOCTL_H # ifdef HAVE_SYS_IO_TRIOCTL_H
#include <sys/io/trioctl.h> # include <sys/io/trioctl.h>
#endif # endif
#include <sys/mtio.h> # include <sys/mtio.h>
#endif #endif
#if !HAVE_DECL_ERRNO #if !HAVE_DECL_ERRNO
@ -90,6 +98,8 @@ tape_empty_output_buffer (int out_des)
output_size = 0; output_size = 0;
} }
static int sparse_write (int fildes, char *buf, unsigned int nbyte);
/* Write `output_size' bytes of `output_buffer' to file /* Write `output_size' bytes of `output_buffer' to file
descriptor OUT_DES and reset `output_size' and `out_buff'. descriptor OUT_DES and reset `output_size' and `out_buff'.
If `swapping_halfwords' or `swapping_bytes' is set, 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. */ Exit with an error if end of file is reached. */
static int 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; in_buff = input_buffer;
num_bytes = (num_bytes < DISK_IO_BLOCK_SIZE) ? num_bytes : DISK_IO_BLOCK_SIZE; 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. */ When `out_buff' fills up, flush it to file descriptor OUT_DES. */
void 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. */ off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
register long space_left; /* Room left in output buffer. */ off_t space_left; /* Room left in output buffer. */
while (bytes_left > 0) 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) if (bytes_left < space_left)
space_left = bytes_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; out_buff += space_left;
output_size += space_left; output_size += space_left;
in_buf += 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. */ When `out_buff' fills up, flush it to file descriptor OUT_DES. */
void 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. */ off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
register long space_left; /* Room left in output buffer. */ off_t space_left; /* Room left in output buffer. */
while (bytes_left > 0) 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) if (bytes_left < space_left)
space_left = bytes_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; out_buff += space_left;
output_size += space_left; output_size += space_left;
in_buf += 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. */ When `in_buff' is exhausted, refill it from file descriptor IN_DES. */
void 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. */ off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
register long space_left; /* Bytes to copy from input buffer. */ off_t space_left; /* Bytes to copy from input buffer. */
while (bytes_left > 0) while (bytes_left > 0)
{ {
@ -295,7 +305,7 @@ tape_buffered_read (char *in_buf, int in_des, long num_bytes)
space_left = bytes_left; space_left = bytes_left;
else else
space_left = input_size; 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_buff += space_left;
in_buf += space_left; in_buf += space_left;
input_size -= 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. */ first block to make room. */
int half; int half;
half = input_buffer_size / 2; half = input_buffer_size / 2;
bcopy (input_buffer + half, input_buffer, half); memmove (input_buffer, input_buffer + half, half);
in_buff = in_buff - half; in_buff = in_buff - half;
append_buf = append_buf - 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; got_bytes = num_bytes;
else else
got_bytes = input_size; got_bytes = input_size;
bcopy (in_buff, peek_buf, (unsigned) got_bytes); memcpy (peek_buf, in_buff, (unsigned) got_bytes);
return got_bytes; return got_bytes;
} }
/* Skip the next NUM_BYTES bytes of file descriptor IN_DES. */ /* Skip the next NUM_BYTES bytes of file descriptor IN_DES. */
void 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. */ off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
register long space_left; /* Bytes to copy from input buffer. */ off_t space_left; /* Bytes to copy from input buffer. */
while (bytes_left > 0) while (bytes_left > 0)
{ {
@ -403,18 +413,19 @@ tape_toss_input (int in_des, long num_bytes)
} }
} }
static void void
write_nuls_to_file (long num_bytes, int out_des, write_nuls_to_file (off_t num_bytes, int out_des,
void (*writer) (char *in_buf, int out_des, long num_bytes)) void (*writer) (char *in_buf, int out_des, off_t num_bytes))
{ {
long blocks; off_t blocks;
long extra_bytes; off_t extra_bytes;
long i; off_t i;
static char zeros_512[512];
blocks = num_bytes / 512;
extra_bytes = num_bytes % 512; blocks = num_bytes / sizeof zeros_512;
extra_bytes = num_bytes % sizeof zeros_512;
for (i = 0; i < blocks; ++i) for (i = 0; i < blocks; ++i)
writer (zeros_512, out_des, 512); writer (zeros_512, out_des, sizeof zeros_512);
if (extra_bytes) if (extra_bytes)
writer (zeros_512, out_des, 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. */ NUM_BYTES is the number of bytes to copy. */
void 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 size;
long k; 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. */ NUM_BYTES is the number of bytes to copy. */
void 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) char *filename)
{ {
long size; long size;
long k; long k;
int rc; int rc;
long original_num_bytes; off_t original_num_bytes;
original_num_bytes = 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 (input_size == 0)
if (rc = disk_fill_input_buffer (in_des, 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) 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 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); original_num_bytes - num_bytes, filename);
write_nuls_to_file (num_bytes, out_des, tape_buffered_write); write_nuls_to_file (num_bytes, out_des, tape_buffered_write);
break; 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. */ NUM_BYTES is the number of bytes to copy. */
void 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) char *filename)
{ {
long size; long size;
long k; long k;
long original_num_bytes; off_t original_num_bytes;
int rc; int rc;
original_num_bytes = num_bytes; 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 = disk_fill_input_buffer (in_des, num_bytes))
{ {
if (rc > 0) 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 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); original_num_bytes - num_bytes, filename);
write_nuls_to_file (num_bytes, out_des, disk_buffered_write); write_nuls_to_file (num_bytes, out_des, disk_buffered_write);
break; break;
@ -545,20 +568,23 @@ copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
void void
warn_if_file_changed (char *file_name, unsigned long old_file_size, 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; struct stat new_file_stat;
if ((*xstat) (file_name, &new_file_stat) < 0) if ((*xstat) (file_name, &new_file_stat) < 0)
{ {
error (0, errno, "%s", file_name); stat_error (file_name);
return; return;
} }
/* Only check growth, shrinkage detected in copy_files_disk_to_{disk,tape}() /* Only check growth, shrinkage detected in copy_files_disk_to_{disk,tape}()
*/ */
if (new_file_stat.st_size > old_file_size) if (new_file_stat.st_size > old_file_size)
error (0, 0, _("File %s grew, %ld new bytes not copied"), error (0, 0,
file_name, (long)(new_file_stat.st_size - old_file_size)); 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) else if (new_file_stat.st_mtime != old_file_mtime)
error (0, 0, _("File %s was modified while being copied"), file_name); 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. */ /* Inode hash table. Allocated by first call to add_inode. */
static struct inode_val **hash_table = NULL; static Hash_table *hash_table = NULL;
/* Size of current hash table. Initial size is 47. (47 = 2*22 + 3) */ static size_t
static int hash_size = 22; inode_val_hasher (const void *val, size_t n_buckets)
{
const struct inode_val *ival = val;
return ival->inode % n_buckets;
}
/* Number of elements in current hash table. */ static bool
static int hash_num; inode_val_compare (const void *val1, const void *val2)
{
/* Find the file name associated with NODE_NUM. If there is no file const struct inode_val *ival1 = val1;
associated with NODE_NUM, return NULL. */ const struct inode_val *ival2 = val2;
return ival1->inode == ival2->inode
&& ival1->major_num == ival2->major_num
&& ival1->minor_num == ival2->minor_num;
}
char * char *
find_inode_file (unsigned long node_num, unsigned long major_num, find_inode_file (unsigned long node_num, unsigned long major_num,
unsigned long minor_num) unsigned long minor_num)
{ {
int start; /* Initial hash location. */ struct inode_val sample;
int temp; /* Rehash search variable. */ struct inode_val *ival;
if (hash_table != NULL) if (!hash_table)
{ return NULL;
/* Hash function is node number modulo the table size. */
start = node_num % hash_size; sample.inode = node_num;
sample.major_num = major_num;
/* Initial look into the table. */ sample.minor_num = minor_num;
if (hash_table[start] == NULL) ival = hash_lookup (hash_table, &sample);
return NULL; return ival ? ival->file_name : 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;
} }
/* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */ /* 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) unsigned long minor_num)
{ {
struct inode_val *temp; struct inode_val *temp;
struct inode_val *e;
/* Create new inode record. */ /* Create new inode record. */
temp = (struct inode_val *) xmalloc (sizeof (struct inode_val)); temp = (struct inode_val *) xmalloc (sizeof (struct inode_val));
temp->inode = node_num; 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->minor_num = minor_num;
temp->file_name = xstrdup (file_name); temp->file_name = xstrdup (file_name);
/* Do we have to increase the size of (or initially allocate) if (!((hash_table
the hash table? */ || (hash_table = hash_initialize (0, 0, inode_val_hasher,
if (hash_num == hash_size || hash_table == NULL) inode_val_compare, 0)))
{ && (e = hash_insert (hash_table, temp))))
struct inode_val **old_table; /* Pointer to old table. */ xalloc_die ();
int i; /* Index for re-insert loop. */ /* FIXME: e is not used */
/* 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++;
} }
@ -800,14 +758,14 @@ open_archive (char *file)
copy_in = process_copy_in; copy_in = process_copy_in;
if (copy_function == 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 else
{ {
if (!append_flag) 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); rsh_command_option);
else 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; return fd;
@ -887,7 +845,7 @@ get_next_reel (int tape_des)
tape_des = open_archive (archive_name); tape_des = open_archive (archive_name);
if (tape_des == -1) if (tape_des == -1)
error (1, errno, "%s", archive_name); open_error (archive_name);
} }
else else
{ {
@ -907,7 +865,7 @@ get_next_reel (int tape_des)
tape_des = open_archive (next_archive_name); tape_des = open_archive (next_archive_name);
if (tape_des == -1) if (tape_des == -1)
error (0, errno, "%s", next_archive_name); open_error (next_archive_name);
} }
while (tape_des < 0); 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 /* Take an input pathname and check it for CDF's. Insert an extra
`/' in the pathname after each "hidden" directory. If we add `/' in the pathname after each "hidden" directory. If we add
any `/'s, return a malloced string (which it will reuse for any `/'s, return a malloced string instead of the original input
later calls so our caller doesn't have to worry about freeing string.
the string) instead of the original input string. */ FIXME: This creates a memory leak.
*/
char * char *
add_cdf_double_slashes (char *input_name) add_cdf_double_slashes (char *input_name)
@ -1055,7 +1014,7 @@ add_cdf_double_slashes (char *input_name)
*p = '\0'; *p = '\0';
if ((*xstat) (input_name, &dir_stat) < 0) if ((*xstat) (input_name, &dir_stat) < 0)
{ {
error (0, errno, "%s", input_name); stat_error (input_name);
return input_name; return input_name;
} }
@ -1081,7 +1040,7 @@ add_cdf_double_slashes (char *input_name)
*p = '\0'; *p = '\0';
if ((*xstat) (input_name, &dir_stat) < 0) if ((*xstat) (input_name, &dir_stat) < 0)
{ {
error (0, errno, "%s", input_name); stat_error (input_name);
return input_name; return input_name;
} }
*p = '/'; *p = '/';
@ -1109,7 +1068,7 @@ islastparentcdf (char *path)
int slash_count; int slash_count;
int length; /* Length of result, not including NUL. */ int length; /* Length of result, not including NUL. */
slash = rindex (path, '/'); slash = strrchr (path, '/');
if (slash == 0) if (slash == 0)
return 0; return 0;
else else
@ -1131,9 +1090,6 @@ islastparentcdf (char *path)
#define DISKBLOCKSIZE (512) #define DISKBLOCKSIZE (512)
enum sparse_write_states { begin, in_zeros, not_in_zeros };
static int static int
buf_all_zeros (char *buf, int bufsize) 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. /* Write NBYTE bytes from BUF to remote tape connection FILDES.
Return the number of bytes written on success, -1 on error. */ Return the number of bytes written on success, -1 on error. */
int static int
sparse_write (int fildes, char *buf, unsigned int nbyte) sparse_write (int fildes, char *buf, unsigned int nbyte)
{ {
int complete_block_count; int complete_block_count;
@ -1162,7 +1118,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
int lseek_rc; int lseek_rc;
int write_rc; int write_rc;
int i; int i;
enum sparse_write_states state; enum { begin, in_zeros, not_in_zeros } state;
complete_block_count = nbyte / DISKBLOCKSIZE; complete_block_count = nbyte / DISKBLOCKSIZE;
leftover_bytes_count = nbyte % DISKBLOCKSIZE; leftover_bytes_count = nbyte % DISKBLOCKSIZE;
@ -1192,6 +1148,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
} }
buf += DISKBLOCKSIZE; buf += DISKBLOCKSIZE;
break; break;
case in_zeros : case in_zeros :
if (buf_all_zeros (buf, DISKBLOCKSIZE)) if (buf_all_zeros (buf, DISKBLOCKSIZE))
{ {
@ -1206,6 +1163,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
} }
buf += DISKBLOCKSIZE; buf += DISKBLOCKSIZE;
break; break;
case not_in_zeros : case not_in_zeros :
if (buf_all_zeros (buf, DISKBLOCKSIZE)) if (buf_all_zeros (buf, DISKBLOCKSIZE))
{ {
@ -1228,6 +1186,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
case in_zeros : case in_zeros :
delayed_seek_count = seek_count; delayed_seek_count = seek_count;
break; break;
case not_in_zeros : case not_in_zeros :
write_rc = write (fildes, cur_write_start, write_count); write_rc = write (fildes, cur_write_start, write_count);
delayed_seek_count = 0; delayed_seek_count = 0;
@ -1245,3 +1204,139 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
} }
return 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));
}