Import heavily trimmed gnu cpio-2.8.
(2.9 switched to gpl3 a few weeks later)
This commit is contained in:
parent
43c61ec889
commit
6ae22f7302
4
COPYING
4
COPYING
@ -2,7 +2,7 @@
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@ -305,7 +305,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
384
ChangeLog
384
ChangeLog
@ -1,3 +1,387 @@
|
||||
2007-06-08 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* configure.ac, NEWS: Version number 2.8
|
||||
* bootstrap.conf: Update
|
||||
|
||||
2007-06-07 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* NEWS: Update
|
||||
* configure.ac: Raise version to 2.7.90
|
||||
* doc/cpio.texi: Update
|
||||
* src/extern.h (set_perms, set_file_times): Take file descriptor
|
||||
as the first argument.
|
||||
* src/util.c (set_perms): Take file descriptor
|
||||
as the first argument and use fchmod/fchown if available. Fixes
|
||||
CAN-2005-1111.
|
||||
* src/copyin.c, src/copyout.c, src/copypass.c: Update calls to
|
||||
set_perms.
|
||||
* src/makepath.c: Remove useless includes.
|
||||
|
||||
* src/util.c (set_perms, stat_to_cpio): Use CPIO_UID and CPIO_GID
|
||||
macros to set uid and gid
|
||||
* src/main.c (process_args): Allow to use --owner in copy-out mode.
|
||||
* THANKS: Add Mike Frysinger
|
||||
|
||||
2007-05-18 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* bootstrap: Update from tar repository
|
||||
* doc/cpio.texi: Fix typo
|
||||
* src/copyin.c (from_ascii): Bugfix: allow for empty fields
|
||||
* src/copyout.c (process_copy_out): Fix memory leaks on
|
||||
orig_file_name.
|
||||
* src/copypass.c (process_copy_pass): symlink_error takes two
|
||||
arguments.
|
||||
* src/extern.h: Add missing includes.
|
||||
|
||||
2006-12-18 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* README-cvs: New file
|
||||
* lib/Makefile.tmpl, lib/bcopy.c, lib/mkdir.c, lib/strdup.c,
|
||||
lib/strerror.c, lib/.cvsignore, po/.cvsignore,
|
||||
po/Makevars: Removed
|
||||
* lib/Makefile.am: New file
|
||||
* po/POTFILES.in: Update
|
||||
* bootstrap: Synch with tar.
|
||||
* configure.ac: Update
|
||||
* gnulib.modules: Add lchown, strerror
|
||||
* src/Makefile.am: Update
|
||||
* src/main.c, src/mt.c: Include rmt-command.h instead of localedir.h
|
||||
* .cvsignore, doc/.cvsignore: Sort
|
||||
|
||||
* src/util.c (sparse_write): Static. Provide a forward
|
||||
declaration. Define enum sparse_write_states inside the function.
|
||||
|
||||
* src/copyin.c (long_format): Use PRIuMAX for printing file size
|
||||
* src/copyout.c (write_out_binary_header): Fix size conversion
|
||||
* src/extern.h (tape_toss_input, warn_if_file_changed): Last
|
||||
argument is off_t
|
||||
* src/util.c (tape_toss_input, warn_if_file_changed): Last
|
||||
argument is off_t
|
||||
(warn_if_file_changed): Use ngettext
|
||||
|
||||
2006-11-15 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/copypass.c: Fix setting output file permissions
|
||||
|
||||
2006-11-13 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* doc/cpio.texi: Consistently use @option{} for displaying command
|
||||
line options.
|
||||
Fix formatting in "Invoking `cpio'" section
|
||||
* src/main.c (process_args): Fix usage error diagnostics in
|
||||
copy-pass mode.
|
||||
|
||||
2006-10-24 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/copyout.c (process_copy_out): Add terminating zero to the
|
||||
link_name.
|
||||
|
||||
* tests/symlink.at: New testcase
|
||||
* tests/Makefile.am: New test symlink.at
|
||||
* tests/inout.at: Add keywords
|
||||
* tests/testsuite.at (AT_SKIP_TEST): New macro
|
||||
New test symlink.at
|
||||
|
||||
2006-10-21 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* configure.ac, NEWS: Version 2.7
|
||||
* gnulib.modules: Add stdint
|
||||
* src/util.c: Use STRINGIFY_BIGINT to display num_bytes
|
||||
|
||||
2006-09-27 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* TODO: Update
|
||||
* README-alpha: Update
|
||||
* bootstrap: Imported from tar
|
||||
* configure.ac: Require autoconf 2.59 and gettext 1.15
|
||||
* gnulib.modules: add inttypes
|
||||
* doc/cpio.texi: Minor fixes
|
||||
* po/Makevars: Remove automatically generated file
|
||||
* po/.cvsignore: Add Makevars
|
||||
* lib/.cvsignore: Update
|
||||
* src/copyin.c, src/copyout.c, src/copypass.c, src/cpio.h,
|
||||
src/cpiohdr.h, src/defer.c, src/defer.h, src/extern.h,
|
||||
src/global.c, src/main.c, src/makepath.c, src/tar.c,
|
||||
src/util.c: Update copyright year.
|
||||
|
||||
2006-07-04 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* bootstrap (update_po): Fix single translation update
|
||||
* lib/Makefile.tmpl: Initialize AM_CPPFLAGS
|
||||
(noinst_HEADERS): Add system-ioctl.h
|
||||
|
||||
Start rewriting using a better suited internal representation for
|
||||
the file meta-data.
|
||||
|
||||
* src/cpiohdr.h (struct old_cpio_header): Remove unused fields
|
||||
c_mtime, c_filesize and c_name.
|
||||
(struct old_ascii_header): New data type
|
||||
(struct new_ascii_header): New data type. Describes the header
|
||||
structure, not its internal representation.
|
||||
(struct cpio_file_stat): New data type. Describes internal
|
||||
representation of a file metadata
|
||||
|
||||
* src/copyin.c (from_ascii): New function
|
||||
Use cpio_file_stat for internal header representation.
|
||||
* src/copyout.c: Use cpio_file_stat for internal header
|
||||
representation. Among other things this fixes bug reported by
|
||||
Peter Vrabec on Mar 2, 2006
|
||||
(http://lists.gnu.org/archive/html/bug-cpio/2006-03/msg00000.html)
|
||||
* src/copypass.c: Use cpio_file_stat for internal header
|
||||
representation.
|
||||
* src/tar.c: Likewise
|
||||
* src/util.c: Likewise
|
||||
* src/defer.c: Likewise
|
||||
* src/defer.h: Likewise
|
||||
* src/extern.h: Likewise
|
||||
(from_ascii): New prototype
|
||||
(LG_8,LG_16,FROM_OCTAL,FROM_HEX): New defines
|
||||
* src/main.c: New command line option --HANG (hidden)
|
||||
|
||||
2006-03-12 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* tests/Makefile.am (AM_CPPFLAGS): Define LOCALEDIR
|
||||
|
||||
2006-02-18 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* gnulib.modules: Add stpcpy. Thanks Benigno B. Junior for
|
||||
reporting.
|
||||
* THANKS: Add Benigno B. Junior
|
||||
* src/makepath.c: Fix indentation.
|
||||
|
||||
2005-11-16 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/copyout.c (process_copy_out): Fix typo.
|
||||
|
||||
2005-11-12 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* bootstrap: Minor fix
|
||||
* src/copyout.c (write_out_header): Rewritten using separate
|
||||
functions for each file format. Use to_ascii to convert numbers to
|
||||
ascii representation. Check for overflows and report them if
|
||||
appropriate. Return 0 if it is OK to proceed with archiving this
|
||||
file, 1 otherwise. All callers updated.
|
||||
* src/extern.h (write_out_header): Return int.
|
||||
|
||||
2005-10-28 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/util.c: Include paxlib.
|
||||
* bootstrap: If file `.bootstrap' exists in the cwd and is
|
||||
readable, prepend its contents to the command line.
|
||||
|
||||
Fix Debian bug 335580:
|
||||
|
||||
* src/copyout.c (read_for_checksum,write_out_header): CRC is a
|
||||
32-bit unsigned value. Patch proposed by Jim Castleberry and
|
||||
Peter Vrabec.
|
||||
* src/extern.h (crc): Change declaration
|
||||
* src/global.c: Likewise
|
||||
* src/tar.c (tar_checksum): Return unsigned int
|
||||
|
||||
* THANKS: Add Jim Castleberry
|
||||
* NEWS: Updated
|
||||
|
||||
2005-09-30 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/copyout.c (process_copy_out): Discern between original and
|
||||
(eventually fixed) file name (in tar terminology, `file name'
|
||||
vs. `member name'.
|
||||
|
||||
2005-09-08 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* gnulib.modules: Add utimens
|
||||
* src/util.c (cpio_safer_name_suffix): Preserve ./ no matter what
|
||||
the value of strip_leading_dots is.
|
||||
(set_file_times): New function
|
||||
* src/extern.h (set_file_times): New function
|
||||
* src/copyin.c: Use set_file_times() to update file atime/mtime
|
||||
* src/copyout.c: Likewise.
|
||||
* src/copypass.c: Likewise.
|
||||
|
||||
2005-05-25 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* src/copyin.c: Use cpio_safer_name_suffix() and CPIO_TRAILER_NAME
|
||||
define instead of hardcoding the trailer file name.
|
||||
* src/copyout.c: Likewise.
|
||||
* src/cpio.h (CPIO_TRAILER_NAME): New define
|
||||
* src/extern.h (cpio_safer_name_suffix): New proto
|
||||
* src/tar.c: Use CPIO_TRAILER_NAME define instead of hardcoding
|
||||
the trailer file name.
|
||||
* src/util.c (cpio_safer_name_suffix): New function
|
||||
(add_cdf_double_slashes): Add FIXME warning.
|
||||
|
||||
* lib/fatal.c: New file
|
||||
* lib/Makefile.tmpl (libcpio_a_SOURCES): Add fatal.c
|
||||
* src/copyout.c: Use error reporting functions from paxlib
|
||||
* src/makepath.c: Likewise
|
||||
* src/mt.c: Likewise
|
||||
* src/main.c (fatal_exit): Moved to lib/fatal.c
|
||||
|
||||
2005-05-24 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* src/copyin.c (process_copy_in): Use safer_name_suffix no matter
|
||||
what the value of no_abs_paths_flag. The function knows better
|
||||
what to do in any case.
|
||||
* src/copyout.c (process_copy_out): Honor no_abs_paths_flag.
|
||||
* src/main.c (options): Minor fixes.
|
||||
|
||||
2005-05-23 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* bootstrap (copy_files): Create destination directory if it does
|
||||
not exist.
|
||||
Preserve longlong.m4 as longlong_gl.m4
|
||||
* src/main.c: Include paxlib.h
|
||||
|
||||
2005-05-22 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* lib/.cvsignore: Updated
|
||||
* gnulib.modules: Add hash
|
||||
* doc/cpio.texi (Reports): New chapter
|
||||
* lib/Makefile.tmpl: Add new paxutils files.
|
||||
* po/POTFILES.in: Likewise
|
||||
* src/copyin.c [!HAVE_LCHOWN] (lchown): Define to 0 to avoid
|
||||
changing ownership of the target file.
|
||||
(process_copy_in): Use safer_name_suffix()
|
||||
* src/main.c (parse_opt): Handle new --absolute-filenames option.
|
||||
(process_args): Updated
|
||||
* src/util.c: Rewrite inode lookup/insertion functions using hash
|
||||
module.
|
||||
|
||||
u2005-05-20 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* configure.ac: Raised version number to 2.6.90
|
||||
* NEWS: Updated
|
||||
* src/copyin.c: Use set_perms.
|
||||
* src/copypass.c: Likewise.
|
||||
* src/copyout.c (process_copy_out): Use stat_to_cpio() to convert
|
||||
struct stat to struct new_cpio_header.
|
||||
* src/defer.h: Remove legacy P_() stuff.
|
||||
* src/dstring.c: Likewise
|
||||
* src/extern.h: Likewise
|
||||
* src/util.c (stat_to_cpio,set_perms): New functions
|
||||
* doc/.cvsignore: Updated
|
||||
* lib/.cvsignore: Updated
|
||||
* tests/.cvsignore: Updated
|
||||
* .cvsignore: Updated
|
||||
* COPYING: Added to the repository
|
||||
|
||||
2005-05-19 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* po/POTFILES.in: Add paxerror.c paxexit.c paxconvert.c
|
||||
|
||||
* bootstrap (copy_files): Accept optional third argument: a prefix
|
||||
to be appended to destination file names.
|
||||
Import paxutils/paxlib files.
|
||||
* lib/Makefile.tmpl (libcpio_a_SOURCES): Add paxerror.c paxexit.c
|
||||
paxconvert.c
|
||||
* src/copyin.c: Use paxutils error reporting functions
|
||||
* src/copyout.c: Likewise
|
||||
* src/copypass.c: Likewise
|
||||
* src/util.c: Likewise. Add missing includes
|
||||
* src/main.c (USAGE_ERROR): Removed
|
||||
(CHECK_USAGE,parse_opt,process_args): Use error() instead of USAGE_ERROR
|
||||
(fatal_exit): New function
|
||||
* src/tar.c (is_tar_filename_too_long): Removed unused variable
|
||||
|
||||
* Makefile.am, configure.ac, doc/Makefile.am,
|
||||
doc/cpio.texi, doc/gendocs_template, headers/Makefile.am,
|
||||
headers/fnmatch.h, lib/Makefile.tmpl, lib/mkdir.c,
|
||||
lib/strdup.c, lib/strerror.c, src/Makefile.am,
|
||||
src/copyin.c, src/copyout.c, src/copypass.c, src/cpio.h,
|
||||
src/cpiohdr.h, src/defer.c, src/defer.h, src/dstring.c,
|
||||
src/dstring.h, src/extern.h, src/filemode.c,
|
||||
src/filetypes.h, src/global.c, src/idcache.c,
|
||||
src/main.c, src/makepath.c, src/mt.c, src/tar.c,
|
||||
src/tar.h, src/tarhdr.h, src/userspec.c, src/util.c,
|
||||
tests/Makefile.am, tests/inout.at, tests/testsuite.at,
|
||||
tests/version.at: Updated FSF postal mail address.
|
||||
|
||||
* bootstrap: Port recent changes from tar bootstrap.
|
||||
* gnulib.modules: New file
|
||||
* tests/Makefile.am (genfile_SOURCES,LDADD): Updated
|
||||
|
||||
* THANKS: Updated
|
||||
* configure.ac: Remove check for gethostname, it is never used.
|
||||
Remove check for setsockopt, it is provided by paxutils.
|
||||
|
||||
Fix LFS support issues. Proposed by Peter Vrabec and Dmitry V. Levin
|
||||
|
||||
* src/extern.h (copy_files_tape_to_disk, copy_files_disk_to_tape,
|
||||
copy_files_disk_to_disk): Change num_bytes argument type from
|
||||
long to off_t.
|
||||
* src/util.c (copy_files_tape_to_disk, copy_files_disk_to_tape,
|
||||
copy_files_disk_to_disk, disk_fill_input_buffer,
|
||||
write_nuls_to_file): Likewise.
|
||||
(write_nuls_to_file, copy_files_disk_to_tape,
|
||||
copy_files_disk_to_disk): Handle `off_t num_bytes' properly.
|
||||
|
||||
* src/util.c (find_inode_file): Fix typos causing function to
|
||||
occasionally miss inodes and, therefore, to copy out the same
|
||||
(hard-linked) file several times to archive. Proposed by Brian
|
||||
Mays.
|
||||
|
||||
2005-03-24 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* src/main.c (process_args): Fixed discrepancy I have been
|
||||
overlooking so far: cpio still does not handle --sparse option
|
||||
the same way tar is handling it. --sparse is allowed in copy-in
|
||||
and copy-pass modes, just as docs say it. Thanks Dmitry Levin.
|
||||
* THANKS: Updated
|
||||
|
||||
2005-03-21 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* src/util.c (disk_buffered_write): Fix typo introduced
|
||||
2005-01-11.
|
||||
* src/main.c (process_args): Fixed error message
|
||||
|
||||
2005-01-31 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* src/main.c (main): Remove umask(0). Fixes CAN-1999-1572.
|
||||
[__TURBOC__,__EMX__]: Removed
|
||||
* src/copypass.c (process_copy_pass): Set umask 0
|
||||
* src/copyin.c (process_copy_in): Likewise
|
||||
* src/util.c (open_archive): Use MODE_RW.
|
||||
|
||||
2005-01-11 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* doc/gendocs_template: Template file for gendocs.sh.
|
||||
* doc/Makefile.am: Use gendocs.sh to generate webdocs.
|
||||
* doc/cpio.texi: Updated.
|
||||
|
||||
* src/copyin.c: Use memset instead of bzero, memmove
|
||||
(or memcpy, if appropriate), instead of bcopy, and
|
||||
strchr/strrchr instead of index/rindex.
|
||||
* src/copypass.c: Likewise.
|
||||
* src/main.c: Likewise.
|
||||
* src/makepath.c: Likewise.
|
||||
* src/tar.c: Likewise.
|
||||
* src/util.c: Likewise.
|
||||
(write_nuls_to_file): Made extern. All callers updated
|
||||
|
||||
* src/copyout.c: Likewise. Use write_nuls_to_file instead
|
||||
of explicitely accessing zeros_512
|
||||
* src/userspec.c: Likewise.
|
||||
Rename isnumber to isnumber_p. Proposed by
|
||||
Albert Chin
|
||||
* src/extern.h (zeros_512): Removed
|
||||
(write_nuls_to_file): New function
|
||||
* src/global.c (zeros_512): Removed
|
||||
|
||||
2005-01-06 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* bootstrap: Add 'fileblocks' gnulib module
|
||||
Create paxutils.m4
|
||||
* configure.ac: Call cpio_PAXUTILS
|
||||
* src/main.c: Remove ifdef around setlocale
|
||||
* src/mt.c: Likewise
|
||||
|
||||
2004-12-21 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
* configure.ac: New option --enable-mt
|
||||
Check for locale.h
|
||||
* doc/cpio.info: Removed
|
||||
* src/mt.c (main): Use argmatch_invalid()
|
||||
|
||||
2004-12-20 Sergey Poznyakoff <gray@Mirddin.farlep.net>
|
||||
|
||||
Released version 2.6. Sources up to this point are tagged
|
||||
|
65
INSTALL
65
INSTALL
@ -1,8 +1,8 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
@ -10,7 +10,10 @@ unlimited permission to copy, distribute and modify it.
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
@ -23,9 +26,9 @@ debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
@ -35,20 +38,17 @@ some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' if you want to change it or regenerate `configure' using
|
||||
a newer version of `autoconf'.
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
@ -78,7 +78,7 @@ details on some of the pertinent environment variables.
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
@ -87,31 +87,29 @@ Compiling For Multiple Architectures
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not support the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a
|
||||
time in the source code directory. After you have installed the
|
||||
package for one architecture, use `make distclean' before reconfiguring
|
||||
for another architecture.
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PREFIX'.
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PREFIX', the package will
|
||||
use PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
@ -159,7 +157,7 @@ where SYSTEM can have one of these forms:
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
@ -189,9 +187,14 @@ them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
will cause the specified gcc to be used as the C compiler (unless it is
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
|
38
NEWS
38
NEWS
@ -1,10 +1,36 @@
|
||||
GNU cpio NEWS -- history of user-visible changes. 2004-12-20
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
GNU cpio NEWS -- history of user-visible changes. 2007-06-08
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
See the end of file for copying conditions.
|
||||
|
||||
Please send cpio bug reports to <bug-cpio@gnu.org>.
|
||||
|
||||
Version 2.6
|
||||
Version 2.8 - Sergey Poznyakoff, 2007-06-08
|
||||
|
||||
* Option --owner can be used in copy-out mode, allowing to uniformly override
|
||||
ownership of the files being added to the archive.
|
||||
|
||||
* Bugfixes:
|
||||
|
||||
** Symlinks were handled incorrectly in copy-out mode.
|
||||
** Fix handling of large files.
|
||||
** Fix setting the file permissions in copy-out mode.
|
||||
** Fix CAN-2005-1111
|
||||
|
||||
|
||||
Version 2.7 - Sergey Poznyakoff, 2006-10-21
|
||||
|
||||
* Improved error checking and diagnostics
|
||||
|
||||
* Bugfixes
|
||||
** Fixed CAN-1999-1572
|
||||
** Allow to use --sparse in both copy-in and copy-pass.
|
||||
** Fix bug that eventually caused copying out the same hard-linked
|
||||
file several times to archive.
|
||||
** Fix several LFS-related issues.
|
||||
** Fix Debian bug 335580.
|
||||
|
||||
|
||||
Version 2.6 - Sergey Poznyakoff, 2004-12-20
|
||||
|
||||
* Added NLS support
|
||||
|
||||
@ -107,7 +133,7 @@ multiple links and of multi-volume archives on floppy disks.
|
||||
----------------------------------------------------------------------
|
||||
Copyright information:
|
||||
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to anyone to make or distribute verbatim copies
|
||||
of this document as received, in any medium, provided that the
|
||||
@ -122,4 +148,8 @@ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
Local variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
time-stamp-start: "changes. "
|
||||
time-stamp-format: "%:y-%02m-%02d"
|
||||
time-stamp-end: "\n"
|
||||
end:
|
||||
|
8
THANKS
8
THANKS
@ -9,6 +9,12 @@ The following is a list of people who contributed to GNU cpio by
|
||||
reporting problems, suggesting various improvements or submitting actual
|
||||
code. Help us keep it complete and exempt of errors.
|
||||
|
||||
Benigno B. Junior <bbj@gentux.com.br>
|
||||
Brian Mays <brian@debian.org>
|
||||
Dmitry V. Levin <ldv@altlinux.org>
|
||||
Jim Castleberry <bhg9aha02@sneakemail.com>
|
||||
Holger Fleischmann <holger_fleischmann@mra.man.de>
|
||||
Matthew Braithwaite <mab@cnet.com>
|
||||
Mike Frysinger <vapier@gentoo.org>
|
||||
Mitsuru Chinen <mchinen@yamato.ibm.com>
|
||||
Holger Fleischmann <holger_fleischmann@mra.man.de>
|
||||
Peter Vrabec <pvrabec@redhat.com>
|
||||
|
357
TODO
357
TODO
@ -1,54 +1,21 @@
|
||||
Following is the list of cpio-related reports to bug-gnu-utils.
|
||||
Many of them appear to be fixed, but quite a number of them is
|
||||
probably still waiting for being handled. The list is sorted
|
||||
in reverse chronological order.
|
||||
probably still waiting for being handled. The list is divided
|
||||
into two parts, the messages are in somehow arbitrary order.
|
||||
|
||||
4. copyin.c cpio probably questions/rfc (score: 35)
|
||||
Author: Grzegorz Jaskiewicz <gj@pointblue.com.pl>
|
||||
Date: Tue, 24 Jun 2003 17:12:45 +0100
|
||||
Hi! I am currently working on module that (in GNU software)
|
||||
will be able to read/write cpio format (only ascii). Thus i am
|
||||
separating some of cpio structures into libcpio. I've been
|
||||
going through cop
|
||||
/archive/html/bug-gnu-utils/2003-06/msg00422.html (5,430 bytes)
|
||||
* Bug reports
|
||||
--------------
|
||||
|
||||
** cpio -d bug (fwd) (score: 47)
|
||||
Author: Christian Smith <csmith@micromuse.com>
|
||||
Date: Wed, 14 Nov 2001 02:06:46 +0000 (GMT)
|
||||
This was bounced from bug-cpio@bogus.example.com I guess that
|
||||
isn't set up yet. -- /"\ \ / ASCII RIBBON CAMPAIGN - AGAINST
|
||||
HTML MAIL X - AGAINST MS ATTACHMENTS / \ $ cpio --version GNU
|
||||
cpio version 2
|
||||
/archive/html/bug-gnu-utils/2001-11/msg00170.html (4,548 bytes)
|
||||
|
||||
5. RE: Problem when building on HP-UX 11i(11.11) (score: 4)
|
||||
Author: "Leon Strydom" <leon.strydom@tasima.co.za>
|
||||
Date: Thu, 13 Mar 2003 09:10:02 +0200
|
||||
Hi Bob, I got it to compile, thanks. The reason why I had to
|
||||
try GNU-Tar is because of the 2GB file size limit problems:
|
||||
Here are the errors I got: With TAR(hp-ux 11i tar): CMD: tar
|
||||
cvf backup.tar /a
|
||||
/archive/html/bug-gnu-utils/2003-03/msg00106.html (5,191 bytes)
|
||||
|
||||
6. cpio - large file support (score: 35)
|
||||
Author: "Keith Ansell" <keitha@edp.fastfreenet.com>
|
||||
Date: Tue, 4 Mar 2003 16:24:37 -0000
|
||||
Can you help. I need to archive a large database, this will
|
||||
create a cpio file greater than 2 Gigabytes. Have you added
|
||||
large file support to the build of cpio. Regards Keith
|
||||
Ansell.....
|
||||
/archive/html/bug-gnu-utils/2003-03/msg00024.html (4,329 bytes)
|
||||
|
||||
7. cpio-2.5 typos (score: 36)
|
||||
Author: Thomas Klausner <wiz@danbala.ifoer.tuwien.ac.at>
|
||||
Date: Sat, 21 Dec 2002 23:53:38 +0100
|
||||
In cpio-2.5, in cpio.texi (and thus cpio.1) and main.c the word
|
||||
'compatibility' is misspelled as 'compatability'. Please fix,
|
||||
thanks. Thomas -- Thomas Klausner - wiz@bogus.example.com What
|
||||
is wanted
|
||||
/archive/html/bug-gnu-utils/2002-12/msg00200.html (3,783 bytes)
|
||||
|
||||
9. Re: bug in cpio with tapechange in copy-in-mode (score: 46)
|
||||
Author: Paul Eggert <eggert@twinsun.com>
|
||||
Date: Mon, 5 Aug 2002 12:28:33 -0700 (PDT)
|
||||
Thanks for your bug report. Can you please verify that the bug
|
||||
still exists in the latest CPIO version
|
||||
<ftp://ftp.gnu.org/gnu/cpio/cpio-2.5.tar.gz>, and if so, please
|
||||
send a patch to <bug-cpio@bogus.
|
||||
/archive/html/bug-gnu-utils/2002-08/msg00127.html (4,275 bytes)
|
||||
|
||||
10. bug in cpio with tapechange in copy-in-mode (score: 34)
|
||||
** bug in cpio with tapechange in copy-in-mode (score: 34)
|
||||
Author: Bernd =?ISO-8859-1?Q?Sch=FCler?=
|
||||
<b.schueler@eckert-buerotechnik.de>
|
||||
Date: 05 Aug 2002 18:37:56 +0200
|
||||
@ -58,15 +25,7 @@ in reverse chronological order.
|
||||
sure, if the pr
|
||||
/archive/html/bug-gnu-utils/2002-08/msg00122.html (4,518 bytes)
|
||||
|
||||
11. Re: CPIO Bug ? (score: 36)
|
||||
Author: Albert Chin <bug-gnu-utils@lists.thewrittenword.com>
|
||||
Date: Thu, 4 Jul 2002 19:31:04 -0500
|
||||
I think the default CPIO format understands only 16-bit inodes.
|
||||
Look at the -H option. '-H newc' should work better for you. --
|
||||
albert chin (china@bogus.example.com)
|
||||
/archive/html/bug-gnu-utils/2002-07/msg00091.html (4,286 bytes)
|
||||
|
||||
14. Re: bug in cpio? (score: 40)
|
||||
** Re: bug in cpio? (score: 40)
|
||||
Author: kasal@matsrv.math.cas.cz (Stepan Kasal)
|
||||
Date: Thu, 13 Jun 2002 07:44:14 +0000 (UTC)
|
||||
Hallo, the following option should help: -d, --make-directories
|
||||
@ -75,44 +34,7 @@ in reverse chronological order.
|
||||
/home/kasal/tmp/db
|
||||
/archive/html/bug-gnu-utils/2002-06/msg00306.html (4,862 bytes)
|
||||
|
||||
15. bug in cpio? (score: 34)
|
||||
Author: "Jeff Holt" <jeff.holt@hotsos.com>
|
||||
Date: Wed, 12 Jun 2002 14:07:59 -0500
|
||||
According to the man page, I should be able to extract an
|
||||
absolute pathname from an archive and have the file created
|
||||
relative to the current directory (by removing the leading
|
||||
‘/’).<o:p>
|
||||
/archive/html/bug-gnu-utils/2002-06/msg00296.html (5,331 bytes)
|
||||
|
||||
16. CPIO Bug ? (score: 35)
|
||||
Author: =?iso-8859-1?Q?Gr=E9goire_Fiot?=
|
||||
<gfiot@eiffageconstruction.fr>
|
||||
Date: Tue, 14 May 2002 17:01:18 +0200
|
||||
Hello, We ve got a problem here using cpio: many "troncating
|
||||
inode number" appear during the process: cpio -ocv Is that a
|
||||
real problem? Does it corrupt files? Well.. what does that
|
||||
mean? We have look
|
||||
/archive/html/bug-gnu-utils/2002-05/msg00333.html (3,855 bytes)
|
||||
|
||||
23. [cpio texinfo] typo (score: 2)
|
||||
Author: fabrice bauzac <fabrice.bauzac@wanadoo.fr>
|
||||
Date: Tue, 7 May 2002 16:37:28 +0200
|
||||
Good afternoon, There is a typo in the Texinfo documentation of
|
||||
GNU cpio, node "Copy-in mode": [--format=format]
|
||||
[--owner=[user][:.][group]] [--no- preserve-owner]
|
||||
[--message=message] [--help] [--ver
|
||||
/archive/html/bug-gnu-utils/2002-05/msg00153.html (4,040 bytes)
|
||||
|
||||
26. cpio: memory exhausted (score: 43)
|
||||
Author: Thomas McLaughlin <tamm@scotlegal.com>
|
||||
Date: Thu, 18 Apr 2002 09:51:18 +0100
|
||||
This is probably not the place for my query, but I have
|
||||
exhausted other avenues and would be glad of some help. I can't
|
||||
work out what's going on with my nightly cpio backup. If I do:
|
||||
cd / find . -pri
|
||||
/archive/html/bug-gnu-utils/2002-04/msg00406.html (4,988 bytes)
|
||||
|
||||
30. cpio 2.4.2 bug? (score: 40)
|
||||
** cpio 2.4.2 bug? (score: 40)
|
||||
Author: "H.J. Thomassen" <H.J.Thomassen@ATComputing.nl>
|
||||
Date: Thu, 10 Jan 2002 18:09:10 +0100 (CET)
|
||||
Hello, We use GNU-cpio 2.4.2 and have the following problem:
|
||||
@ -120,62 +42,9 @@ in reverse chronological order.
|
||||
hardlinks to the same i-node. I make a crc-cpio archive with
|
||||
both files; th
|
||||
/archive/html/bug-gnu-utils/2002-01/msg00161.html (5,624 bytes)
|
||||
|
||||
32. GNU cpio suggestion (score: 42)
|
||||
Author: "H.J.Thomassen" <hjt@ATComputing.nl>
|
||||
Date: Mon, 17 Dec 2001 11:27:11 +0100
|
||||
Re: suggestion for GNU-cpio extension (plus reference
|
||||
implementation) We use cpio for our backup purposes. The backup
|
||||
is started automatically in the middle of the night. To chase
|
||||
away all users we d
|
||||
/archive/html/bug-gnu-utils/2001-12/msg00244.html (7,474 bytes)
|
||||
|
||||
35. GNU cpio compile problem (score: 34)
|
||||
Author: Daniel Savard <dsavard@videotron.ca>
|
||||
Date: Wed, 14 Nov 2001 12:43:11 -0500
|
||||
Hi, I am trying to make the GNU cpio utility (version 2.4.2)
|
||||
using the gcc 3.0.2 compiler. The make failed on the userspec.c
|
||||
file compilation. I then tried to compile with gcc 2.95.3 with
|
||||
the followi
|
||||
/archive/html/bug-gnu-utils/2001-11/msg00180.html (5,518 bytes)
|
||||
|
||||
36. cpio -d bug (fwd) (score: 47)
|
||||
Author: Christian Smith <csmith@micromuse.com>
|
||||
Date: Wed, 14 Nov 2001 02:06:46 +0000 (GMT)
|
||||
This was bounced from bug-cpio@bogus.example.com I guess that
|
||||
isn't set up yet. -- /"\ \ / ASCII RIBBON CAMPAIGN - AGAINST
|
||||
HTML MAIL X - AGAINST MS ATTACHMENTS / \ $ cpio --version GNU
|
||||
cpio version 2
|
||||
/archive/html/bug-gnu-utils/2001-11/msg00170.html (4,548 bytes)
|
||||
|
||||
38. [cpio] man page enhancement: a Example section ? (score: 5)
|
||||
Author: Yannick Patois <patois@calvix.org>
|
||||
Date: Wed, 24 Oct 2001 12:48:33 +0200 (CEST)
|
||||
Hello, I seldom use cpio (as I think many people) and only had
|
||||
to use it once or twice. IMHA, would be good to have a small
|
||||
section with an example of most often performed actions
|
||||
(creating an archiv
|
||||
/archive/html/bug-gnu-utils/2001-10/msg00270.html (4,336 bytes)
|
||||
|
||||
39. Patch to cpio to enable verbose *skipping* of files (score: 40)
|
||||
Author: Tomas Pospisek <tpo@sourcepole.ch>
|
||||
Date: Mon, 8 Oct 2001 13:54:14 +0200 (CEST)
|
||||
This patch enables cpio to be verbose about the files that it
|
||||
does not copy, which is very handy for seeing cpio's progress
|
||||
through a tape or simply for debuging. The patch along with a
|
||||
Debian packag
|
||||
/archive/html/bug-gnu-utils/2001-10/msg00083.html (4,548 bytes)
|
||||
|
||||
40. cpio-2.4.2 patch (score: 39)
|
||||
Author: Alex Efros <powerman@sky.net.ua>
|
||||
Date: Wed, 29 Aug 2001 07:36:31 +0300 (EEST)
|
||||
Hi. Linux-2.4.9, GCC-3.0, GLIBC-2.2.4, cpio-2.4.2. Compile-time
|
||||
errors: --cut-- gcc -c -DRETSIGTYPE=void -DHAVE_SYS_MTIO_H=1
|
||||
-DHAVE_NETDB_H=1 -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1
|
||||
-DHAVE_STRING_H=1 -DHA
|
||||
/archive/html/bug-gnu-utils/2001-08/msg00264.html (5,259 bytes)
|
||||
|
||||
41. cpio copy-in and multiply-linked files (score: 35)
|
||||
|
||||
** These two seem to be related:
|
||||
*** cpio copy-in and multiply-linked files (score: 35)
|
||||
Author: Chris Jaeger <cjaeger@ensim.com>
|
||||
Date: Tue, 07 Aug 2001 23:46:04 -0700
|
||||
Hi, I was wondering whether it was a bug or a feature that GNU
|
||||
@ -184,14 +53,7 @@ in reverse chronological order.
|
||||
due to th
|
||||
/archive/html/bug-gnu-utils/2001-08/msg00074.html (4,142 bytes)
|
||||
|
||||
42. Re: minor problems with slackware-current (score: 7)
|
||||
Author: Cezary Sliwa <sliwa@cft.edu.pl>
|
||||
Date: Wed, 1 Aug 2001 10:43:37 +0200
|
||||
"cpio --sparse" corrupts data. A fix attached. C.S. Attachment:
|
||||
cpio-2.4.2-sparse.diff Description: Text document
|
||||
/archive/html/bug-gnu-utils/2001-08/msg00000.html (3,989 bytes)
|
||||
|
||||
43. (no subject) (score: 2)
|
||||
*** (no subject) (score: 2)
|
||||
Author: brian@debian.org (Brian Mays)
|
||||
Date: Sat, 07 Jul 2001 16:35:13 -0400
|
||||
When hard-linked files (along with many other files) are
|
||||
@ -200,69 +62,24 @@ in reverse chronological order.
|
||||
the same set of fil
|
||||
/archive/html/bug-gnu-utils/2001-07/msg00080.html (5,666 bytes)
|
||||
|
||||
44. gnu cpio and files over 2G (score: 37)
|
||||
Author: J.S.Peatfield@damtp.cam.ac.uk
|
||||
Date: Wed, 2 May 2001 06:28:18 +0100
|
||||
As an increasing number of opertaing systems now support files
|
||||
over 2G I took a look at the cpio (2.4.2) source to see how
|
||||
hard it would be to make it cope, and was slightly shocked at
|
||||
the number of
|
||||
/archive/html/bug-gnu-utils/2001-05/msg00010.html (4,802 bytes)
|
||||
** These too:
|
||||
|
||||
*** Re: minor problems with slackware-current (score: 7)
|
||||
Author: Cezary Sliwa <sliwa@cft.edu.pl>
|
||||
Date: Wed, 1 Aug 2001 10:43:37 +0200
|
||||
"cpio --sparse" corrupts data. A fix attached. C.S. Attachment:
|
||||
cpio-2.4.2-sparse.diff Description: Text document
|
||||
/archive/html/bug-gnu-utils/2001-08/msg00000.html (3,989 bytes)
|
||||
|
||||
45. cpio suggestion + patch (score: 38)
|
||||
Author: Taylor Gautier <tgautier@s8.com>
|
||||
Date: Fri, 20 Apr 2001 09:40:05 -0700
|
||||
I have a suggestion for cpio. The suggestion is to make it copy
|
||||
files into a temporary name and then rename the file as the
|
||||
last operation. Since UNIX filesystems are supposed to
|
||||
gaurantee atomicity
|
||||
/archive/html/bug-gnu-utils/2001-04/msg00169.html (10,674
|
||||
bytes)
|
||||
|
||||
46. [cpio 2.4.2] rmt build fails (score: 8)
|
||||
Author: Gert <n8w8@n8w8.wox.org>
|
||||
Date: Thu, 29 Mar 2001 21:28:52 +0200 (CEST)
|
||||
Hi, The cpio 2.4.2 rmt tool fails to build on my system. I run
|
||||
the following software: - Linux 2.4.2 - GCC 2.95.2 - GNU Make
|
||||
3.79.1 - GNU ld 2.10 (with BFD 2.10) - glibc 2.1.3 The build
|
||||
fails like th
|
||||
/archive/html/bug-gnu-utils/2001-03/msg00262.html (5,498 bytes)
|
||||
|
||||
47. cpio --sparse (score: 34)
|
||||
*** cpio --sparse (score: 34)
|
||||
Author: Cezary Sliwa <sliwa@cft.edu.pl>
|
||||
Date: Mon, 26 Mar 2001 10:43:34 +0200 (CEST)
|
||||
the '--sparse' option of gnu cpio causes data corruption
|
||||
(blocks of zeros are lost or appended to other files). C.S.
|
||||
/archive/html/bug-gnu-utils/2001-03/msg00235.html (3,671 bytes)
|
||||
|
||||
49. Re: bug with gnu cpio 2.4.2 (score: 38)
|
||||
Author: Hans-Bernhard Broeker <broeker@physik.rwth-aachen.de>
|
||||
Date: 6 Mar 2001 15:19:34 GMT
|
||||
This would happen if cpio want to do any user interaction (ask
|
||||
for the next tape cartridge, because the current one is full,
|
||||
e.g.). Cron jobs don't have access to a terminal (/dev/tty), so
|
||||
this will
|
||||
/archive/html/bug-gnu-utils/2001-03/msg00029.html (5,062 bytes)
|
||||
|
||||
50. bug with gnu cpio 2.4.2 (score: 37)
|
||||
Author: dominique.bieber@sagem.com
|
||||
Date: Tue, 6 Mar 2001 12:27:14 +0100
|
||||
Hi, I have a problem using cpio with a Red Hat 6.2 whith a
|
||||
2.2.14-5.0smp kernel. The backup device is a HP DAT DDS4 20/40
|
||||
with the right cartridge. The cpio is launched by the cron.
|
||||
During the backup
|
||||
/archive/html/bug-gnu-utils/2001-03/msg00024.html (4,315 bytes)
|
||||
|
||||
52. [PATCH] cpio 2.4.2 does not compile with libc 2.2, gcc 2.95
|
||||
(score: 38)
|
||||
Author: "John Fremlin" <chief@bandits.org>
|
||||
Date: 11 Feb 2001 22:19:09 +0000
|
||||
In fact it violates the GNU coding standards by declaring stuff
|
||||
when it shouldn't. Tsk, tsk. Attachment: cpio-2.4.2-build.patch
|
||||
Description: Text Data -- http://www.penguinpowered.com/~vii
|
||||
/archive/html/bug-gnu-utils/2001-02/msg00065.html (4,169 bytes)
|
||||
|
||||
53. cpio-2.4.2: data corruption bug (score: 35)
|
||||
|
||||
** And these too
|
||||
*** cpio-2.4.2: data corruption bug (score: 35)
|
||||
Author: Todd Kelley <toddk@oeone.com>
|
||||
Date: Fri, 09 Feb 2001 17:00:06 -0500
|
||||
Hello, Recently at OEone we fixed a bug in GNU cpio-2.4.2: When
|
||||
@ -271,7 +88,16 @@ in reverse chronological order.
|
||||
corrupted. The crc do
|
||||
/archive/html/bug-gnu-utils/2001-02/msg00062.html (4,297 bytes)
|
||||
|
||||
54. cpio 2.4.2 unconditionally takes the tape drive offline (score:
|
||||
*** cpio pass-through can corrupt files (score: 36)
|
||||
Author: "Parrott, Jeff" <Jeff.Parrott@sea.siemens.com>
|
||||
Date: Mon, 16 Oct 2000 13:32:57 -0400
|
||||
I have seen corrupted files as a result of using the
|
||||
pass-through option in cpio. The corruption occurs when
|
||||
active/in-use (and growing) files are being copied. The problem
|
||||
is that the file size has
|
||||
/archive/html/bug-gnu-utils/2000-10/msg00087.html (4,974 bytes)
|
||||
|
||||
** cpio 2.4.2 unconditionally takes the tape drive offline (score:
|
||||
39)
|
||||
Author: Scott Larson <scowl@plaza.ds.adp.com>
|
||||
Date: Thu, 11 Jan 2001 13:15:52 -0800
|
||||
@ -281,7 +107,7 @@ in reverse chronological order.
|
||||
tape) after rea
|
||||
/archive/html/bug-gnu-utils/2001-01/msg00087.html (4,264 bytes)
|
||||
|
||||
55. cpio -t can see international filenames, find -ls also suffers
|
||||
** cpio -t can see international filenames, find -ls also suffers
|
||||
(score: 35)
|
||||
Author: "Dan Jacobson" <jidanni@kimo.FiXcomTHiS.tw>
|
||||
Date: Tue, 26 Dec 2000 07:38:53 +0800
|
||||
@ -291,66 +117,43 @@ in reverse chronological order.
|
||||
http://www.geocities.com/jidanni
|
||||
/archive/html/bug-gnu-utils/2000-12/msg00143.html (4,084 bytes)
|
||||
|
||||
56. cpio-2.4.2 compilation problems (score: 34)
|
||||
Author: Thomas =?iso-8859-1?q?K=F6ller?= <tkoeller@gmx.net>
|
||||
Date: Wed, 20 Dec 2000 02:50:24 +0100
|
||||
I encountered several problems building cpio-2.4.2. I am
|
||||
running linux-2.2.17, glibc-2.1.3 and gcc 2.95.2. The errors I
|
||||
received were mostly due to the source files re-declaring
|
||||
things unconditionall
|
||||
/archive/html/bug-gnu-utils/2000-12/msg00109.html (5,782 bytes)
|
||||
* Suggestions
|
||||
-------------
|
||||
|
||||
** GNU cpio suggestion (score: 42)
|
||||
Author: "H.J.Thomassen" <hjt@ATComputing.nl>
|
||||
Date: Mon, 17 Dec 2001 11:27:11 +0100
|
||||
Re: suggestion for GNU-cpio extension (plus reference
|
||||
implementation) We use cpio for our backup purposes. The backup
|
||||
is started automatically in the middle of the night. To chase
|
||||
away all users we d
|
||||
/archive/html/bug-gnu-utils/2001-12/msg00244.html (7,474 bytes)
|
||||
|
||||
58. cpio-2.4.2 & glibc-2.* (score: 46)
|
||||
Author: Florian Wunderlich <fwunderlich@devbrain.de>
|
||||
Date: Mon, 18 Dec 2000 16:25:00 +0100
|
||||
I still do not see a new version of cpio or at least extra
|
||||
patches that fix it so it works with the glibc. Thus, here is a
|
||||
simple patch to make it compile with glibc: diff -u
|
||||
cpio-2.4.2-old/rmt.c cpi
|
||||
/archive/html/bug-gnu-utils/2000-12/msg00098.html (4,846 bytes)
|
||||
** cpio suggestion + patch (score: 38)
|
||||
Author: Taylor Gautier <tgautier@s8.com>
|
||||
Date: Fri, 20 Apr 2001 09:40:05 -0700
|
||||
I have a suggestion for cpio. The suggestion is to make it copy
|
||||
files into a temporary name and then rename the file as the
|
||||
last operation. Since UNIX filesystems are supposed to
|
||||
gaurantee atomicity
|
||||
/archive/html/bug-gnu-utils/2001-04/msg00169.html (10,674
|
||||
bytes)
|
||||
|
||||
60. cpio-2.4.2 signed-unsigned int disagreement with malloc (score:
|
||||
39)
|
||||
Author: Antonomasia <ant@notatla.demon.co.uk>
|
||||
Date: Mon, 27 Nov 2000 07:05:01 GMT
|
||||
copyin.c: 534 link_name = (char *) xmalloc ((unsigned int)
|
||||
file_hdr.c_filesize + 1); 535 link_name[file_hdr.c_filesize] =
|
||||
'\0'; file_hdr.c_filesize can be a large negative number as
|
||||
seen here then th
|
||||
/archive/html/bug-gnu-utils/2000-11/msg00171.html (4,718 bytes)
|
||||
** [cpio] man page enhancement: a Example section ? (score: 5)
|
||||
Author: Yannick Patois <patois@calvix.org>
|
||||
Date: Wed, 24 Oct 2001 12:48:33 +0200 (CEST)
|
||||
Hello, I seldom use cpio (as I think many people) and only had
|
||||
to use it once or twice. IMHA, would be good to have a small
|
||||
section with an example of most often performed actions
|
||||
(creating an archiv
|
||||
/archive/html/bug-gnu-utils/2001-10/msg00270.html (4,336 bytes)
|
||||
|
||||
** Patch to cpio to enable verbose *skipping* of files (score: 40)
|
||||
Author: Tomas Pospisek <tpo@sourcepole.ch>
|
||||
Date: Mon, 8 Oct 2001 13:54:14 +0200 (CEST)
|
||||
This patch enables cpio to be verbose about the files that it
|
||||
does not copy, which is very handy for seeing cpio's progress
|
||||
through a tape or simply for debuging. The patch along with a
|
||||
Debian packag
|
||||
/archive/html/bug-gnu-utils/2001-10/msg00083.html (4,548 bytes)
|
||||
|
||||
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)
|
||||
|
317
doc/cpio.texi
317
doc/cpio.texi
@ -3,94 +3,70 @@
|
||||
@setfilename cpio.info
|
||||
@settitle cpio
|
||||
@setchapternewpage off
|
||||
@set VERSION GNU cpio 2.5
|
||||
@set RELEASEDATE June 2002
|
||||
@c %**end of header
|
||||
|
||||
@ifinfo
|
||||
@format
|
||||
START-INFO-DIR-ENTRY
|
||||
* cpio: (cpio). Making tape (or disk) archives.
|
||||
END-INFO-DIR-ENTRY
|
||||
@end format
|
||||
@end ifinfo
|
||||
@dircategory Archiving
|
||||
@direntry
|
||||
* Cpio: (cpio). Copy-in-copy-out archiver to tape or disk.
|
||||
@end direntry
|
||||
|
||||
@ifinfo
|
||||
This file documents @value{VERSION}.
|
||||
@include version.texi
|
||||
|
||||
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
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
@ignore
|
||||
Permission is granted to process this file through TeX and print the
|
||||
results, provided the printed document carries copying permission
|
||||
notice identical to this one except for the removal of this paragraph
|
||||
|
||||
|
||||
@end ignore
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided that the entire
|
||||
resulting derived work is distributed under the terms of a permission
|
||||
notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the above conditions for modified versions,
|
||||
except that this permission notice may be stated in a translation approved
|
||||
by the Foundation.
|
||||
@end ifinfo
|
||||
Copyright @copyright{} 1995, 2001, 2002, 2004 Free Software Foundation, Inc.
|
||||
@sp 1
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.2 or
|
||||
any later version published by the Free Software Foundation; with no
|
||||
Invariant Sections, with the Front-Cover texts being ``A GNU Manual'',
|
||||
and with the Back-Cover Texts as in (a) below. A copy of the license
|
||||
is included in the section entitled ``GNU Free Documentation License''.
|
||||
|
||||
(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
|
||||
this GNU Manual, like GNU software. Copies published by the Free
|
||||
Software Foundation raise funds for GNU development.''
|
||||
@end quotation
|
||||
@end copying
|
||||
|
||||
@titlepage
|
||||
@title GNU CPIO
|
||||
@subtitle @value{VERSION} @value{RELEASEDATE}
|
||||
@subtitle @value{VERSION} @value{UPDATED}
|
||||
@author by Robert Carleton
|
||||
@c copyright page
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
Copyright @copyright{} 1995, 2001, 2002 Free Software Foundation, Inc.
|
||||
@sp 2
|
||||
This is the first edition of the GNU cpio documentation,@*
|
||||
and is consistent with @value{VERSION}.@*
|
||||
@insertcopying
|
||||
@sp 2
|
||||
Published by the Free Software Foundation @*
|
||||
59 Temple Place - Suite 330, @*
|
||||
Boston, MA 02111-1307, USA @*
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided that the entire
|
||||
resulting derived work is distributed under the terms of a permission
|
||||
notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the above conditions for modified versions,
|
||||
except that this permission notice may be stated in a translation
|
||||
approved by the Free Software Foundation.
|
||||
51 Franklin Street, Fifth Floor, @*
|
||||
Boston, MA 02110-1301, USA @*
|
||||
@end titlepage
|
||||
|
||||
@ifinfo
|
||||
@node Top, Introduction, (dir), (dir)
|
||||
@comment node-name, next, previous, up
|
||||
|
||||
@ifinfo
|
||||
@top
|
||||
|
||||
GNU cpio is a tool for creating and extracting archives, or copying
|
||||
files from one place to another. It handles a number of cpio formats as
|
||||
well as reading and writing tar files. This is the first edition of the
|
||||
GNU cpio documentation and is consistant with @value{VERSION}.
|
||||
GNU cpio documentation and is consistent with @value{VERSION}.
|
||||
|
||||
@end ifinfo
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
* Tutorial:: Getting started.
|
||||
* Invoking `cpio':: How to invoke `cpio'.
|
||||
* Invoking cpio:: How to invoke @command{cpio}.
|
||||
* Media:: Using tapes and other archive media.
|
||||
* Reports:: Reporting bugs or suggestions
|
||||
* Concept Index:: Concept index.
|
||||
|
||||
@detailmenu
|
||||
--- The Detailed Node Listing ---
|
||||
|
||||
Invoking cpio
|
||||
@ -99,9 +75,9 @@ Invoking cpio
|
||||
* Copy-in mode::
|
||||
* Copy-pass mode::
|
||||
* Options::
|
||||
@end menu
|
||||
|
||||
@end ifinfo
|
||||
@end detailmenu
|
||||
@end menu
|
||||
|
||||
@node Introduction, Tutorial, Top, Top
|
||||
@comment node-name, next, previous, up
|
||||
@ -112,13 +88,13 @@ can be another file on the disk, a magnetic tape, or a pipe.
|
||||
|
||||
GNU cpio supports the following archive formats: binary, old ASCII, new
|
||||
ASCII, crc, HPUX binary, HPUX old ASCII, old tar, and POSIX.1 tar. The
|
||||
tar format is provided for compatability with the tar program. By
|
||||
tar format is provided for compatibility with the tar program. By
|
||||
default, cpio creates binary format archives, for compatibility with
|
||||
older cpio programs. When extracting from archives, cpio automatically
|
||||
recognizes which kind of archive it is reading and can read archives
|
||||
created on machines with a different byte-order.
|
||||
|
||||
@node Tutorial, Invoking `cpio', Introduction, Top
|
||||
@node Tutorial, Invoking cpio, Introduction, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Tutorial
|
||||
@cindex creating a cpio archive
|
||||
@ -134,7 +110,7 @@ disks, or one or more tapes.
|
||||
|
||||
When creating an archive, cpio takes the list of files to be processed
|
||||
from the standard input, and then sends the archive to the standard
|
||||
output, or to the device defined by the @samp{-F} option.
|
||||
output, or to the device defined by the @option{-F} option.
|
||||
@xref{Copy-out mode}. Usually find or ls is used to provide this list
|
||||
to the standard input. In the following example you can see the
|
||||
possibilities for archiving the contents of a single directory.
|
||||
@ -146,9 +122,9 @@ possibilities for archiving the contents of a single directory.
|
||||
@end cartouche
|
||||
@end example
|
||||
|
||||
The @samp{-o} option creates the archive, and the @samp{-v} option
|
||||
The @option{-o} option creates the archive, and the @option{-v} option
|
||||
prints the names of the files archived as they are added. Notice that
|
||||
the options can be put together after a single @samp{-} or can be placed
|
||||
the options can be put together after a single @option{-} or can be placed
|
||||
separately on the command line. The @samp{>} redirects the cpio output
|
||||
to the file @samp{directory.cpio}.
|
||||
|
||||
@ -165,12 +141,12 @@ provide the file list to cpio:
|
||||
|
||||
|
||||
This will take all the files in the current directory, the directories
|
||||
below and place them in the archive tree.cpio. Again the @samp{-o}
|
||||
creates an archive, and the @samp{-v} option shows you the name of the
|
||||
files as they are archived. @xref{Copy-out mode}. Using the `.' in the
|
||||
below and place them in the archive tree.cpio. Again the @option{-o}
|
||||
creates an archive, and the @option{-v} option shows you the name of the
|
||||
files as they are archived. @xref{Copy-out mode}. Using the @samp{.} in the
|
||||
find statement will give you more flexibility when doing restores, as it
|
||||
will save file names with a relative path vice a hard wired, absolute
|
||||
path. The @samp{-depth} option forces @samp{find} to print of the
|
||||
path. The @option{-depth} option forces @samp{find} to print of the
|
||||
entries in a directory before printing the directory itself. This
|
||||
limits the effects of restrictive directory permissions by printing the
|
||||
directory entries in a directory before the directory name itself.
|
||||
@ -190,10 +166,10 @@ overwrite existing files unless you tell it to.
|
||||
@end example
|
||||
|
||||
This will retrieve the files archived in the file directory.cpio and
|
||||
place them in the present directory. The @samp{-i} option extracts the
|
||||
archive and the @samp{-v} shows the file names as they are extracted.
|
||||
place them in the present directory. The @option{-i} option extracts the
|
||||
archive and the @option{-v} shows the file names as they are extracted.
|
||||
If you are dealing with an archived directory tree, you need to use the
|
||||
@samp{-d} option to create directories as necessary, something like:
|
||||
@option{-d} option to create directories as necessary, something like:
|
||||
|
||||
@example
|
||||
@cartouche
|
||||
@ -223,13 +199,13 @@ argument. @xref{Copy-pass mode}.
|
||||
|
||||
The example shows copying the files of the present directory, and
|
||||
sub-directories to a new directory called new-dir. Some new options are
|
||||
the @samp{-print0} available with GNU find, combined with the
|
||||
@samp{--null} option of cpio. These two options act together to send
|
||||
the @option{-print0} available with GNU find, combined with the
|
||||
@option{--null} option of cpio. These two options act together to send
|
||||
file names between find and cpio, even if special characters are
|
||||
embedded in the file names. Another is @samp{-p}, which tells cpio to
|
||||
embedded in the file names. Another is @option{-p}, which tells cpio to
|
||||
pass the files it finds to the directory @samp{new-dir}.
|
||||
|
||||
@node Invoking `cpio', Media, Tutorial, Top
|
||||
@node Invoking cpio, Media, Tutorial, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Invoking cpio
|
||||
@cindex invoking cpio
|
||||
@ -242,7 +218,7 @@ pass the files it finds to the directory @samp{new-dir}.
|
||||
* Options::
|
||||
@end menu
|
||||
|
||||
@node Copy-out mode, Copy-in mode, Invoking `cpio', Invoking `cpio'
|
||||
@node Copy-out mode, Copy-in mode, Invoking cpio, Invoking cpio
|
||||
@comment node-name, next, previous, up
|
||||
@section Copy-out mode
|
||||
|
||||
@ -264,7 +240,7 @@ cpio @{-o|--create@} [-0acvABLV] [-C bytes] [-H format]
|
||||
< name-list [> archive]
|
||||
@end example
|
||||
|
||||
@node Copy-in mode, Copy-pass mode, Copy-out mode, Invoking `cpio'
|
||||
@node Copy-in mode, Copy-pass mode, Copy-out mode, Invoking cpio
|
||||
@comment node-name, next, previous, up
|
||||
@section Copy-in mode
|
||||
|
||||
@ -272,8 +248,8 @@ In copy-in mode, cpio copies files out of an archive or lists the
|
||||
archive contents. It reads the archive from the standard input. Any
|
||||
non-option command line arguments are shell globbing patterns; only
|
||||
files in the archive whose names match one or more of those patterns are
|
||||
copied from the archive. Unlike in the shell, an initial `.' in a
|
||||
filename does match a wildcard at the start of a pattern, and a `/' in a
|
||||
copied from the archive. Unlike in the shell, an initial @samp{.} in a
|
||||
filename does match a wildcard at the start of a pattern, and a @samp{/} in a
|
||||
filename can match wildcards. If no patterns are given, all files are
|
||||
extracted. @xref{Options}.
|
||||
|
||||
@ -288,11 +264,11 @@ cpio @{-i|--extract@} [-bcdfmnrtsuvBSV] [-C bytes] [-E file]
|
||||
[--swap-halfwords] [--io-size=bytes] [--pattern-file=file]
|
||||
[--format=format] [--owner=[user][:.][group]]
|
||||
[--no-preserve-owner] [--message=message] [--help] [--version]
|
||||
[-no-absolute-filenames] [--sparse] [-only-verify-crc] [-quiet]
|
||||
[--no-absolute-filenames] [--sparse] [-only-verify-crc] [-quiet]
|
||||
[--rsh-command=command] [pattern...] [< archive]
|
||||
@end example
|
||||
|
||||
@node Copy-pass mode, Options, Copy-in mode, Invoking `cpio'
|
||||
@node Copy-pass mode, Options, Copy-in mode, Invoking cpio
|
||||
@comment node-name, next, previous, up
|
||||
@section Copy-pass mode
|
||||
|
||||
@ -314,7 +290,7 @@ cpio @{-p|--pass-through@} [-0adlmuvLV] [-R [user][:.][group]]
|
||||
|
||||
|
||||
|
||||
@node Options, , Copy-pass mode, Invoking `cpio'
|
||||
@node Options, , Copy-pass mode, Invoking cpio
|
||||
@comment node-name, next, previous, up
|
||||
@section Options
|
||||
|
||||
@ -322,22 +298,26 @@ cpio @{-p|--pass-through@} [-0adlmuvLV] [-R [user][:.][group]]
|
||||
@table @code
|
||||
|
||||
|
||||
@item -0, --null
|
||||
@item -0
|
||||
@itemx --null
|
||||
Read a list of filenames terminated by a null character, instead of a
|
||||
newline, so that files whose names contain newlines can be archived.
|
||||
GNU find is one way to produce a list of null-terminated filenames.
|
||||
This option may be used in copy-out and copy-pass modes.
|
||||
|
||||
@item -a, --reset-access-time
|
||||
@item -a
|
||||
@itemx --reset-access-time
|
||||
Reset the access times of files after reading them, so
|
||||
that it does not look like they have just been read.
|
||||
|
||||
@item -A, --append
|
||||
@item -A
|
||||
@itemx --append
|
||||
Append to an existing archive. Only works in copy-out
|
||||
mode. The archive must be a disk file specified with
|
||||
the -O or -F (--file) option.
|
||||
the @option{-O} or @option{-F} (@option{--file}) option.
|
||||
|
||||
@item -b, --swap
|
||||
@item -b
|
||||
@itemx --swap
|
||||
Swap both halfwords of words and bytes of halfwords in the data.
|
||||
Equivalent to -sS. This option may be used in copy-in mode. Use this
|
||||
option to convert 32-bit integers between big-endian and little-endian
|
||||
@ -347,42 +327,49 @@ machines.
|
||||
Set the I/O block size to 5120 bytes. Initially the
|
||||
block size is 512 bytes.
|
||||
|
||||
@item --block-size=BLOCK-SIZE
|
||||
Set the I/O block size to BLOCK-SIZE * 512 bytes.
|
||||
@item --block-size=@var{block-size}
|
||||
Set the I/O block size to @var{block-size} * 512 bytes.
|
||||
|
||||
@item -c
|
||||
Use the old portable (ASCII) archive format.
|
||||
|
||||
@item -C IO-SIZE, --io-size=IO-SIZE
|
||||
Set the I/O block size to IO-SIZE bytes.
|
||||
@item -C @var{io-size}
|
||||
@itemx --io-size=@var{io-size}
|
||||
Set the I/O block size to @var{io-size} bytes.
|
||||
|
||||
@item -d, --make-directories
|
||||
@item -d
|
||||
@itemx --make-directories
|
||||
Create leading directories where needed.
|
||||
|
||||
@item -E FILE, --pattern-file=FILE
|
||||
@item -E @var{file}
|
||||
@itemx --pattern-file=@var{file}
|
||||
Read additional patterns specifying filenames to extract or list from
|
||||
FILE. The lines of FILE are treated as if they had been non-option
|
||||
@var{file}. The lines of @var{file} are treated as if they had been non-option
|
||||
arguments to cpio. This option is used in copy-in mode,
|
||||
|
||||
@item -f, --nonmatching
|
||||
@item -f
|
||||
@itemx --nonmatching
|
||||
Only copy files that do not match any of the given
|
||||
patterns.
|
||||
|
||||
@item -F, --file=archive
|
||||
@item -F @var{archive}
|
||||
@itemx --file=@var{archive}
|
||||
Archive filename to use instead of standard input or output. To use a
|
||||
tape drive on another machine as the archive, use a filename that starts
|
||||
with `HOSTNAME:'. The hostname can be preceded by a username and an
|
||||
`@@' to access the remote tape drive as that user, if you have
|
||||
permission to do so (typically an entry in that user's `~/.rhosts'
|
||||
with @samp{@var{hostname}:}, where @var{hostname} is the name or IP
|
||||
address of the machine. The hostname can be preceded by a username and an
|
||||
@samp{@@} to access the remote tape drive as that user, if you have
|
||||
permission to do so (typically an entry in that user's @file{~/.rhosts}
|
||||
file).
|
||||
|
||||
@item --force-local
|
||||
With -F, -I, or -O, take the archive file name to be a
|
||||
With @option{-F}, @option{-I}, or @option{-O}, take the archive file name to be a
|
||||
local file even if it contains a colon, which would
|
||||
ordinarily indicate a remote host name.
|
||||
|
||||
@item -H FORMAT, --format=FORMAT
|
||||
Use archive format FORMAT. The valid formats are listed below; the same
|
||||
@item -H @var{format}
|
||||
@itemx --format=@var{format}
|
||||
Use archive format @var{format}. The valid formats are listed below; the same
|
||||
names are also recognized in all-caps. The default in copy-in mode is
|
||||
to automatically detect the archive format, and in copy-out mode is
|
||||
@samp{bin}.
|
||||
@ -417,39 +404,46 @@ The portable format used by HPUX's cpio (which stores device files
|
||||
differently).
|
||||
@end table
|
||||
|
||||
@item -i, --extract
|
||||
@item -i
|
||||
@itemx --extract
|
||||
Run in copy-in mode.
|
||||
@xref{Copy-in mode}.
|
||||
|
||||
@item -I archive
|
||||
@item -I @var{archive}
|
||||
Archive filename to use instead of standard input. To use a tape drive
|
||||
on another machine as the archive, use a filename that starts with
|
||||
`HOSTNAME:'. The hostname can be preceded by a username and an `@@' to
|
||||
@samp{@var{hostname}:}, where @var{hostname} is the name or IP address
|
||||
of the remote host. The hostname can be preceded by a username and an @samp{@@} to
|
||||
access the remote tape drive as that user, if you have permission to do
|
||||
so (typically an entry in that user's `~/.rhosts' file).
|
||||
so (typically an entry in that user's @file{~/.rhosts} file).
|
||||
|
||||
@item -k
|
||||
Ignored; for compatibility with other versions of cpio.
|
||||
|
||||
@item -l, --link
|
||||
@item -l
|
||||
@itemx --link
|
||||
Link files instead of copying them, when possible.
|
||||
|
||||
@item -L, --dereference
|
||||
@item -L
|
||||
@itemx --dereference
|
||||
Copy the file that a symbolic link points to, rather than the symbolic
|
||||
link itself.
|
||||
|
||||
@item -m, --preserve-modification-time
|
||||
@item -m
|
||||
@itemx --preserve-modification-time
|
||||
Retain previous file modification times when creating files.
|
||||
|
||||
@item -M MESSAGE, --message=MESSAGE
|
||||
Print MESSAGE when the end of a volume of the backup media (such as a
|
||||
@item -M @var{message}
|
||||
@itemx --message=@var{message}
|
||||
Print @var{message} when the end of a volume of the backup media (such as a
|
||||
tape or a floppy disk) is reached, to prompt the user to insert a new
|
||||
volume. If MESSAGE contains the string "%d", it is replaced by the
|
||||
volume. If @var{message} contains the string @samp{%d}, it is replaced by the
|
||||
current volume number (starting at 1).
|
||||
|
||||
@item -n, --numeric-uid-gid
|
||||
@item -n
|
||||
@itemx --numeric-uid-gid
|
||||
Show numeric UID and GID instead of translating them into names when using the
|
||||
@samp{--verbose option}.
|
||||
@option{--verbose} option.
|
||||
|
||||
@item --no-absolute-filenames
|
||||
Create all files relative to the current directory in copy-in mode, even
|
||||
@ -461,47 +455,72 @@ extracting them. This is the default for non-root users, so that users
|
||||
on System V don't inadvertantly give away files. This option can be
|
||||
used in copy-in mode and copy-pass mode
|
||||
|
||||
@item -o, --create
|
||||
@item -o
|
||||
@itemx --create
|
||||
Run in copy-out mode.
|
||||
@xref{Copy-out mode}.
|
||||
|
||||
@item -O archive
|
||||
@item -O @var{archive}
|
||||
Archive filename to use instead of standard output. To use a tape drive
|
||||
on another machine as the archive, use a filename that starts with
|
||||
`HOSTNAME:'. The hostname can be preceded by a username and an `@@' to
|
||||
@samp{@var{hostname}:}, where @var{hostname} is the name or IP address
|
||||
of the machine. The hostname can be preceded by a username and an @samp{@@} to
|
||||
access the remote tape drive as that user, if you have permission to do
|
||||
so (typically an entry in that user's `~/.rhosts' file).
|
||||
so (typically an entry in that user's @file{~/.rhosts} file).
|
||||
|
||||
@item --only-verify-crc
|
||||
Verify the CRC's of each file in the archive, when reading a CRC format
|
||||
archive. Don't actually extract the files.
|
||||
|
||||
@item -p, --pass-through
|
||||
@item -p
|
||||
@itemx --pass-through
|
||||
Run in copy-pass mode.
|
||||
@xref{Copy-pass mode}.
|
||||
|
||||
@item --quiet
|
||||
Do not print the number of blocks copied.
|
||||
|
||||
@item -r, --rename
|
||||
@item -r
|
||||
@itemx --rename
|
||||
Interactively rename files.
|
||||
|
||||
@item -R [user][:.][group], --owner [user][:.][group]
|
||||
Set the ownership of all files created to the specified user and/or
|
||||
group in copy-out and copy-pass modes. Either the user, the group, or
|
||||
both, must be present. If the group is omitted but the ":" or "."
|
||||
separator is given, use the given user's login group. Only the
|
||||
super-user can change files' ownership.
|
||||
@item -R @var{owner}
|
||||
@itemx --owner @var{owner}
|
||||
|
||||
@item --rsh-command=COMMAND
|
||||
Notifies cpio that is should use COMMAND to communicate with remote
|
||||
In copy-in and copy-pass mode, set the ownership of all files created
|
||||
to the specified @var{owner} (this operation is allowed only for the
|
||||
super-user). In copy-out mode, store the supplied owner information in
|
||||
the archive.
|
||||
|
||||
The argument can be either the user name or the user name
|
||||
and group name, separated by a dot or a colon, or the group name,
|
||||
preceeded by a dot or a colon, as shown in the examples below:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
cpio --owner smith
|
||||
cpio --owner smith:
|
||||
cpio --owner smith:users
|
||||
cpio --owner :users
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
If the group is omitted but the @samp{:} or @samp{.} separator is
|
||||
given, as in the second example. the given user's login group will be
|
||||
used.
|
||||
|
||||
@item --rsh-command=@var{command}
|
||||
Notifies cpio that is should use @var{command} to communicate with remote
|
||||
devices.
|
||||
|
||||
@item -s, --swap-bytes
|
||||
Swap the bytes of each halfword (pair of bytes) in the files.This option
|
||||
@item -s
|
||||
@itemx --swap-bytes
|
||||
Swap the bytes of each halfword (pair of bytes) in the files. This option
|
||||
can be used in copy-in mode.
|
||||
|
||||
@item -S, --swap-halfwords
|
||||
@item -S
|
||||
@itemx --swap-halfwords
|
||||
Swap the halfwords of each word (4 bytes) in the files. This option may
|
||||
be used in copy-in mode.
|
||||
|
||||
@ -509,29 +528,33 @@ be used in copy-in mode.
|
||||
Write files with large blocks of zeros as sparse files. This option is
|
||||
used in copy-in and copy-pass modes.
|
||||
|
||||
@item -t, --list
|
||||
@item -t
|
||||
@itemx --list
|
||||
Print a table of contents of the input.
|
||||
|
||||
@item -u, --unconditional
|
||||
@item -u
|
||||
@itemx --unconditional
|
||||
Replace all files, without asking whether to replace
|
||||
existing newer files with older files.
|
||||
|
||||
@item -v, --verbose
|
||||
List the files processed, or with @samp{-t}, give an @samp{ls -l} style
|
||||
@item -v
|
||||
@itemx --verbose
|
||||
List the files processed, or with @option{-t}, give an @samp{ls -l} style
|
||||
table of contents listing. In a verbose table of contents of a ustar
|
||||
archive, user and group names in the archive that do not exist on the
|
||||
local system are replaced by the names that correspond locally to the
|
||||
numeric UID and GID stored in the archive.
|
||||
|
||||
@item -V --dot
|
||||
Print a @kbd{.} for each file processed.
|
||||
@item -V
|
||||
@itemx --dot
|
||||
Print a @samp{.} for each file processed.
|
||||
|
||||
@item --version
|
||||
Print the cpio program version number and exit.
|
||||
@end table
|
||||
|
||||
|
||||
@node Media, Concept Index, Invoking `cpio', Top
|
||||
@node Media, Reports, Invoking cpio, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Magnetic Media
|
||||
@cindex magnetic media
|
||||
@ -554,8 +577,24 @@ be protected from such fields to avoid damage to stored data. Sticking
|
||||
a floppy disk to a filing cabinet using a magnet is probably not a good
|
||||
idea.
|
||||
|
||||
@node Reports, Concept Index, Media, Top
|
||||
@chapter Reporting bugs or suggestions
|
||||
|
||||
@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
|
||||
@unnumbered Concept Index
|
||||
@printindex cp
|
||||
|
4
doc/version.texi
Normal file
4
doc/version.texi
Normal file
@ -0,0 +1,4 @@
|
||||
@set UPDATED 7 June 2007
|
||||
@set UPDATED-MONTH June 2007
|
||||
@set EDITION 2.8
|
||||
@set VERSION 2.8
|
@ -1,6 +1,6 @@
|
||||
/* Memory allocation on the stack.
|
||||
|
||||
Copyright (C) 1995, 1999, 2001, 2002, 2003, 2004 Free Software
|
||||
Copyright (C) 1995, 1999, 2001-2004, 2006-2007 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
@ -15,15 +15,13 @@
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
USA. */
|
||||
|
||||
/* When this file is included, it may be preceded only by preprocessor
|
||||
declarations. Thanks to AIX. Therefore we include it right after
|
||||
"config.h", not later. */
|
||||
|
||||
#ifndef _ALLOCA_H
|
||||
# define _ALLOCA_H
|
||||
/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
|
||||
means there is a real alloca function. */
|
||||
#ifndef _GL_ALLOCA_H
|
||||
#define _GL_ALLOCA_H
|
||||
|
||||
/* alloca (N) returns a pointer to N bytes of memory
|
||||
allocated on the stack, which will last until the function returns.
|
||||
@ -36,19 +34,21 @@
|
||||
request, the program just crashes.
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
#elif defined _AIX
|
||||
# define alloca __alloca
|
||||
#elif defined _MSC_VER
|
||||
# include <malloc.h>
|
||||
# define alloca _alloca
|
||||
#else
|
||||
# include <stddef.h>
|
||||
# ifdef __cplusplus
|
||||
#ifndef alloca
|
||||
# ifdef __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
# elif defined _AIX
|
||||
# define alloca __alloca
|
||||
# elif defined _MSC_VER
|
||||
# include <malloc.h>
|
||||
# define alloca _alloca
|
||||
# else
|
||||
# include <stddef.h>
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
# endif
|
||||
void *alloca (size_t);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _ALLOCA_H */
|
||||
#endif /* _GL_ALLOCA_H */
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* If set by the user program, it should point to string that is the
|
||||
bug-reporting address for the program. It will be printed by argp_help if
|
||||
|
@ -15,10 +15,10 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sysexits.h>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Word-wrapping and line-truncating streams
|
||||
Copyright (C) 1997,1998,1999,2001,2002,2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997-1999,2001,2002,2003,2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
@ -15,13 +15,13 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* This package emulates glibc `line_wrap_stream' semantics for systems that
|
||||
don't have that. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -101,11 +101,10 @@ __argp_fmtstream_free (argp_fmtstream_t fs)
|
||||
if (fs->p > fs->buf)
|
||||
{
|
||||
#ifdef USE_IN_LIBIO
|
||||
if (_IO_fwide (fs->stream, 0) > 0)
|
||||
__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf);
|
||||
else
|
||||
__fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
|
||||
#else
|
||||
fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
|
||||
#endif
|
||||
fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
|
||||
}
|
||||
free (fs->buf);
|
||||
free (fs);
|
||||
@ -247,9 +246,10 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
|
||||
Oh well. Put it on an overlong line by itself. */
|
||||
p = buf + (r + 1 - fs->point_col);
|
||||
/* Find the end of the long word. */
|
||||
do
|
||||
++p;
|
||||
while (p < nl && !isblank (*p));
|
||||
if (p < nl)
|
||||
do
|
||||
++p;
|
||||
while (p < nl && !isblank (*p));
|
||||
if (p == nl)
|
||||
{
|
||||
/* It already ends a line. No fussing required. */
|
||||
@ -290,17 +290,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
|
||||
else
|
||||
/* Output the first line so we can use the space. */
|
||||
{
|
||||
#ifdef USE_IN_LIBIO
|
||||
if (_IO_fwide (fs->stream, 0) > 0)
|
||||
__fwprintf (fs->stream, L"%.*s\n",
|
||||
(int) (nl - fs->buf), fs->buf);
|
||||
else
|
||||
#ifdef _LIBC
|
||||
__fxprintf (fs->stream, "%.*s\n",
|
||||
(int) (nl - fs->buf), fs->buf);
|
||||
#else
|
||||
if (nl > fs->buf)
|
||||
fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
|
||||
putc_unlocked ('\n', fs->stream);
|
||||
#endif
|
||||
{
|
||||
if (nl > fs->buf)
|
||||
fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
|
||||
putc_unlocked ('\n', fs->stream);
|
||||
}
|
||||
|
||||
len += buf - fs->buf;
|
||||
nl = buf = fs->buf;
|
||||
}
|
||||
@ -359,15 +357,12 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
|
||||
/* Flush FS's buffer. */
|
||||
__argp_fmtstream_update (fs);
|
||||
|
||||
#ifdef USE_IN_LIBIO
|
||||
if (_IO_fwide (fs->stream, 0) > 0)
|
||||
{
|
||||
__fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf);
|
||||
wrote = fs->p - fs->buf;
|
||||
}
|
||||
else
|
||||
#ifdef _LIBC
|
||||
__fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
|
||||
wrote = fs->p - fs->buf;
|
||||
#else
|
||||
wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
|
||||
#endif
|
||||
wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
|
||||
if (wrote == fs->p - fs->buf)
|
||||
{
|
||||
fs->p = fs->buf;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Word-wrapping and line-truncating streams.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* This package emulates glibc `line_wrap_stream' semantics for systems that
|
||||
don't have that. If the system does have it, it is just a wrapper for
|
||||
@ -25,10 +25,6 @@
|
||||
#ifndef _ARGP_FMTSTREAM_H
|
||||
#define _ARGP_FMTSTREAM_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@ -93,10 +89,6 @@ typedef FILE *argp_fmtstream_t;
|
||||
|
||||
#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
|
||||
/* Guess we have to define our own version. */
|
||||
|
||||
#ifndef __const
|
||||
#define __const const
|
||||
#endif
|
||||
|
||||
struct argp_fmtstream
|
||||
{
|
||||
@ -137,22 +129,22 @@ extern void __argp_fmtstream_free (argp_fmtstream_t __fs);
|
||||
extern void argp_fmtstream_free (argp_fmtstream_t __fs);
|
||||
|
||||
extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs,
|
||||
__const char *__fmt, ...)
|
||||
const char *__fmt, ...)
|
||||
__attribute__ ((__format__ (printf, 2, 3)));
|
||||
extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
|
||||
__const char *__fmt, ...)
|
||||
const char *__fmt, ...)
|
||||
__attribute__ ((__format__ (printf, 2, 3)));
|
||||
|
||||
extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
|
||||
extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
|
||||
|
||||
extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
|
||||
extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
|
||||
extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str);
|
||||
extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str);
|
||||
|
||||
extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs,
|
||||
__const char *__str, size_t __len);
|
||||
const char *__str, size_t __len);
|
||||
extern size_t argp_fmtstream_write (argp_fmtstream_t __fs,
|
||||
__const char *__str, size_t __len);
|
||||
const char *__str, size_t __len);
|
||||
|
||||
/* Access macros for various bits of state. */
|
||||
#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin)
|
||||
@ -211,7 +203,7 @@ extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
|
||||
|
||||
ARGP_FS_EI size_t
|
||||
__argp_fmtstream_write (argp_fmtstream_t __fs,
|
||||
__const char *__str, size_t __len)
|
||||
const char *__str, size_t __len)
|
||||
{
|
||||
if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
|
||||
{
|
||||
@ -224,7 +216,7 @@ __argp_fmtstream_write (argp_fmtstream_t __fs,
|
||||
}
|
||||
|
||||
ARGP_FS_EI int
|
||||
__argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str)
|
||||
__argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str)
|
||||
{
|
||||
size_t __len = strlen (__str);
|
||||
if (__len)
|
||||
|
@ -15,10 +15,10 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#define ARGP_FS_EI
|
||||
|
312
lib/argp-help.c
312
lib/argp-help.c
@ -1,5 +1,5 @@
|
||||
/* Hierarchial argument parsing help output
|
||||
Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2005, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
@ -15,14 +15,14 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
@ -89,15 +89,15 @@ struct uparams
|
||||
int dup_args_note;
|
||||
|
||||
/* Various output columns. */
|
||||
int short_opt_col;
|
||||
int long_opt_col;
|
||||
int doc_opt_col;
|
||||
int opt_doc_col;
|
||||
int header_col;
|
||||
int usage_indent;
|
||||
int rmargin;
|
||||
int short_opt_col; /* column in which short options start */
|
||||
int long_opt_col; /* column in which long options start */
|
||||
int doc_opt_col; /* column in which doc options start */
|
||||
int opt_doc_col; /* column in which option text starts */
|
||||
int header_col; /* column in which group headers are printed */
|
||||
int usage_indent; /* indentation of wrapped usage lines */
|
||||
int rmargin; /* right margin used for wrapping */
|
||||
|
||||
int valid; /* True when the values in here are valid. */
|
||||
int valid; /* True when the values in here are valid. */
|
||||
};
|
||||
|
||||
/* This is a global variable, as user options are only ever read once. */
|
||||
@ -131,91 +131,126 @@ static const struct uparam_name uparam_names[] =
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Read user options from the environment, and fill in UPARAMS appropiately. */
|
||||
static void
|
||||
validate_uparams (const struct argp_state *state, struct uparams *upptr)
|
||||
{
|
||||
const struct uparam_name *up;
|
||||
|
||||
for (up = uparam_names; up->name; up++)
|
||||
{
|
||||
if (up->is_bool
|
||||
|| up->uparams_offs == offsetof (struct uparams, rmargin))
|
||||
continue;
|
||||
if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin)
|
||||
{
|
||||
__argp_failure (state, 0, 0,
|
||||
dgettext (state->root_argp->argp_domain,
|
||||
"\
|
||||
ARGP_HELP_FMT: %s value is less than or equal to %s"),
|
||||
"rmargin", up->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
uparams = *upptr;
|
||||
uparams.valid = 1;
|
||||
}
|
||||
|
||||
/* Read user options from the environment, and fill in UPARAMS appropiately. */
|
||||
static void
|
||||
fill_in_uparams (const struct argp_state *state)
|
||||
{
|
||||
const char *var = getenv ("ARGP_HELP_FMT");
|
||||
|
||||
#define SKIPWS(p) do { while (isspace (*p)) p++; } while (0);
|
||||
struct uparams new_params = uparams;
|
||||
|
||||
#define SKIPWS(p) do { while (isspace ((unsigned char) *p)) p++; } while (0);
|
||||
|
||||
if (var)
|
||||
/* Parse var. */
|
||||
while (*var)
|
||||
{
|
||||
SKIPWS (var);
|
||||
{
|
||||
/* Parse var. */
|
||||
while (*var)
|
||||
{
|
||||
SKIPWS (var);
|
||||
|
||||
if (isalpha ((unsigned char) *var))
|
||||
{
|
||||
size_t var_len;
|
||||
const struct uparam_name *un;
|
||||
int unspec = 0, val = 0;
|
||||
const char *arg = var;
|
||||
|
||||
if (isalpha (*var))
|
||||
{
|
||||
size_t var_len;
|
||||
const struct uparam_name *un;
|
||||
int unspec = 0, val = 0;
|
||||
const char *arg = var;
|
||||
|
||||
while (isalnum (*arg) || *arg == '-' || *arg == '_')
|
||||
arg++;
|
||||
var_len = arg - var;
|
||||
|
||||
SKIPWS (arg);
|
||||
|
||||
if (*arg == '\0' || *arg == ',')
|
||||
unspec = 1;
|
||||
else if (*arg == '=')
|
||||
{
|
||||
while (isalnum ((unsigned char) *arg) || *arg == '-' || *arg == '_')
|
||||
arg++;
|
||||
SKIPWS (arg);
|
||||
}
|
||||
|
||||
if (unspec)
|
||||
{
|
||||
if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
|
||||
{
|
||||
val = 0;
|
||||
var += 3;
|
||||
var_len -= 3;
|
||||
}
|
||||
else
|
||||
val = 1;
|
||||
}
|
||||
else if (isdigit (*arg))
|
||||
{
|
||||
val = atoi (arg);
|
||||
while (isdigit (*arg))
|
||||
arg++;
|
||||
SKIPWS (arg);
|
||||
}
|
||||
|
||||
for (un = uparam_names; un->name; un++)
|
||||
if (strlen (un->name) == var_len
|
||||
&& strncmp (var, un->name, var_len) == 0)
|
||||
var_len = arg - var;
|
||||
|
||||
SKIPWS (arg);
|
||||
|
||||
if (*arg == '\0' || *arg == ',')
|
||||
unspec = 1;
|
||||
else if (*arg == '=')
|
||||
{
|
||||
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
|
||||
*(int *)((char *)&uparams + un->uparams_offs) = val;
|
||||
break;
|
||||
arg++;
|
||||
SKIPWS (arg);
|
||||
}
|
||||
if (! un->name)
|
||||
__argp_failure (state, 0, 0,
|
||||
dgettext (state->root_argp->argp_domain, "\
|
||||
|
||||
if (unspec)
|
||||
{
|
||||
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"),
|
||||
(int) var_len, var);
|
||||
(int) var_len, var);
|
||||
|
||||
var = arg;
|
||||
if (*var == ',')
|
||||
var++;
|
||||
}
|
||||
else if (*var)
|
||||
{
|
||||
__argp_failure (state, 0, 0,
|
||||
dgettext (state->root_argp->argp_domain,
|
||||
"Garbage in ARGP_HELP_FMT: %s"), var);
|
||||
break;
|
||||
}
|
||||
}
|
||||
var = arg;
|
||||
if (*var == ',')
|
||||
var++;
|
||||
}
|
||||
else if (*var)
|
||||
{
|
||||
__argp_failure (state, 0, 0,
|
||||
dgettext (state->root_argp->argp_domain,
|
||||
"Garbage in ARGP_HELP_FMT: %s"), var);
|
||||
break;
|
||||
}
|
||||
}
|
||||
validate_uparams (state, &new_params);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if OPT hasn't been marked invisible. Visibility only affects
|
||||
@ -340,6 +375,9 @@ struct hol_entry
|
||||
|
||||
/* The argp from which this option came. */
|
||||
const struct argp *argp;
|
||||
|
||||
/* Position in the array */
|
||||
unsigned ord;
|
||||
};
|
||||
|
||||
/* A cluster of entries to reflect the argp tree structure. */
|
||||
@ -638,10 +676,12 @@ static int
|
||||
hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
|
||||
{
|
||||
/* If one cluster is deeper than the other, use its ancestor at the same
|
||||
level, so that finding the common ancestor is straightforward. */
|
||||
while (cl1->depth < cl2->depth)
|
||||
level, so that finding the common ancestor is straightforward.
|
||||
|
||||
clN->depth > 0 means that clN->parent != NULL (see hol_add_cluster) */
|
||||
while (cl1->depth > cl2->depth)
|
||||
cl1 = cl1->parent;
|
||||
while (cl2->depth < cl1->depth)
|
||||
while (cl2->depth > cl1->depth)
|
||||
cl2 = cl2->parent;
|
||||
|
||||
/* Now reduce both clusters to their ancestors at the point where both have
|
||||
@ -685,17 +725,19 @@ canon_doc_option (const char **name)
|
||||
else
|
||||
{
|
||||
/* Skip initial whitespace. */
|
||||
while (isspace (**name))
|
||||
while (isspace ((unsigned char) **name))
|
||||
(*name)++;
|
||||
/* Decide whether this looks like an option (leading `-') or not. */
|
||||
non_opt = (**name != '-');
|
||||
/* Skip until part of name used for sorting. */
|
||||
while (**name && !isalnum (**name))
|
||||
while (**name && !isalnum ((unsigned char) **name))
|
||||
(*name)++;
|
||||
}
|
||||
return non_opt;
|
||||
}
|
||||
|
||||
#define HOL_ENTRY_PTRCMP(a,b) ((a)->ord < (b)->ord ? -1 : 1)
|
||||
|
||||
/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help
|
||||
listing. */
|
||||
static int
|
||||
@ -705,6 +747,7 @@ hol_entry_cmp (const struct hol_entry *entry1,
|
||||
/* The group numbers by which the entries should be ordered; if either is
|
||||
in a cluster, then this is just the group within the cluster. */
|
||||
int group1 = entry1->group, group2 = entry2->group;
|
||||
int rc;
|
||||
|
||||
if (entry1->cluster != entry2->cluster)
|
||||
{
|
||||
@ -721,7 +764,8 @@ hol_entry_cmp (const struct hol_entry *entry1,
|
||||
return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
|
||||
else
|
||||
/* Both entries are in clusters, we can just compare the clusters. */
|
||||
return hol_cluster_cmp (entry1->cluster, entry2->cluster);
|
||||
return (rc = hol_cluster_cmp (entry1->cluster, entry2->cluster)) ?
|
||||
rc : HOL_ENTRY_PTRCMP(entry1, entry2);
|
||||
}
|
||||
else if (group1 == group2)
|
||||
/* The entries are both in the same cluster and group, so compare them
|
||||
@ -745,7 +789,8 @@ hol_entry_cmp (const struct hol_entry *entry1,
|
||||
return doc1 - doc2;
|
||||
else if (!short1 && !short2 && long1 && long2)
|
||||
/* Only long options. */
|
||||
return __strcasecmp (long1, long2);
|
||||
return (rc = __strcasecmp (long1, long2)) ?
|
||||
rc : HOL_ENTRY_PTRCMP(entry1, entry2);
|
||||
else
|
||||
/* Compare short/short, long/short, short/long, using the first
|
||||
character of long options. Entries without *any* valid
|
||||
@ -762,13 +807,15 @@ hol_entry_cmp (const struct hol_entry *entry1,
|
||||
#endif
|
||||
/* Compare ignoring case, except when the options are both the
|
||||
same letter, in which case lower-case always comes first. */
|
||||
return lower_cmp ? lower_cmp : first2 - first1;
|
||||
return lower_cmp ? lower_cmp :
|
||||
(rc = first2 - first1) ?
|
||||
rc : HOL_ENTRY_PTRCMP(entry1, entry2);
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Within the same cluster, but not the same group, so just compare
|
||||
groups. */
|
||||
return group_cmp (group1, group2, 0);
|
||||
return group_cmp (group1, group2, HOL_ENTRY_PTRCMP(entry1, entry2));
|
||||
}
|
||||
|
||||
/* Version of hol_entry_cmp with correct signature for qsort. */
|
||||
@ -785,8 +832,14 @@ static void
|
||||
hol_sort (struct hol *hol)
|
||||
{
|
||||
if (hol->num_entries > 0)
|
||||
qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
|
||||
hol_entry_qcmp);
|
||||
{
|
||||
unsigned i;
|
||||
struct hol_entry *e;
|
||||
for (i = 0, e = hol->entries; i < hol->num_entries; i++, e++)
|
||||
e->ord = i;
|
||||
qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
|
||||
hol_entry_qcmp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow
|
||||
@ -1055,7 +1108,13 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
|
||||
int old_wm = __argp_fmtstream_wmargin (stream);
|
||||
/* PEST is a state block holding some of our variables that we'd like to
|
||||
share with helper functions. */
|
||||
struct pentry_state pest = { entry, stream, hhstate, 1, state };
|
||||
struct pentry_state pest;
|
||||
|
||||
pest.entry = entry;
|
||||
pest.stream = stream;
|
||||
pest.hhstate = hhstate;
|
||||
pest.first = 1;
|
||||
pest.state = state;
|
||||
|
||||
if (! odoc (real))
|
||||
for (opt = real, num = entry->num; num > 0; opt++, num--)
|
||||
@ -1263,7 +1322,7 @@ usage_long_opt (const struct argp_option *opt,
|
||||
if (! arg)
|
||||
arg = real->arg;
|
||||
|
||||
if (! (flags & OPTION_NO_USAGE))
|
||||
if (! (flags & OPTION_NO_USAGE) && !odoc (opt))
|
||||
{
|
||||
if (arg)
|
||||
{
|
||||
@ -1434,46 +1493,51 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
|
||||
{
|
||||
const char *text;
|
||||
const char *inp_text;
|
||||
size_t inp_text_len = 0;
|
||||
const char *trans_text;
|
||||
void *input = 0;
|
||||
int anything = 0;
|
||||
size_t inp_text_limit = 0;
|
||||
const char *doc = dgettext (argp->argp_domain, argp->doc);
|
||||
const struct argp_child *child = argp->children;
|
||||
|
||||
if (doc)
|
||||
if (argp->doc)
|
||||
{
|
||||
char *vt = strchr (doc, '\v');
|
||||
inp_text = post ? (vt ? vt + 1 : 0) : doc;
|
||||
inp_text_limit = (!post && vt) ? (vt - doc) : 0;
|
||||
char *vt = strchr (argp->doc, '\v');
|
||||
if (vt)
|
||||
{
|
||||
if (post)
|
||||
inp_text = vt + 1;
|
||||
else
|
||||
{
|
||||
inp_text_len = vt - argp->doc;
|
||||
inp_text = __strndup (argp->doc, inp_text_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
inp_text = post ? 0 : argp->doc;
|
||||
trans_text = inp_text ? dgettext (argp->argp_domain, inp_text) : NULL;
|
||||
}
|
||||
else
|
||||
inp_text = 0;
|
||||
trans_text = inp_text = 0;
|
||||
|
||||
if (argp->help_filter)
|
||||
/* We have to filter the doc strings. */
|
||||
{
|
||||
if (inp_text_limit)
|
||||
/* Copy INP_TEXT so that it's nul-terminated. */
|
||||
inp_text = __strndup (inp_text, inp_text_limit);
|
||||
input = __argp_input (argp, state);
|
||||
text =
|
||||
(*argp->help_filter) (post
|
||||
? ARGP_KEY_HELP_POST_DOC
|
||||
: ARGP_KEY_HELP_PRE_DOC,
|
||||
inp_text, input);
|
||||
trans_text, input);
|
||||
}
|
||||
else
|
||||
text = (const char *) inp_text;
|
||||
text = (const char *) trans_text;
|
||||
|
||||
if (text)
|
||||
{
|
||||
if (pre_blank)
|
||||
__argp_fmtstream_putc (stream, '\n');
|
||||
|
||||
if (text == inp_text && inp_text_limit)
|
||||
__argp_fmtstream_write (stream, inp_text, inp_text_limit);
|
||||
else
|
||||
__argp_fmtstream_puts (stream, text);
|
||||
__argp_fmtstream_puts (stream, text);
|
||||
|
||||
if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
|
||||
__argp_fmtstream_putc (stream, '\n');
|
||||
@ -1481,9 +1545,10 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
|
||||
anything = 1;
|
||||
}
|
||||
|
||||
if (text && text != inp_text)
|
||||
if (text && text != trans_text)
|
||||
free ((char *) text); /* Free TEXT returned from the help filter. */
|
||||
if (inp_text && inp_text_limit && argp->help_filter)
|
||||
|
||||
if (inp_text && inp_text_len)
|
||||
free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */
|
||||
|
||||
if (post && argp->help_filter)
|
||||
@ -1663,7 +1728,10 @@ Try `%s --help' or `%s --usage' for more information.\n"),
|
||||
void __argp_help (const struct argp *argp, FILE *stream,
|
||||
unsigned flags, char *name)
|
||||
{
|
||||
_help (argp, 0, stream, flags, name);
|
||||
struct argp_state state;
|
||||
memset (&state, 0, sizeof state);
|
||||
state.root_argp = argp;
|
||||
_help (argp, &state, stream, flags, name);
|
||||
}
|
||||
#ifdef weak_alias
|
||||
weak_alias (__argp_help, argp_help)
|
||||
@ -1674,8 +1742,7 @@ char *
|
||||
__argp_short_program_name (void)
|
||||
{
|
||||
# if HAVE_DECL_PROGRAM_INVOCATION_NAME
|
||||
char *name = strrchr (program_invocation_name, '/');
|
||||
return name ? name + 1 : program_invocation_name;
|
||||
return __argp_base_name (program_invocation_name);
|
||||
# else
|
||||
/* FIXME: What now? Miles suggests that it is better to use NULL,
|
||||
but currently the value is passed on directly to fputs_unlocked,
|
||||
@ -1739,7 +1806,8 @@ __argp_error (const struct argp_state *state, const char *fmt, ...)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
__asprintf (&buf, fmt, ap);
|
||||
if (__asprintf (&buf, fmt, ap) < 0)
|
||||
buf = NULL;
|
||||
|
||||
__fwprintf (stream, L"%s: %s\n",
|
||||
state ? state->name : __argp_short_program_name (),
|
||||
@ -1817,7 +1885,8 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
|
||||
{
|
||||
char *buf;
|
||||
|
||||
__asprintf (&buf, fmt, ap);
|
||||
if (__asprintf (&buf, fmt, ap) < 0)
|
||||
buf = NULL;
|
||||
|
||||
__fwprintf (stream, L": %s", buf);
|
||||
|
||||
@ -1857,7 +1926,8 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
|
||||
#endif
|
||||
#if !_LIBC
|
||||
if (! s && ! (s = strerror (errnum)))
|
||||
s = "Unknown system error"; /* FIXME: translate this */
|
||||
s = dgettext (state->root_argp->argp_domain,
|
||||
"Unknown system error");
|
||||
#endif
|
||||
fputs (s, stream);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Name frobnication for compiling argp outside of glibc
|
||||
Copyright (C) 1997, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 2003, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if !_LIBC
|
||||
/* This code is written for inclusion in gnu-libc, and uses names in the
|
||||
@ -76,11 +76,6 @@
|
||||
#undef __argp_fmtstream_wmargin
|
||||
#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
|
||||
|
||||
#include "mempcpy.h"
|
||||
#include "strcase.h"
|
||||
#include "strchrnul.h"
|
||||
#include "strndup.h"
|
||||
|
||||
/* normal libc functions we call */
|
||||
#undef __flockfile
|
||||
#define __flockfile flockfile
|
||||
@ -141,14 +136,21 @@
|
||||
# define putchar_unlocked(x) putchar (x)
|
||||
# endif
|
||||
|
||||
extern char *__argp_basename (char *name);
|
||||
|
||||
#endif /* !_LIBC */
|
||||
|
||||
#ifndef __set_errno
|
||||
#define __set_errno(e) (errno = (e))
|
||||
#endif
|
||||
|
||||
#if defined GNULIB_ARGP_DISABLE_DIRNAME
|
||||
# define __argp_base_name(arg) arg
|
||||
#elif defined GNULIB_ARGP_EXTERN_BASENAME
|
||||
extern char *__argp_base_name(const char *arg);
|
||||
#else
|
||||
# include "dirname.h"
|
||||
# define __argp_base_name base_name
|
||||
#endif
|
||||
|
||||
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
# define __argp_short_program_name() (program_invocation_short_name)
|
||||
#else
|
||||
|
@ -15,13 +15,14 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@ -37,11 +38,14 @@
|
||||
#else
|
||||
# include "gettext.h"
|
||||
#endif
|
||||
#define N_(msgid) (msgid)
|
||||
#define N_(msgid) msgid
|
||||
|
||||
#include "argp.h"
|
||||
#include "argp-namefrob.h"
|
||||
|
||||
#define alignof(type) offsetof (struct { char c; type x; }, x)
|
||||
#define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d))
|
||||
|
||||
/* Getopt return values. */
|
||||
#define KEY_END (-1) /* The end of the options. */
|
||||
#define KEY_ARG 1 /* A non-option argument. */
|
||||
@ -75,11 +79,11 @@ static volatile int _argp_hang;
|
||||
|
||||
static const struct argp_option argp_default_options[] =
|
||||
{
|
||||
{"help", '?', 0, 0, N_("Give this help list"), -1},
|
||||
{"usage", OPT_USAGE, 0, 0, N_("Give a short usage message"), 0},
|
||||
{"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name"), 0},
|
||||
{"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
|
||||
N_("Hang for SECS seconds (default 3600)"), 0},
|
||||
{"help", '?', 0, 0, N_("give this help list"), -1},
|
||||
{"usage", OPT_USAGE, 0, 0, N_("give a short usage message"), 0},
|
||||
{"program-name",OPT_PROGNAME,N_("NAME"), OPTION_HIDDEN, N_("set the program name"), 0},
|
||||
{"HANG", OPT_HANG, N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
|
||||
N_("hang for SECS seconds (default 3600)"), 0},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
@ -93,7 +97,7 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
|
||||
break;
|
||||
case OPT_USAGE:
|
||||
__argp_state_help (state, state->out_stream,
|
||||
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
|
||||
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
|
||||
break;
|
||||
|
||||
case OPT_PROGNAME: /* Set the program name. */
|
||||
@ -105,11 +109,7 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
|
||||
to be that, so we have to be a bit careful here.] */
|
||||
|
||||
/* Update what we use for messages. */
|
||||
state->name = strrchr (arg, '/');
|
||||
if (state->name)
|
||||
state->name++;
|
||||
else
|
||||
state->name = arg;
|
||||
state->name = __argp_base_name (arg);
|
||||
|
||||
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
program_invocation_short_name = state->name;
|
||||
@ -140,7 +140,7 @@ static const struct argp argp_default_argp =
|
||||
|
||||
static const struct argp_option argp_version_options[] =
|
||||
{
|
||||
{"version", 'V', 0, 0, N_("Print program version"), -1},
|
||||
{"version", 'V', 0, 0, N_("print program version"), -1},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
@ -462,6 +462,11 @@ parser_init (struct parser *parser, const struct argp *argp,
|
||||
struct group *group;
|
||||
struct parser_sizes szs;
|
||||
struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
|
||||
char *storage;
|
||||
size_t glen, gsum;
|
||||
size_t clen, csum;
|
||||
size_t llen, lsum;
|
||||
size_t slen, ssum;
|
||||
|
||||
szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
|
||||
szs.long_len = 0;
|
||||
@ -472,22 +477,33 @@ parser_init (struct parser *parser, const struct argp *argp,
|
||||
calc_sizes (argp, &szs);
|
||||
|
||||
/* Lengths of the various bits of storage used by PARSER. */
|
||||
#define GLEN (szs.num_groups + 1) * sizeof (struct group)
|
||||
#define CLEN (szs.num_child_inputs * sizeof (void *))
|
||||
#define LLEN ((szs.long_len + 1) * sizeof (struct option))
|
||||
#define SLEN (szs.short_len + 1)
|
||||
glen = (szs.num_groups + 1) * sizeof (struct group);
|
||||
clen = szs.num_child_inputs * sizeof (void *);
|
||||
llen = (szs.long_len + 1) * sizeof (struct option);
|
||||
slen = szs.short_len + 1;
|
||||
|
||||
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)
|
||||
return ENOMEM;
|
||||
|
||||
storage = parser->storage;
|
||||
parser->groups = parser->storage;
|
||||
parser->child_inputs = parser->storage + GLEN;
|
||||
parser->long_opts = parser->storage + GLEN + CLEN;
|
||||
parser->short_opts = parser->storage + GLEN + CLEN + LLEN;
|
||||
parser->child_inputs = (void **) (storage + gsum);
|
||||
parser->long_opts = (struct option *) (storage + csum);
|
||||
parser->short_opts = storage + lsum;
|
||||
parser->opt_data = opt_data;
|
||||
|
||||
memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *));
|
||||
memset (parser->child_inputs, 0, clen);
|
||||
parser_convert (parser, argp, flags);
|
||||
|
||||
memset (&parser->state, 0, sizeof (struct argp_state));
|
||||
@ -542,10 +558,7 @@ parser_init (struct parser *parser, const struct argp *argp,
|
||||
|
||||
if (parser->state.argv == argv && argv[0])
|
||||
/* There's an argv[0]; use it for messages. */
|
||||
{
|
||||
char *short_name = strrchr (argv[0], '/');
|
||||
parser->state.name = short_name ? short_name + 1 : argv[0];
|
||||
}
|
||||
parser->state.name = __argp_base_name (argv[0]);
|
||||
else
|
||||
parser->state.name = __argp_short_program_name ();
|
||||
|
||||
@ -864,6 +877,20 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
|
||||
to be parsed (which in some cases isn't actually an error). */
|
||||
int arg_ebadkey = 0;
|
||||
|
||||
#ifndef _LIBC
|
||||
if (!(flags & ARGP_PARSE_ARGV0))
|
||||
{
|
||||
#ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME
|
||||
if (!program_invocation_name)
|
||||
program_invocation_name = argv[0];
|
||||
#endif
|
||||
#ifdef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
if (!program_invocation_short_name)
|
||||
program_invocation_short_name = __argp_base_name (argv[0]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! (flags & ARGP_NO_HELP))
|
||||
/* Add our own options. */
|
||||
{
|
||||
|
28
lib/argp-pin.c
Normal file
28
lib/argp-pin.c
Normal 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Default definition for ARGP_PROGRAM_VERSION.
|
||||
Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996, 1997, 1999, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
@ -15,10 +15,10 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* If set by the user program to a non-zero value, then a default option
|
||||
--version is added (unless the ARGP_NO_HELP flag is used), which will
|
||||
print this this string followed by a newline and exit (unless the
|
||||
print this string followed by a newline and exit (unless the
|
||||
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
|
||||
const char *argp_program_version;
|
||||
|
@ -15,10 +15,10 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "argp.h"
|
||||
|
@ -15,10 +15,10 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined _LIBC || defined HAVE_FEATURES_H
|
||||
|
124
lib/argp.h
124
lib/argp.h
@ -1,5 +1,5 @@
|
||||
/* Hierarchial argument parsing, layered over getopt.
|
||||
Copyright (C) 1995-1999,2003,2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-1999,2003-2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>.
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _ARGP_H
|
||||
#define _ARGP_H
|
||||
@ -23,14 +23,11 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define __need_error_t
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __const
|
||||
# define __const const
|
||||
#endif
|
||||
|
||||
#ifndef __THROW
|
||||
# define __THROW
|
||||
#endif
|
||||
@ -52,10 +49,12 @@
|
||||
#endif
|
||||
|
||||
/* GCC 2.95 and later have "__restrict"; C99 compilers have
|
||||
"restrict", and "configure" may have defined "restrict". */
|
||||
"restrict", and "configure" may have defined "restrict".
|
||||
Other compilers use __restrict, __restrict__, and _Restrict, and
|
||||
'configure' might #define 'restrict' to those words. */
|
||||
#ifndef __restrict
|
||||
# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
|
||||
# if defined restrict || 199901L <= __STDC_VERSION__
|
||||
# if 199901L <= __STDC_VERSION__
|
||||
# define __restrict restrict
|
||||
# else
|
||||
# define __restrict
|
||||
@ -81,7 +80,7 @@ struct argp_option
|
||||
{
|
||||
/* The long option name. For more than one name for the same option, you
|
||||
can use following options with the OPTION_ALIAS flag set. */
|
||||
__const char *name;
|
||||
const char *name;
|
||||
|
||||
/* What key is returned for this option. If > 0 and printable, then it's
|
||||
also accepted as a short option. */
|
||||
@ -89,7 +88,7 @@ struct argp_option
|
||||
|
||||
/* If non-NULL, this is the name of the argument associated with this
|
||||
option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */
|
||||
__const char *arg;
|
||||
const char *arg;
|
||||
|
||||
/* OPTION_ flags. */
|
||||
int flags;
|
||||
@ -97,8 +96,11 @@ struct argp_option
|
||||
/* The doc string for this option. If both NAME and KEY are 0, This string
|
||||
will be printed outdented from the normal option column, making it
|
||||
useful as a group header (it will be the first thing printed in its
|
||||
group); in this usage, it's conventional to end the string with a `:'. */
|
||||
__const char *doc;
|
||||
group); in this usage, it's conventional to end the string with a `:'.
|
||||
|
||||
Write the initial value as N_("TEXT") if you want xgettext to collect
|
||||
it into a POT file. */
|
||||
const char *doc;
|
||||
|
||||
/* The group this option is in. In a long help message, options are sorted
|
||||
alphabetically within each group, and the groups presented in the order
|
||||
@ -226,7 +228,7 @@ struct argp
|
||||
{
|
||||
/* An array of argp_option structures, terminated by an entry with both
|
||||
NAME and KEY having a value of 0. */
|
||||
__const struct argp_option *options;
|
||||
const struct argp_option *options;
|
||||
|
||||
/* What to do with an option from this structure. KEY is the key
|
||||
associated with the option, and ARG is any associated argument (NULL if
|
||||
@ -242,12 +244,14 @@ struct argp
|
||||
contains newlines, the strings separated by them are considered
|
||||
alternative usage patterns, and printed on separate lines (lines after
|
||||
the first are prefix by ` or: ' instead of `Usage:'). */
|
||||
__const char *args_doc;
|
||||
const char *args_doc;
|
||||
|
||||
/* If non-NULL, a string containing extra text to be printed before and
|
||||
after the options in a long help message (separated by a vertical tab
|
||||
`\v' character). */
|
||||
__const char *doc;
|
||||
`\v' character).
|
||||
Write the initial value as N_("BEFORE-TEXT") "\v" N_("AFTER-TEXT") if
|
||||
you want xgettext to collect the two pieces of text into a POT file. */
|
||||
const char *doc;
|
||||
|
||||
/* A vector of argp_children structures, terminated by a member with a 0
|
||||
argp field, pointing to child argps should be parsed with this one. Any
|
||||
@ -255,7 +259,7 @@ struct argp
|
||||
CHILDREN list. This field is useful if you use libraries that supply
|
||||
their own argp structure, which you want to use in conjunction with your
|
||||
own. */
|
||||
__const struct argp_child *children;
|
||||
const struct argp_child *children;
|
||||
|
||||
/* If non-zero, this should be a function to filter the output of help
|
||||
messages. KEY is either a key from an option, in which case TEXT is
|
||||
@ -267,7 +271,7 @@ struct argp
|
||||
has been done, so if any of the replacement text also needs translation,
|
||||
that should be done by the filter function. INPUT is either the input
|
||||
supplied to argp_parse, or NULL, if argp_help was called directly. */
|
||||
char *(*help_filter) (int __key, __const char *__text, void *__input);
|
||||
char *(*help_filter) (int __key, const char *__text, void *__input);
|
||||
|
||||
/* If non-zero the strings used in the argp library are translated using
|
||||
the domain described by this string. Otherwise the currently installed
|
||||
@ -291,7 +295,7 @@ struct argp
|
||||
struct argp_child
|
||||
{
|
||||
/* The child parser. */
|
||||
__const struct argp *argp;
|
||||
const struct argp *argp;
|
||||
|
||||
/* Flags for this child. */
|
||||
int flags;
|
||||
@ -300,7 +304,7 @@ struct argp_child
|
||||
child options. As a side-effect, a non-zero value forces the child
|
||||
options to be grouped together; to achieve this effect without actually
|
||||
printing a header string, use a value of "". */
|
||||
__const char *header;
|
||||
const char *header;
|
||||
|
||||
/* Where to group the child options relative to the other (`consolidated')
|
||||
options in the parent argp; the values are the same as the GROUP field
|
||||
@ -316,7 +320,7 @@ struct argp_child
|
||||
struct argp_state
|
||||
{
|
||||
/* The top level ARGP being parsed. */
|
||||
__const struct argp *root_argp;
|
||||
const struct argp *root_argp;
|
||||
|
||||
/* The argument vector being parsed. May be modified. */
|
||||
int argc;
|
||||
@ -410,22 +414,36 @@ struct argp_state
|
||||
routine returned a non-zero value, it is returned; otherwise 0 is
|
||||
returned. This function may also call exit unless the ARGP_NO_HELP flag
|
||||
is set. INPUT is a pointer to a value to be passed in to the parser. */
|
||||
extern error_t argp_parse (__const struct argp *__restrict __argp,
|
||||
int __argc, char **__restrict __argv,
|
||||
extern error_t argp_parse (const struct argp *__restrict __argp,
|
||||
int /*argc*/, char **__restrict /*argv*/,
|
||||
unsigned __flags, int *__restrict __arg_index,
|
||||
void *__restrict __input);
|
||||
extern error_t __argp_parse (__const struct argp *__restrict __argp,
|
||||
int __argc, char **__restrict __argv,
|
||||
extern error_t __argp_parse (const struct argp *__restrict __argp,
|
||||
int /*argc*/, char **__restrict /*argv*/,
|
||||
unsigned __flags, int *__restrict __arg_index,
|
||||
void *__restrict __input);
|
||||
|
||||
/* Global variables. */
|
||||
|
||||
/* GNULIB makes sure both program_invocation_name and
|
||||
program_invocation_short_name are available */
|
||||
#ifdef GNULIB_PROGRAM_INVOCATION_NAME
|
||||
extern char *program_invocation_name;
|
||||
# undef HAVE_DECL_PROGRAM_INVOCATION_NAME
|
||||
# define HAVE_DECL_PROGRAM_INVOCATION_NAME 1
|
||||
#endif
|
||||
|
||||
#ifdef GNULIB_PROGRAM_INVOCATION_SHORT_NAME
|
||||
extern char *program_invocation_short_name;
|
||||
# undef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
# define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 1
|
||||
#endif
|
||||
|
||||
/* If defined or set by the user program to a non-zero value, then a default
|
||||
option --version is added (unless the ARGP_NO_HELP flag is used), which
|
||||
will print this string followed by a newline and exit (unless the
|
||||
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
|
||||
extern __const char *argp_program_version;
|
||||
extern const char *argp_program_version;
|
||||
|
||||
/* If defined or set by the user program to a non-zero value, then a default
|
||||
option --version is added (unless the ARGP_NO_HELP flag is used), which
|
||||
@ -441,7 +459,7 @@ extern void (*argp_program_version_hook) (FILE *__restrict __stream,
|
||||
argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various
|
||||
standard help messages), embedded in a sentence that says something like
|
||||
`Report bugs to ADDR.'. */
|
||||
extern __const char *argp_program_bug_address;
|
||||
extern const char *argp_program_bug_address;
|
||||
|
||||
/* The exit status that argp will use when exiting due to a parsing error.
|
||||
If not defined or set by the user program, this defaults to EX_USAGE from
|
||||
@ -479,10 +497,10 @@ extern error_t argp_err_exit_status;
|
||||
|
||||
/* Output a usage message for ARGP to STREAM. FLAGS are from the set
|
||||
ARGP_HELP_*. */
|
||||
extern void argp_help (__const struct argp *__restrict __argp,
|
||||
extern void argp_help (const struct argp *__restrict __argp,
|
||||
FILE *__restrict __stream,
|
||||
unsigned __flags, char *__restrict __name);
|
||||
extern void __argp_help (__const struct argp *__restrict __argp,
|
||||
extern void __argp_help (const struct argp *__restrict __argp,
|
||||
FILE *__restrict __stream, unsigned __flags,
|
||||
char *__name);
|
||||
|
||||
@ -496,25 +514,25 @@ extern void __argp_help (__const struct argp *__restrict __argp,
|
||||
|
||||
/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are
|
||||
from the set ARGP_HELP_*. */
|
||||
extern void argp_state_help (__const struct argp_state *__restrict __state,
|
||||
extern void argp_state_help (const struct argp_state *__restrict __state,
|
||||
FILE *__restrict __stream,
|
||||
unsigned int __flags);
|
||||
extern void __argp_state_help (__const struct argp_state *__restrict __state,
|
||||
extern void __argp_state_help (const struct argp_state *__restrict __state,
|
||||
FILE *__restrict __stream,
|
||||
unsigned int __flags);
|
||||
|
||||
/* Possibly output the standard usage message for ARGP to stderr and exit. */
|
||||
extern void argp_usage (__const struct argp_state *__state);
|
||||
extern void __argp_usage (__const struct argp_state *__state);
|
||||
extern void argp_usage (const struct argp_state *__state);
|
||||
extern void __argp_usage (const struct argp_state *__state);
|
||||
|
||||
/* If appropriate, print the printf string FMT and following args, preceded
|
||||
by the program name and `:', to stderr, and followed by a `Try ... --help'
|
||||
message, then exit (1). */
|
||||
extern void argp_error (__const struct argp_state *__restrict __state,
|
||||
__const char *__restrict __fmt, ...)
|
||||
extern void argp_error (const struct argp_state *__restrict __state,
|
||||
const char *__restrict __fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
extern void __argp_error (__const struct argp_state *__restrict __state,
|
||||
__const char *__restrict __fmt, ...)
|
||||
extern void __argp_error (const struct argp_state *__restrict __state,
|
||||
const char *__restrict __fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
|
||||
/* Similar to the standard gnu error-reporting function error(), but will
|
||||
@ -525,31 +543,31 @@ extern void __argp_error (__const struct argp_state *__restrict __state,
|
||||
difference between this function and argp_error is that the latter is for
|
||||
*parsing errors*, and the former is for other problems that occur during
|
||||
parsing but don't reflect a (syntactic) problem with the input. */
|
||||
extern void argp_failure (__const struct argp_state *__restrict __state,
|
||||
extern void argp_failure (const struct argp_state *__restrict __state,
|
||||
int __status, int __errnum,
|
||||
__const char *__restrict __fmt, ...)
|
||||
const char *__restrict __fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 4, 5)));
|
||||
extern void __argp_failure (__const struct argp_state *__restrict __state,
|
||||
extern void __argp_failure (const struct argp_state *__restrict __state,
|
||||
int __status, int __errnum,
|
||||
__const char *__restrict __fmt, ...)
|
||||
const char *__restrict __fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 4, 5)));
|
||||
|
||||
/* Returns true if the option OPT is a valid short option. */
|
||||
extern int _option_is_short (__const struct argp_option *__opt) __THROW;
|
||||
extern int __option_is_short (__const struct argp_option *__opt) __THROW;
|
||||
extern int _option_is_short (const struct argp_option *__opt) __THROW;
|
||||
extern int __option_is_short (const struct argp_option *__opt) __THROW;
|
||||
|
||||
/* Returns true if the option OPT is in fact the last (unused) entry in an
|
||||
options array. */
|
||||
extern int _option_is_end (__const struct argp_option *__opt) __THROW;
|
||||
extern int __option_is_end (__const struct argp_option *__opt) __THROW;
|
||||
extern int _option_is_end (const struct argp_option *__opt) __THROW;
|
||||
extern int __option_is_end (const struct argp_option *__opt) __THROW;
|
||||
|
||||
/* Return the input field for ARGP in the parser corresponding to STATE; used
|
||||
by the help routines. */
|
||||
extern void *_argp_input (__const struct argp *__restrict __argp,
|
||||
__const struct argp_state *__restrict __state)
|
||||
extern void *_argp_input (const struct argp *__restrict __argp,
|
||||
const struct argp_state *__restrict __state)
|
||||
__THROW;
|
||||
extern void *__argp_input (__const struct argp *__restrict __argp,
|
||||
__const struct argp_state *__restrict __state)
|
||||
extern void *__argp_input (const struct argp *__restrict __argp,
|
||||
const struct argp_state *__restrict __state)
|
||||
__THROW;
|
||||
|
||||
#ifdef __USE_EXTERN_INLINES
|
||||
@ -566,25 +584,25 @@ extern void *__argp_input (__const struct argp *__restrict __argp,
|
||||
# endif
|
||||
|
||||
ARGP_EI void
|
||||
__NTH (__argp_usage (__const struct argp_state *__state))
|
||||
__argp_usage (const struct argp_state *__state)
|
||||
{
|
||||
__argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE);
|
||||
}
|
||||
|
||||
ARGP_EI int
|
||||
__NTH (__option_is_short (__const struct argp_option *__opt))
|
||||
__NTH (__option_is_short (const struct argp_option *__opt))
|
||||
{
|
||||
if (__opt->flags & OPTION_DOC)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
int __key = __opt->key;
|
||||
return __key > 0 && isprint (__key);
|
||||
return __key > 0 && __key <= UCHAR_MAX && isprint (__key);
|
||||
}
|
||||
}
|
||||
|
||||
ARGP_EI int
|
||||
__NTH (__option_is_end (__const struct argp_option *__opt))
|
||||
__NTH (__option_is_end (const struct argp_option *__opt))
|
||||
{
|
||||
return !__opt->key && !__opt->name && !__opt->doc && !__opt->group;
|
||||
}
|
||||
|
112
lib/basename.c
112
lib/basename.c
@ -1,6 +1,6 @@
|
||||
/* basename.c -- return the last element in a path
|
||||
/* basename.c -- return the last element in a file name
|
||||
|
||||
Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004 Free
|
||||
Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -15,65 +15,115 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
#include "dirname.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "xalloc.h"
|
||||
#include "xstrndup.h"
|
||||
|
||||
/* In general, we can't use the builtin `basename' function if available,
|
||||
since it has different meanings in different environments.
|
||||
In some environments the builtin `basename' modifies its argument.
|
||||
|
||||
Return the address of the last file name component of NAME. If
|
||||
NAME has no file name components because it is all slashes, return
|
||||
NAME if it is empty, the address of its last slash otherwise. */
|
||||
/* Return the address of the last file name component of NAME. If
|
||||
NAME has no relative file name components because it is a file
|
||||
system root, return the empty string. */
|
||||
|
||||
char *
|
||||
base_name (char const *name)
|
||||
last_component (char const *name)
|
||||
{
|
||||
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
|
||||
char const *p;
|
||||
bool saw_slash = false;
|
||||
|
||||
while (ISSLASH (*base))
|
||||
base++;
|
||||
|
||||
for (p = base; *p; p++)
|
||||
{
|
||||
if (ISSLASH (*p))
|
||||
saw_slash = true;
|
||||
else if (saw_slash)
|
||||
{
|
||||
/* Treat multiple adjacent slashes like a single slash. */
|
||||
do p++;
|
||||
while (ISSLASH (*p));
|
||||
|
||||
/* If the file name ends in slash, use the trailing slash as
|
||||
the basename if no non-slashes have been found. */
|
||||
if (! *p)
|
||||
{
|
||||
if (ISSLASH (*base))
|
||||
base = p - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* *P is a non-slash preceded by a slash. */
|
||||
base = p;
|
||||
saw_slash = false;
|
||||
}
|
||||
}
|
||||
|
||||
return (char *) base;
|
||||
}
|
||||
|
||||
/* Return the length of of the basename NAME. Typically NAME is the
|
||||
value returned by base_name. Act like strlen (NAME), except omit
|
||||
redundant trailing slashes. */
|
||||
|
||||
/* In general, we can't use the builtin `basename' function if available,
|
||||
since it has different meanings in different environments.
|
||||
In some environments the builtin `basename' modifies its argument.
|
||||
|
||||
Return the last file name component of NAME, allocated with
|
||||
xmalloc. On systems with drive letters, a leading "./"
|
||||
distinguishes relative names that would otherwise look like a drive
|
||||
letter. Unlike POSIX basename(), NAME cannot be NULL,
|
||||
base_name("") returns "", and the first trailing slash is not
|
||||
stripped.
|
||||
|
||||
If lstat (NAME) would succeed, then { chdir (dir_name (NAME));
|
||||
lstat (base_name (NAME)); } will access the same file. Likewise,
|
||||
if the sequence { chdir (dir_name (NAME));
|
||||
rename (base_name (NAME), "foo"); } succeeds, you have renamed NAME
|
||||
to "foo" in the same directory NAME was in. */
|
||||
|
||||
char *
|
||||
base_name (char const *name)
|
||||
{
|
||||
char const *base = last_component (name);
|
||||
size_t length;
|
||||
|
||||
/* If there is no last component, then name is a file system root or the
|
||||
empty string. */
|
||||
if (! *base)
|
||||
return xstrndup (name, base_len (name));
|
||||
|
||||
/* Collapse a sequence of trailing slashes into one. */
|
||||
length = base_len (base);
|
||||
if (ISSLASH (base[length]))
|
||||
length++;
|
||||
|
||||
/* On systems with drive letters, `a/b:c' must return `./b:c' rather
|
||||
than `b:c' to avoid confusion with a drive letter. On systems
|
||||
with pure POSIX semantics, this is not an issue. */
|
||||
if (FILE_SYSTEM_PREFIX_LEN (base))
|
||||
{
|
||||
char *p = xmalloc (length + 3);
|
||||
p[0] = '.';
|
||||
p[1] = '/';
|
||||
memcpy (p + 2, base, length);
|
||||
p[length + 2] = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Finally, copy the basename. */
|
||||
return xstrndup (base, length);
|
||||
}
|
||||
|
||||
/* Return the length of the basename NAME. Typically NAME is the
|
||||
value returned by base_name or last_component. Act like strlen
|
||||
(NAME), except omit all trailing slashes. */
|
||||
|
||||
size_t
|
||||
base_len (char const *name)
|
||||
{
|
||||
size_t len;
|
||||
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
|
||||
|
||||
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
|
||||
continue;
|
||||
|
||||
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
|
||||
&& ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
|
||||
return 2;
|
||||
|
||||
if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
|
||||
&& len == prefix_len && ISSLASH (name[prefix_len]))
|
||||
return prefix_len + 1;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
138
lib/dirname.c
138
lib/dirname.c
@ -1,6 +1,6 @@
|
||||
/* dirname.c -- return all but the last element in a path
|
||||
/* dirname.c -- return all but the last element in a file name
|
||||
|
||||
Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004 Free Software
|
||||
Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -15,107 +15,71 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
#include "dirname.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Return the length of `dirname (PATH)', or zero if PATH is
|
||||
in the working directory. Works properly even if
|
||||
there are trailing slashes (by effectively ignoring them). */
|
||||
/* Return the length of the prefix of FILE that will be used by
|
||||
dir_name. If FILE is in the working directory, this returns zero
|
||||
even though `dir_name (FILE)' will return ".". Works properly even
|
||||
if there are trailing slashes (by effectively ignoring them). */
|
||||
|
||||
size_t
|
||||
dir_len (char const *path)
|
||||
dir_len (char const *file)
|
||||
{
|
||||
size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (path);
|
||||
size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
|
||||
size_t length;
|
||||
|
||||
/* Strip the basename and any redundant slashes before it. */
|
||||
for (length = base_name (path) - path; prefix_length < length; length--)
|
||||
if (! ISSLASH (path[length - 1]))
|
||||
return length;
|
||||
/* Advance prefix_length beyond important leading slashes. */
|
||||
prefix_length += (prefix_length != 0
|
||||
? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
&& ISSLASH (file[prefix_length]))
|
||||
: (ISSLASH (file[0])
|
||||
? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||
&& ISSLASH (file[1]) && ! ISSLASH (file[2])
|
||||
? 2 : 1))
|
||||
: 0));
|
||||
|
||||
/* But don't strip the only slash from "/". */
|
||||
return prefix_length + ISSLASH (path[prefix_length]);
|
||||
/* Strip the basename and any redundant slashes before it. */
|
||||
for (length = last_component (file) - file;
|
||||
prefix_length < length; length--)
|
||||
if (! ISSLASH (file[length - 1]))
|
||||
break;
|
||||
return length;
|
||||
}
|
||||
|
||||
/* Return the leading directories part of PATH,
|
||||
allocated with xmalloc.
|
||||
Works properly even if there are trailing slashes
|
||||
(by effectively ignoring them). */
|
||||
|
||||
/* In general, we can't use the builtin `dirname' function if available,
|
||||
since it has different meanings in different environments.
|
||||
In some environments the builtin `dirname' modifies its argument.
|
||||
|
||||
Return the leading directories part of FILE, allocated with xmalloc.
|
||||
Works properly even if there are trailing slashes (by effectively
|
||||
ignoring them). Unlike POSIX dirname(), FILE cannot be NULL.
|
||||
|
||||
If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
|
||||
lstat (base_name (FILE)); } will access the same file. Likewise,
|
||||
if the sequence { chdir (dir_name (FILE));
|
||||
rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
|
||||
to "foo" in the same directory FILE was in. */
|
||||
|
||||
char *
|
||||
dir_name (char const *path)
|
||||
dir_name (char const *file)
|
||||
{
|
||||
size_t length = dir_len (path);
|
||||
bool append_dot = (length == FILE_SYSTEM_PREFIX_LEN (path));
|
||||
char *newpath = xmalloc (length + append_dot + 1);
|
||||
memcpy (newpath, path, length);
|
||||
size_t length = dir_len (file);
|
||||
bool append_dot = (length == 0
|
||||
|| (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
&& length == FILE_SYSTEM_PREFIX_LEN (file)
|
||||
&& file[2] != '\0' && ! ISSLASH (file[2])));
|
||||
char *dir = xmalloc (length + append_dot + 1);
|
||||
memcpy (dir, file, length);
|
||||
if (append_dot)
|
||||
newpath[length++] = '.';
|
||||
newpath[length] = 0;
|
||||
return newpath;
|
||||
dir[length++] = '.';
|
||||
dir[length] = '\0';
|
||||
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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Take file names apart into directory and base names.
|
||||
|
||||
Copyright (C) 1998, 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 2001, 2003-2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef DIRNAME_H_
|
||||
# define DIRNAME_H_ 1
|
||||
@ -31,17 +31,40 @@
|
||||
# endif
|
||||
|
||||
# ifndef FILE_SYSTEM_PREFIX_LEN
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
|
||||
# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
|
||||
/* This internal macro assumes ASCII, but all hosts that support drive
|
||||
letters use ASCII. */
|
||||
# define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \
|
||||
<= 'z' - 'a')
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) \
|
||||
(_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
|
||||
# else
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
|
||||
# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
|
||||
# endif
|
||||
|
||||
# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
|
||||
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
|
||||
# endif
|
||||
|
||||
# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
|
||||
# else
|
||||
# define IS_ABSOLUTE_FILE_NAME(F) \
|
||||
(ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F))
|
||||
# endif
|
||||
# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
|
||||
|
||||
char *base_name (char const *path);
|
||||
char *dir_name (char const *path);
|
||||
size_t base_len (char const *path);
|
||||
size_t dir_len (char const *path);
|
||||
char *base_name (char const *file);
|
||||
char *dir_name (char const *file);
|
||||
size_t base_len (char const *file);
|
||||
size_t dir_len (char const *file);
|
||||
char *last_component (char const *file);
|
||||
|
||||
bool strip_trailing_slashes (char *path);
|
||||
bool strip_trailing_slashes (char *file);
|
||||
|
||||
#endif /* not DIRNAME_H_ */
|
||||
|
138
lib/error.c
138
lib/error.c
@ -1,5 +1,5 @@
|
||||
/* Error handler for noninteractive utilities
|
||||
Copyright (C) 1990-1998, 2000-2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990-1998, 2000-2005, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -14,11 +14,11 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#if !_LIBC
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
@ -29,13 +29,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <libintl.h>
|
||||
#else
|
||||
#if !_LIBC && ENABLE_NLS
|
||||
# include "gettext.h"
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <libintl.h>
|
||||
# include <stdbool.h>
|
||||
# include <stdint.h>
|
||||
# include <wchar.h>
|
||||
# define mbsrtowcs __mbsrtowcs
|
||||
#endif
|
||||
@ -61,6 +62,7 @@ unsigned int error_message_count;
|
||||
|
||||
# define program_name program_invocation_name
|
||||
# include <errno.h>
|
||||
# include <limits.h>
|
||||
# include <libio/libioP.h>
|
||||
|
||||
/* In GNU libc we want do not want to use the common name `error' directly.
|
||||
@ -90,23 +92,19 @@ extern void __error_at_line (int status, int errnum, const char *file_name,
|
||||
char *strerror_r ();
|
||||
# endif
|
||||
|
||||
# ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
# endif
|
||||
|
||||
/* The calling program should define program_name and set it to the
|
||||
name of the executing program. */
|
||||
extern char *program_name;
|
||||
|
||||
# if HAVE_STRERROR_R || defined strerror_r
|
||||
# define __strerror_r strerror_r
|
||||
# endif
|
||||
# endif /* HAVE_STRERROR_R || defined strerror_r */
|
||||
#endif /* not _LIBC */
|
||||
|
||||
static void
|
||||
print_errno_message (int errnum)
|
||||
{
|
||||
char const *s = NULL;
|
||||
char const *s;
|
||||
|
||||
#if defined HAVE_STRERROR_R || _LIBC
|
||||
char errbuf[1024];
|
||||
@ -115,23 +113,23 @@ print_errno_message (int errnum)
|
||||
# else
|
||||
if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
|
||||
s = errbuf;
|
||||
else
|
||||
s = 0;
|
||||
# endif
|
||||
#else
|
||||
s = strerror (errnum);
|
||||
#endif
|
||||
|
||||
#if !_LIBC
|
||||
if (! s && ! (s = strerror (errnum)))
|
||||
if (! s)
|
||||
s = _("Unknown system error");
|
||||
#endif
|
||||
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
{
|
||||
__fwprintf (stderr, L": %s", s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
__fxprintf (NULL, ": %s", s);
|
||||
#else
|
||||
fprintf (stderr, ": %s", s);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -142,26 +140,65 @@ error_tail (int status, int errnum, const char *message, va_list args)
|
||||
{
|
||||
# define ALLOCA_LIMIT 2000
|
||||
size_t len = strlen (message) + 1;
|
||||
const wchar_t *wmessage = L"out of memory";
|
||||
wchar_t *wbuf = (len < ALLOCA_LIMIT
|
||||
? alloca (len * sizeof *wbuf)
|
||||
: len <= SIZE_MAX / sizeof *wbuf
|
||||
? malloc (len * sizeof *wbuf)
|
||||
: NULL);
|
||||
wchar_t *wmessage = NULL;
|
||||
mbstate_t st;
|
||||
size_t res;
|
||||
const char *tmp;
|
||||
bool use_malloc = false;
|
||||
|
||||
if (wbuf)
|
||||
while (1)
|
||||
{
|
||||
size_t res;
|
||||
mbstate_t st;
|
||||
const char *tmp = message;
|
||||
if (__libc_use_alloca (len * sizeof (wchar_t)))
|
||||
wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
|
||||
else
|
||||
{
|
||||
if (!use_malloc)
|
||||
wmessage = NULL;
|
||||
|
||||
wchar_t *p = (wchar_t *) realloc (wmessage,
|
||||
len * sizeof (wchar_t));
|
||||
if (p == NULL)
|
||||
{
|
||||
free (wmessage);
|
||||
fputws_unlocked (L"out of memory\n", stderr);
|
||||
return;
|
||||
}
|
||||
wmessage = p;
|
||||
use_malloc = true;
|
||||
}
|
||||
|
||||
memset (&st, '\0', sizeof (st));
|
||||
res = mbsrtowcs (wbuf, &tmp, len, &st);
|
||||
wmessage = res == (size_t) -1 ? L"???" : wbuf;
|
||||
tmp = message;
|
||||
|
||||
res = mbsrtowcs (wmessage, &tmp, len, &st);
|
||||
if (res != len)
|
||||
break;
|
||||
|
||||
if (__builtin_expect (len >= SIZE_MAX / 2, 0))
|
||||
{
|
||||
/* This really should not happen if everything is fine. */
|
||||
res = (size_t) -1;
|
||||
break;
|
||||
}
|
||||
|
||||
len *= 2;
|
||||
}
|
||||
|
||||
if (res == (size_t) -1)
|
||||
{
|
||||
/* The string cannot be converted. */
|
||||
if (use_malloc)
|
||||
{
|
||||
free (wmessage);
|
||||
use_malloc = false;
|
||||
}
|
||||
wmessage = (wchar_t *) L"???";
|
||||
}
|
||||
|
||||
__vfwprintf (stderr, wmessage, args);
|
||||
if (! (len < ALLOCA_LIMIT))
|
||||
free (wbuf);
|
||||
|
||||
if (use_malloc)
|
||||
free (wmessage);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -172,11 +209,10 @@ error_tail (int status, int errnum, const char *message, va_list args)
|
||||
if (errnum)
|
||||
print_errno_message (errnum);
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
putwc (L'\n', stderr);
|
||||
else
|
||||
__fxprintf (NULL, "\n");
|
||||
#else
|
||||
putc ('\n', stderr);
|
||||
#endif
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
exit (status);
|
||||
@ -209,11 +245,10 @@ error (int status, int errnum, const char *message, ...)
|
||||
else
|
||||
{
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s: ", program_name);
|
||||
else
|
||||
__fxprintf (NULL, "%s: ", program_name);
|
||||
#else
|
||||
fprintf (stderr, "%s: ", program_name);
|
||||
#endif
|
||||
fprintf (stderr, "%s: ", program_name);
|
||||
}
|
||||
|
||||
va_start (args, message);
|
||||
@ -269,22 +304,19 @@ error_at_line (int status, int errnum, const char *file_name,
|
||||
else
|
||||
{
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s: ", program_name);
|
||||
else
|
||||
__fxprintf (NULL, "%s:", program_name);
|
||||
#else
|
||||
fprintf (stderr, "%s:", program_name);
|
||||
#endif
|
||||
fprintf (stderr, "%s:", program_name);
|
||||
}
|
||||
|
||||
if (file_name != NULL)
|
||||
{
|
||||
#if _LIBC
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s:%d: ", file_name, line_number);
|
||||
else
|
||||
__fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
|
||||
file_name, line_number);
|
||||
#else
|
||||
fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
|
||||
file_name, line_number);
|
||||
#endif
|
||||
fprintf (stderr, "%s:%d: ", file_name, line_number);
|
||||
}
|
||||
|
||||
va_start (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Declaration for error-reporting function
|
||||
Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996, 1997, 2003, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -14,14 +14,14 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _ERROR_H
|
||||
#define _ERROR_H 1
|
||||
|
||||
#ifndef __attribute__
|
||||
/* This feature is available in gcc versions 2.5 and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
/* The __-protected variants of `format' and `printf' attributes
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Failure exit status
|
||||
|
||||
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -15,13 +15,12 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
#include "exitfail.h"
|
||||
#include "exit.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int volatile exit_failure = EXIT_FAILURE;
|
||||
|
@ -15,6 +15,6 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
extern int volatile exit_failure;
|
||||
|
27
lib/fatal.c
Normal file
27
lib/fatal.c
Normal 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);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* An interface to read and write that retries (if necessary) until complete.
|
||||
|
||||
Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
||||
2004 Free Software Foundation, Inc.
|
||||
2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -15,11 +15,9 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#ifdef FULL_READ
|
||||
@ -62,7 +60,7 @@ size_t
|
||||
full_rw (int fd, const void *buf, size_t count)
|
||||
{
|
||||
size_t total = 0;
|
||||
const char *ptr = buf;
|
||||
const char *ptr = (const char *) buf;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
88
lib/getopt.c
88
lib/getopt.c
@ -2,7 +2,7 @@
|
||||
NOTE: getopt is now part of the C library, so if you don't know what
|
||||
"Keep this file name-space clean" means, talk to drepper@gnu.org
|
||||
before changing it!
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
@ -18,32 +18,20 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
|
||||
Ditto for AIX 3.2 and <stdlib.h>. */
|
||||
#ifndef _NO_PROTO
|
||||
# define _NO_PROTO
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#ifndef _LIBC
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
/* Don't include stdlib.h for non-GNU C libraries because some of them
|
||||
contain conflicting prototypes for getopt. */
|
||||
# include <stdlib.h>
|
||||
# include <unistd.h>
|
||||
#endif /* GNU C library. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef VMS
|
||||
#ifdef __VMS
|
||||
# include <unixlib.h>
|
||||
#endif
|
||||
|
||||
@ -76,7 +64,6 @@
|
||||
GNU application programs can use a third alternative mode in which
|
||||
they can distinguish the relative order of options and other arguments. */
|
||||
|
||||
#include "getopt.h"
|
||||
#include "getopt_int.h"
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
@ -118,16 +105,9 @@ int optopt = '?';
|
||||
static struct _getopt_data getopt_data;
|
||||
|
||||
|
||||
#ifndef __GNU_LIBRARY__
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
#ifndef getenv
|
||||
#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV
|
||||
extern char *getenv ();
|
||||
#endif
|
||||
|
||||
#endif /* not __GNU_LIBRARY__ */
|
||||
|
||||
#ifdef _LIBC
|
||||
/* Stored original parameters.
|
||||
@ -556,10 +536,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
|
||||
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
|
||||
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
|
||||
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s", buf);
|
||||
else
|
||||
fputs (buf, stderr);
|
||||
__fxprintf (NULL, "%s", buf);
|
||||
|
||||
((_IO_FILE *) stderr)->_flags2 = old_flags2;
|
||||
_IO_funlockfile (stderr);
|
||||
@ -634,10 +611,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
|
||||
((_IO_FILE *) stderr)->_flags2
|
||||
|= _IO_FLAGS2_NOTCANCEL;
|
||||
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s", buf);
|
||||
else
|
||||
fputs (buf, stderr);
|
||||
__fxprintf (NULL, "%s", buf);
|
||||
|
||||
((_IO_FILE *) stderr)->_flags2 = old_flags2;
|
||||
_IO_funlockfile (stderr);
|
||||
@ -674,10 +648,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
|
||||
((_IO_FILE *) stderr)->_flags2
|
||||
|= _IO_FLAGS2_NOTCANCEL;
|
||||
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s", buf);
|
||||
else
|
||||
fputs (buf, stderr);
|
||||
__fxprintf (NULL, "%s", buf);
|
||||
|
||||
((_IO_FILE *) stderr)->_flags2 = old_flags2;
|
||||
_IO_funlockfile (stderr);
|
||||
@ -751,10 +722,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
|
||||
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
|
||||
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
|
||||
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s", buf);
|
||||
else
|
||||
fputs (buf, stderr);
|
||||
__fxprintf (NULL, "%s", buf);
|
||||
|
||||
((_IO_FILE *) stderr)->_flags2 = old_flags2;
|
||||
_IO_funlockfile (stderr);
|
||||
@ -817,10 +785,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
|
||||
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
|
||||
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
|
||||
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s", buf);
|
||||
else
|
||||
fputs (buf, stderr);
|
||||
__fxprintf (NULL, "%s", buf);
|
||||
|
||||
((_IO_FILE *) stderr)->_flags2 = old_flags2;
|
||||
_IO_funlockfile (stderr);
|
||||
@ -868,10 +833,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
|
||||
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
|
||||
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
|
||||
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s", buf);
|
||||
else
|
||||
fputs (buf, stderr);
|
||||
__fxprintf (NULL, "%s", buf);
|
||||
|
||||
((_IO_FILE *) stderr)->_flags2 = old_flags2;
|
||||
_IO_funlockfile (stderr);
|
||||
@ -940,10 +902,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
|
||||
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
|
||||
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
|
||||
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s", buf);
|
||||
else
|
||||
fputs (buf, stderr);
|
||||
__fxprintf (NULL, "%s", buf);
|
||||
|
||||
((_IO_FILE *) stderr)->_flags2 = old_flags2;
|
||||
_IO_funlockfile (stderr);
|
||||
@ -985,10 +944,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
|
||||
((_IO_FILE *) stderr)->_flags2
|
||||
|= _IO_FLAGS2_NOTCANCEL;
|
||||
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s", buf);
|
||||
else
|
||||
fputs (buf, stderr);
|
||||
__fxprintf (NULL, "%s", buf);
|
||||
|
||||
((_IO_FILE *) stderr)->_flags2 = old_flags2;
|
||||
_IO_funlockfile (stderr);
|
||||
@ -1027,10 +983,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
|
||||
((_IO_FILE *) stderr)->_flags2
|
||||
|= _IO_FLAGS2_NOTCANCEL;
|
||||
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s", buf);
|
||||
else
|
||||
fputs (buf, stderr);
|
||||
__fxprintf (NULL, "%s", buf);
|
||||
|
||||
((_IO_FILE *) stderr)->_flags2 = old_flags2;
|
||||
_IO_funlockfile (stderr);
|
||||
@ -1101,10 +1054,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
|
||||
int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
|
||||
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
|
||||
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s", buf);
|
||||
else
|
||||
fputs (buf, stderr);
|
||||
__fxprintf (NULL, "%s", buf);
|
||||
|
||||
((_IO_FILE *) stderr)->_flags2 = old_flags2;
|
||||
_IO_funlockfile (stderr);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004,2006
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
@ -15,15 +15,12 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <getopt.h>
|
||||
#else
|
||||
# include <config.h>
|
||||
# include "getopt.h"
|
||||
#endif
|
||||
#include "getopt_int.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Declarations for getopt.
|
||||
Copyright (C) 1989-1994,1996-1999,2001,2003,2004
|
||||
Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005,2006,2007
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
|
||||
@ -34,9 +34,7 @@
|
||||
#if defined __GETOPT_PREFIX && !defined __need_getopt
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
# undef __need_getopt
|
||||
# undef getopt
|
||||
# undef getopt_long
|
||||
@ -67,14 +65,14 @@
|
||||
but it caused redefinition warnings if both unistd.h and getopt.h were
|
||||
included, since unistd.h includes getopt.h having previously defined
|
||||
__need_getopt.
|
||||
|
||||
|
||||
The only place where __getopt_argv_const is used is in definitions
|
||||
of getopt_long and getopt_long_only below, but these are visible
|
||||
only if __need_getopt is not defined, so it is quite safe to rewrite
|
||||
the conditional as follows:
|
||||
*/
|
||||
#if !defined __need_getopt
|
||||
# if defined __GETOPT_PREFIX
|
||||
# if defined __GETOPT_PREFIX
|
||||
# define __getopt_argv_const /* empty */
|
||||
# else
|
||||
# define __getopt_argv_const const
|
||||
@ -103,7 +101,7 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@ -198,9 +196,10 @@ struct option
|
||||
scanning, explicitly telling `getopt' that there are no more
|
||||
options.
|
||||
|
||||
If OPTS begins with `--', then non-option arguments are treated as
|
||||
arguments to the option '\0'. This behavior is specific to the GNU
|
||||
`getopt'. */
|
||||
If OPTS begins with `-', then non-option arguments are treated as
|
||||
arguments to the option '\1'. This behavior is specific to the GNU
|
||||
`getopt'. If OPTS begins with `+', or POSIXLY_CORRECT is set in
|
||||
the environment, then do not permute arguments. */
|
||||
|
||||
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
|
||||
__THROW;
|
||||
@ -217,7 +216,7 @@ extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _GETOPT_INT_H
|
||||
#define _GETOPT_INT_H 1
|
||||
|
220
lib/gettext.h
220
lib/gettext.h
@ -1,5 +1,5 @@
|
||||
/* Convenience header for conditional use of GNU <libintl.h>.
|
||||
Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _LIBGETTEXT_H
|
||||
#define _LIBGETTEXT_H 1
|
||||
@ -24,6 +24,18 @@
|
||||
/* Get declarations of GNU message catalog functions. */
|
||||
# include <libintl.h>
|
||||
|
||||
/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
|
||||
the gettext() and ngettext() macros. This is an alternative to calling
|
||||
textdomain(), and is useful for libraries. */
|
||||
# ifdef DEFAULT_TEXT_DOMAIN
|
||||
# undef gettext
|
||||
# define gettext(Msgid) \
|
||||
dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
|
||||
# undef ngettext
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
|
||||
@ -36,23 +48,38 @@
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
|
||||
<libintl.h>, which chokes if dcgettext is defined as a macro. So include
|
||||
it now, to make later inclusions of <libintl.h> a NOP. */
|
||||
#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
|
||||
# include <cstdlib>
|
||||
# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
|
||||
# include <libintl.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Disabled NLS.
|
||||
The casts to 'const char *' serve the purpose of producing warnings
|
||||
for invalid uses of the value returned from these functions.
|
||||
On pre-ANSI systems without 'const', the config.h file is supposed to
|
||||
contain "#define const". */
|
||||
# define gettext(Msgid) ((const char *) (Msgid))
|
||||
# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
|
||||
# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
|
||||
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
|
||||
# define dcgettext(Domainname, Msgid, Category) \
|
||||
((void) (Category), dgettext (Domainname, Msgid))
|
||||
# define ngettext(Msgid1, Msgid2, N) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
((N) == 1 \
|
||||
? ((void) (Msgid2), (const char *) (Msgid1)) \
|
||||
: ((void) (Msgid1), (const char *) (Msgid2)))
|
||||
# define dngettext(Domainname, Msgid1, Msgid2, N) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
((void) (Domainname), ngettext (Msgid1, Msgid2, N))
|
||||
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
|
||||
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
|
||||
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
|
||||
# define textdomain(Domainname) ((const char *) (Domainname))
|
||||
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
|
||||
# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
|
||||
# define bindtextdomain(Domainname, Dirname) \
|
||||
((void) (Domainname), (const char *) (Dirname))
|
||||
# define bind_textdomain_codeset(Domainname, Codeset) \
|
||||
((void) (Domainname), (const char *) (Codeset))
|
||||
|
||||
#endif
|
||||
|
||||
@ -65,4 +92,179 @@
|
||||
initializer for static 'char[]' or 'const char[]' variables. */
|
||||
#define gettext_noop(String) String
|
||||
|
||||
/* The separator between msgctxt and msgid in a .mo file. */
|
||||
#define GETTEXT_CONTEXT_GLUE "\004"
|
||||
|
||||
/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
|
||||
MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
|
||||
short and rarely need to change.
|
||||
The letter 'p' stands for 'particular' or 'special'. */
|
||||
#ifdef DEFAULT_TEXT_DOMAIN
|
||||
# define pgettext(Msgctxt, Msgid) \
|
||||
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#else
|
||||
# define pgettext(Msgctxt, Msgid) \
|
||||
pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#endif
|
||||
#define dpgettext(Domainname, Msgctxt, Msgid) \
|
||||
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
|
||||
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
|
||||
#ifdef DEFAULT_TEXT_DOMAIN
|
||||
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#else
|
||||
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#endif
|
||||
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
|
||||
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
|
||||
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
pgettext_aux (const char *domain,
|
||||
const char *msg_ctxt_id, const char *msgid,
|
||||
int category)
|
||||
{
|
||||
const char *translation = dcgettext (domain, msg_ctxt_id, category);
|
||||
if (translation == msg_ctxt_id)
|
||||
return msgid;
|
||||
else
|
||||
return translation;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
npgettext_aux (const char *domain,
|
||||
const char *msg_ctxt_id, const char *msgid,
|
||||
const char *msgid_plural, unsigned long int n,
|
||||
int category)
|
||||
{
|
||||
const char *translation =
|
||||
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
|
||||
if (translation == msg_ctxt_id || translation == msgid_plural)
|
||||
return (n == 1 ? msgid : msgid_plural);
|
||||
else
|
||||
return translation;
|
||||
}
|
||||
|
||||
/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
|
||||
can be arbitrary expressions. But for string literals these macros are
|
||||
less efficient than those above. */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
|
||||
(((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
|
||||
/* || __STDC_VERSION__ >= 199901L */ )
|
||||
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define pgettext_expr(Msgctxt, Msgid) \
|
||||
dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
|
||||
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
|
||||
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
dcpgettext_expr (const char *domain,
|
||||
const char *msgctxt, const char *msgid,
|
||||
int category)
|
||||
{
|
||||
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||
size_t msgid_len = strlen (msgid) + 1;
|
||||
const char *translation;
|
||||
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
char msg_ctxt_id[msgctxt_len + msgid_len];
|
||||
#else
|
||||
char buf[1024];
|
||||
char *msg_ctxt_id =
|
||||
(msgctxt_len + msgid_len <= sizeof (buf)
|
||||
? buf
|
||||
: (char *) malloc (msgctxt_len + msgid_len));
|
||||
if (msg_ctxt_id != NULL)
|
||||
#endif
|
||||
{
|
||||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||
translation = dcgettext (domain, msg_ctxt_id, category);
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
if (msg_ctxt_id != buf)
|
||||
free (msg_ctxt_id);
|
||||
#endif
|
||||
if (translation != msg_ctxt_id)
|
||||
return translation;
|
||||
}
|
||||
return msgid;
|
||||
}
|
||||
|
||||
#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
|
||||
dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
|
||||
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
inline
|
||||
#endif
|
||||
#endif
|
||||
static const char *
|
||||
dcnpgettext_expr (const char *domain,
|
||||
const char *msgctxt, const char *msgid,
|
||||
const char *msgid_plural, unsigned long int n,
|
||||
int category)
|
||||
{
|
||||
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||
size_t msgid_len = strlen (msgid) + 1;
|
||||
const char *translation;
|
||||
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
char msg_ctxt_id[msgctxt_len + msgid_len];
|
||||
#else
|
||||
char buf[1024];
|
||||
char *msg_ctxt_id =
|
||||
(msgctxt_len + msgid_len <= sizeof (buf)
|
||||
? buf
|
||||
: (char *) malloc (msgctxt_len + msgid_len));
|
||||
if (msg_ctxt_id != NULL)
|
||||
#endif
|
||||
{
|
||||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
|
||||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||
if (msg_ctxt_id != buf)
|
||||
free (msg_ctxt_id);
|
||||
#endif
|
||||
if (!(translation == msg_ctxt_id || translation == msgid_plural))
|
||||
return translation;
|
||||
}
|
||||
return (n == 1 ? msgid : msgid_plural);
|
||||
}
|
||||
|
||||
#endif /* _LIBGETTEXT_H */
|
||||
|
1048
lib/hash.c
Normal file
1048
lib/hash.c
Normal file
File diff suppressed because it is too large
Load Diff
88
lib/hash.h
Normal file
88
lib/hash.h
Normal 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
78
lib/intprops.h
Normal 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
51
lib/inttostr.c
Normal 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;
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
/* exit() function.
|
||||
Copyright (C) 1995, 2001 Free Software Foundation, Inc.
|
||||
/* inttostr.h -- convert integers to printable strings
|
||||
|
||||
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -13,20 +15,16 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _EXIT_H
|
||||
#define _EXIT_H
|
||||
/* Written by Paul Eggert */
|
||||
|
||||
/* Get exit() declaration. */
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Some systems do not define EXIT_*, even with STDC_HEADERS. */
|
||||
#ifndef EXIT_SUCCESS
|
||||
# define EXIT_SUCCESS 0
|
||||
#endif
|
||||
#ifndef EXIT_FAILURE
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
#include "intprops.h"
|
||||
|
||||
#endif /* _EXIT_H */
|
||||
char *offtostr (off_t, char *);
|
||||
char *imaxtostr (intmax_t, char *);
|
||||
char *umaxtostr (uintmax_t, char *);
|
||||
char *uinttostr (unsigned int, char *);
|
@ -1,5 +1,5 @@
|
||||
/* Copy memory area and return pointer after last written byte.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -13,11 +13,11 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include "mempcpy.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
|
||||
|
365
lib/paxerror.c
Normal file
365
lib/paxerror.c
Normal 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
28
lib/paxexit.c
Normal 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
115
lib/paxlib.h
Normal 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
156
lib/paxnames.c
Normal 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
41
lib/quote.c
Normal 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);
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
/* Searching in a string.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
/* quote.h - prototypes for quote.c
|
||||
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -13,16 +15,8 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_STRCHRNUL
|
||||
|
||||
/* Get strchrnul() declaration. */
|
||||
#include <string.h>
|
||||
|
||||
#else
|
||||
|
||||
/* Find the first occurrence of C in S or the final NUL byte. */
|
||||
extern char *strchrnul (const char *s, int c_in);
|
||||
|
||||
#endif
|
||||
char const *quote_n (int n, char const *name);
|
||||
char const *quote (char const *name);
|
697
lib/quotearg.c
Normal file
697
lib/quotearg.c
Normal 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
140
lib/quotearg.h
Normal 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_ */
|
@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
extern char *rmt_command;
|
||||
extern char *rmt_dev_name__;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Functions for communicating with a remote tape drive.
|
||||
|
||||
Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004,
|
||||
2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* The man page rmt(8) for /etc/rmt documents the remote mag tape protocol
|
||||
which rdump and rrestore use. Unfortunately, the man page is *WRONG*.
|
||||
@ -33,6 +33,8 @@
|
||||
code, courtesy of Dan Kegel. */
|
||||
|
||||
#include "system.h"
|
||||
#include "system-ioctl.h"
|
||||
|
||||
#include <safe-read.h>
|
||||
#include <full-write.h>
|
||||
|
||||
@ -58,7 +60,7 @@
|
||||
#endif
|
||||
|
||||
#include <rmt.h>
|
||||
#include <localedir.h>
|
||||
#include <rmt-command.h>
|
||||
|
||||
/* Exit status if exec errors. */
|
||||
#define EXIT_ON_EXEC_ERROR 128
|
||||
@ -340,9 +342,7 @@ encode_oflag (char *buf, int oflag)
|
||||
#ifdef O_NOCTTY
|
||||
if (oflag & O_NOCTTY) strcat (buf, "|O_NOCTTY");
|
||||
#endif
|
||||
#ifdef O_NONBLOCK
|
||||
if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK");
|
||||
#endif
|
||||
#ifdef O_RSYNC
|
||||
if (oflag & O_RSYNC) strcat (buf, "|O_RSYNC");
|
||||
#endif
|
||||
@ -358,7 +358,7 @@ encode_oflag (char *buf, int oflag)
|
||||
remote pipe number plus BIAS. REMOTE_SHELL may be overridden. On
|
||||
error, return -1. */
|
||||
int
|
||||
rmt_open__ (const char *file_name, int open_mode, int bias,
|
||||
rmt_open__ (const char *file_name, int open_mode, int bias,
|
||||
const char *remote_shell)
|
||||
{
|
||||
int remote_pipe_number; /* pseudo, biased file descriptor */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* An interface to read and write that retries after interrupts.
|
||||
|
||||
Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004 Free Software
|
||||
Foundation, Inc.
|
||||
Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004, 2005, 2006 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -15,11 +15,9 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#ifdef SAFE_WRITE
|
||||
@ -30,9 +28,7 @@
|
||||
|
||||
/* Get ssize_t. */
|
||||
#include <sys/types.h>
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* An interface to read() that retries after interrupts.
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -13,13 +13,23 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define SAFE_READ_ERROR ((size_t) -1)
|
||||
|
||||
/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted.
|
||||
Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR
|
||||
upon error. */
|
||||
extern size_t safe_read (int fd, void *buf, size_t count);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#define SAFE_WRITE
|
||||
#include "safe-read.c"
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* savedir.c -- save the list of files in a directory in a string
|
||||
|
||||
Copyright 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright (C) 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -15,13 +15,11 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
#include "savedir.h"
|
||||
|
||||
@ -29,68 +27,62 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef CLOSEDIR_VOID
|
||||
/* Fake a return value. */
|
||||
# define CLOSEDIR(d) (closedir (d), 0)
|
||||
#else
|
||||
# define CLOSEDIR(d) closedir (d)
|
||||
#include <dirent.h>
|
||||
#ifndef _D_EXACT_NAMLEN
|
||||
# define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "openat.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Return a freshly allocated string containing the filenames
|
||||
in directory DIR, separated by '\0' characters;
|
||||
the end is marked by two '\0' characters in a row.
|
||||
Return NULL (setting errno) if DIR cannot be opened, read, or closed. */
|
||||
|
||||
#ifndef NAME_SIZE_DEFAULT
|
||||
# define NAME_SIZE_DEFAULT 512
|
||||
#endif
|
||||
|
||||
char *
|
||||
savedir (const char *dir)
|
||||
/* The results of opendir() in this file are not used with dirfd and fchdir,
|
||||
therefore save some unnecessary work in fchdir.c. */
|
||||
#undef opendir
|
||||
#undef closedir
|
||||
|
||||
/* Return a freshly allocated string containing the file names
|
||||
in directory DIRP, separated by '\0' characters;
|
||||
the end is marked by two '\0' characters in a row.
|
||||
Return NULL (setting errno) if DIRP cannot be read or closed.
|
||||
If DIRP is NULL, return NULL without affecting errno. */
|
||||
|
||||
static char *
|
||||
savedirstream (DIR *dirp)
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
char *name_space;
|
||||
size_t allocated = NAME_SIZE_DEFAULT;
|
||||
size_t used = 0;
|
||||
int save_errno;
|
||||
|
||||
dirp = opendir (dir);
|
||||
if (dirp == NULL)
|
||||
return NULL;
|
||||
|
||||
name_space = xmalloc (allocated);
|
||||
|
||||
errno = 0;
|
||||
while ((dp = readdir (dirp)) != NULL)
|
||||
for (;;)
|
||||
{
|
||||
struct dirent const *dp;
|
||||
char const *entry;
|
||||
|
||||
errno = 0;
|
||||
dp = readdir (dirp);
|
||||
if (! dp)
|
||||
break;
|
||||
|
||||
/* Skip "", ".", and "..". "" is returned by at least one buggy
|
||||
implementation: Solaris 2.4 readdir on NFS file systems. */
|
||||
char const *entry = dp->d_name;
|
||||
entry = dp->d_name;
|
||||
if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
|
||||
{
|
||||
size_t entry_size = strlen (entry) + 1;
|
||||
size_t entry_size = _D_EXACT_NAMLEN (dp) + 1;
|
||||
if (used + entry_size < used)
|
||||
xalloc_die ();
|
||||
if (allocated <= used + entry_size)
|
||||
@ -111,7 +103,7 @@ savedir (const char *dir)
|
||||
}
|
||||
name_space[used] = '\0';
|
||||
save_errno = errno;
|
||||
if (CLOSEDIR (dirp) != 0)
|
||||
if (closedir (dirp) != 0)
|
||||
save_errno = errno;
|
||||
if (save_errno != 0)
|
||||
{
|
||||
@ -121,3 +113,25 @@ savedir (const char *dir)
|
||||
}
|
||||
return name_space;
|
||||
}
|
||||
|
||||
/* Return a freshly allocated string containing the file names
|
||||
in directory DIR, separated by '\0' characters;
|
||||
the end is marked by two '\0' characters in a row.
|
||||
Return NULL (setting errno) if DIR cannot be opened, read, or closed. */
|
||||
|
||||
char *
|
||||
savedir (char const *dir)
|
||||
{
|
||||
return savedirstream (opendir (dir));
|
||||
}
|
||||
|
||||
/* Return a freshly allocated string containing the file names
|
||||
in directory FD, separated by '\0' characters;
|
||||
the end is marked by two '\0' characters in a row.
|
||||
Return NULL (setting errno) if FD cannot be read or closed. */
|
||||
|
||||
char *
|
||||
fdsavedir (int fd)
|
||||
{
|
||||
return savedirstream (fdopendir (fd));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Save the list of files in a directory in a string.
|
||||
|
||||
Copyright 1997, 1999, 2001, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 1999, 2001, 2003, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -14,13 +14,14 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#if !defined SAVEDIR_H_
|
||||
# define SAVEDIR_H_
|
||||
|
||||
char *savedir (const char *dir);
|
||||
char *savedir (char const *dir);
|
||||
char *fdsavedir (int fd);
|
||||
|
||||
#endif
|
||||
|
@ -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 */
|
@ -1,5 +1,5 @@
|
||||
/* Searching in a string.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -13,10 +13,12 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include "strchrnul.h"
|
||||
#include <string.h>
|
||||
|
||||
/* Find the first occurrence of C in S or the final NUL byte. */
|
||||
char *
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* stripslash.c -- remove redundant trailing slashes from a file name
|
||||
Copyright (C) 1990, 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
Copyright (C) 1990, 2001, 2003-2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -13,27 +14,32 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
#include "dirname.h"
|
||||
|
||||
/* Remove trailing slashes from PATH.
|
||||
Return true if a trailing slash was removed.
|
||||
This is useful when using filename completion from a shell that
|
||||
adds a "/" after directory names (such as tcsh and bash), because
|
||||
the Unix rename and rmdir system calls return an "Invalid argument" error
|
||||
when given a path that ends in "/" (except for the root directory). */
|
||||
/* Remove trailing slashes from FILE. Return true if a trailing slash
|
||||
was removed. This is useful when using file name completion from a
|
||||
shell that adds a "/" after directory names (such as tcsh and
|
||||
bash), because on symlinks to directories, several system calls
|
||||
have different semantics according to whether a trailing slash is
|
||||
present. */
|
||||
|
||||
bool
|
||||
strip_trailing_slashes (char *path)
|
||||
strip_trailing_slashes (char *file)
|
||||
{
|
||||
char *base = base_name (path);
|
||||
char *base_lim = base + base_len (base);
|
||||
bool had_slash = (*base_lim != '\0');
|
||||
char *base = last_component (file);
|
||||
char *base_lim;
|
||||
bool had_slash;
|
||||
|
||||
/* last_component returns "" for file system roots, but we need to turn
|
||||
`///' into `/'. */
|
||||
if (! *base)
|
||||
base = file;
|
||||
base_lim = base + base_len (base);
|
||||
had_slash = (*base_lim != '\0');
|
||||
*base_lim = '\0';
|
||||
return had_slash;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Copyright (C) 1996, 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
|
||||
/* A replacement function, for systems that lack strndup.
|
||||
|
||||
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2005, 2006, 2007
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@ -15,31 +15,16 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef HAVE_DECL_STRNLEN
|
||||
"this configure-time declaration test was not run"
|
||||
#endif
|
||||
#if !HAVE_DECL_STRNLEN
|
||||
size_t strnlen ();
|
||||
#endif
|
||||
|
||||
#undef __strndup
|
||||
#undef strndup
|
||||
|
||||
#ifndef weak_alias
|
||||
# define __strndup strndup
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
char *
|
||||
__strndup (const char *s, size_t n)
|
||||
strndup (char const *s, size_t n)
|
||||
{
|
||||
size_t len = strnlen (s, n);
|
||||
char *new = malloc (len + 1);
|
||||
@ -50,6 +35,3 @@ __strndup (const char *s, size_t n)
|
||||
new[len] = '\0';
|
||||
return memcpy (new, s, len);
|
||||
}
|
||||
#ifdef weak_alias
|
||||
weak_alias (__strndup, strndup)
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Find the length of STRING, but scan at most MAXLEN characters.
|
||||
Copyright (C) 1996, 1997, 1998, 2000-2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
Written by Simon Josefsson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -12,37 +12,20 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#undef strnlen
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#undef __strnlen
|
||||
#undef strnlen
|
||||
|
||||
#ifndef _LIBC
|
||||
# define strnlen rpl_strnlen
|
||||
#endif
|
||||
|
||||
#ifndef weak_alias
|
||||
# define __strnlen strnlen
|
||||
#endif
|
||||
|
||||
/* Find the length of STRING, but scan at most MAXLEN characters.
|
||||
If no '\0' terminator is found in that many characters, return MAXLEN. */
|
||||
|
||||
size_t
|
||||
__strnlen (const char *string, size_t maxlen)
|
||||
strnlen (const char *string, size_t maxlen)
|
||||
{
|
||||
const char *end = memchr (string, '\0', maxlen);
|
||||
return end ? (size_t) (end - string) : maxlen;
|
||||
}
|
||||
#ifdef weak_alias
|
||||
weak_alias (__strnlen, strnlen)
|
||||
#endif
|
||||
|
55
lib/system-ioctl.h
Normal file
55
lib/system-ioctl.h
Normal 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
|
99
lib/system.h
99
lib/system.h
@ -1,7 +1,7 @@
|
||||
/* System dependent definitions for GNU tar.
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2004 Free Software Foundation, Inc.
|
||||
2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -15,8 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
@ -109,10 +108,19 @@ extern int errno;
|
||||
#ifndef O_TRUNC
|
||||
# define O_TRUNC 32 /* truncate file on open */
|
||||
#endif
|
||||
/* MS-DOG forever, with my love! */
|
||||
#ifndef O_BINARY
|
||||
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
#ifndef O_DIRECTORY
|
||||
# define O_DIRECTORY 0
|
||||
#endif
|
||||
#ifndef O_NOATIME
|
||||
# define O_NOATIME 0
|
||||
#endif
|
||||
#ifndef O_NONBLOCK
|
||||
# define O_NONBLOCK 0
|
||||
#endif
|
||||
|
||||
/* Declare file status routines and bits. */
|
||||
|
||||
@ -252,9 +260,7 @@ extern int errno;
|
||||
#define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
|
||||
|
||||
/* Include <unistd.h> before any preprocessor test of _POSIX_VERSION. */
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0
|
||||
@ -282,6 +288,9 @@ extern int errno;
|
||||
|
||||
#if MAJOR_IN_MKDEV
|
||||
# include <sys/mkdev.h>
|
||||
# if !defined(makedev) && defined(mkdev)
|
||||
# define makedev(a,b) mkdev((a),(b))
|
||||
# endif
|
||||
# define GOT_MAJOR
|
||||
#endif
|
||||
|
||||
@ -377,45 +386,12 @@ extern int errno;
|
||||
#endif
|
||||
|
||||
#ifndef ST_NBLOCKSIZE
|
||||
#define ST_NBLOCKSIZE 512
|
||||
# define ST_NBLOCKSIZE 512
|
||||
#endif
|
||||
|
||||
/* This is a real challenge to properly get MTIO* symbols :-(. ISC uses
|
||||
<sys/gentape.h>. SCO and BSDi uses <sys/tape.h>; BSDi also requires
|
||||
<sys/tprintf.h> and <sys/device.h> for defining tp_dev and tpr_t. It
|
||||
seems that the rest use <sys/mtio.h>, which itself requires other files,
|
||||
depending on systems. Pyramid defines _IOW in <sgtty.h>, for example. */
|
||||
|
||||
#if HAVE_SYS_GENTAPE_H
|
||||
# include <sys/gentape.h>
|
||||
#else
|
||||
# if HAVE_SYS_TAPE_H
|
||||
# if HAVE_SYS_DEVICE_H
|
||||
# include <sys/device.h>
|
||||
# endif
|
||||
# if HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# if HAVE_SYS_BUF_H
|
||||
# include <sys/buf.h>
|
||||
# endif
|
||||
# if HAVE_SYS_TPRINTF_H
|
||||
# include <sys/tprintf.h>
|
||||
# endif
|
||||
# include <sys/tape.h>
|
||||
# else
|
||||
# if HAVE_SYS_MTIO_H
|
||||
# include <sys/ioctl.h>
|
||||
# if HAVE_SGTTY_H
|
||||
# include <sgtty.h>
|
||||
# endif
|
||||
# if HAVE_SYS_IO_TRIOCTL_H
|
||||
# include <sys/io/trioctl.h>
|
||||
# endif
|
||||
# include <sys/mtio.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#define ST_IS_SPARSE(st) \
|
||||
(ST_NBLOCKS (st) \
|
||||
< ((st).st_size / ST_NBLOCKSIZE + ((st).st_size % ST_NBLOCKSIZE != 0)))
|
||||
|
||||
/* Declare standard functions. */
|
||||
|
||||
@ -435,7 +411,6 @@ char *getenv ();
|
||||
#endif
|
||||
|
||||
#if WITH_DMALLOC
|
||||
# undef HAVE_DECL_VALLOC
|
||||
# define DMALLOC_FUNC_CHECK
|
||||
# include <dmalloc.h>
|
||||
#endif
|
||||
@ -446,28 +421,11 @@ char *getenv ();
|
||||
# define MB_LEN_MAX 1
|
||||
#endif
|
||||
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
|
||||
/* These macros work even on ones'-complement hosts (!).
|
||||
The extra casts work around common compiler bugs. */
|
||||
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
#define TYPE_MINIMUM(t) (TYPE_SIGNED (t) \
|
||||
? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
|
||||
: (t) 0)
|
||||
#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
|
||||
#include <intprops.h>
|
||||
|
||||
/* Bound on length of the string representing an integer value of type t.
|
||||
Subtract one for the sign bit if t is signed;
|
||||
302 / 1000 is log10 (2) rounded up;
|
||||
add one for integer division truncation;
|
||||
add one more for a minus sign if t is signed. */
|
||||
#define INT_STRLEN_BOUND(t) \
|
||||
((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
|
||||
+ 1 + TYPE_SIGNED (t))
|
||||
|
||||
#define UINTMAX_STRSIZE_BOUND (INT_STRLEN_BOUND (uintmax_t) + 1)
|
||||
#define UINTMAX_STRSIZE_BOUND INT_BUFSIZE_BOUND (uintmax_t)
|
||||
|
||||
/* Prototypes for external functions. */
|
||||
|
||||
@ -479,16 +437,9 @@ char *getenv ();
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#if defined(HAVE_SYS_TIME_H) && defined(TIME_WITH_SYS_TIME)
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#if ! HAVE_DECL_TIME
|
||||
time_t time ();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#endif
|
||||
|
||||
/* Library modules. */
|
||||
|
||||
|
3
lib/umaxtostr.c
Normal file
3
lib/umaxtostr.c
Normal file
@ -0,0 +1,3 @@
|
||||
#define inttostr umaxtostr
|
||||
#define inttype uintmax_t
|
||||
#include "inttostr.c"
|
@ -14,12 +14,12 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Jim Meyering. */
|
||||
|
||||
#ifndef UNLOCKED_IO_H
|
||||
#define UNLOCKED_IO_H 1
|
||||
# define UNLOCKED_IO_H 1
|
||||
|
||||
/* These are wrappers for functions/macros from the GNU C library, and
|
||||
from other C libraries supporting POSIX's optional thread-safe functions.
|
||||
@ -32,106 +32,106 @@
|
||||
the *_unlocked functions directly. On hosts that lack those
|
||||
functions, invoke the non-thread-safe versions instead. */
|
||||
|
||||
#include <stdio.h>
|
||||
# include <stdio.h>
|
||||
|
||||
#if HAVE_DECL_CLEARERR_UNLOCKED
|
||||
# undef clearerr
|
||||
# define clearerr(x) clearerr_unlocked (x)
|
||||
#else
|
||||
# define clearerr_unlocked(x) clearerr (x)
|
||||
#endif
|
||||
# if HAVE_DECL_CLEARERR_UNLOCKED
|
||||
# undef clearerr
|
||||
# define clearerr(x) clearerr_unlocked (x)
|
||||
# else
|
||||
# define clearerr_unlocked(x) clearerr (x)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_FEOF_UNLOCKED
|
||||
# undef feof
|
||||
# define feof(x) feof_unlocked (x)
|
||||
#else
|
||||
# define feof_unlocked(x) feof (x)
|
||||
#endif
|
||||
# if HAVE_DECL_FEOF_UNLOCKED
|
||||
# undef feof
|
||||
# define feof(x) feof_unlocked (x)
|
||||
# else
|
||||
# define feof_unlocked(x) feof (x)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_FERROR_UNLOCKED
|
||||
# undef ferror
|
||||
# define ferror(x) ferror_unlocked (x)
|
||||
#else
|
||||
# define ferror_unlocked(x) ferror (x)
|
||||
#endif
|
||||
# if HAVE_DECL_FERROR_UNLOCKED
|
||||
# undef ferror
|
||||
# define ferror(x) ferror_unlocked (x)
|
||||
# else
|
||||
# define ferror_unlocked(x) ferror (x)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_FFLUSH_UNLOCKED
|
||||
# undef fflush
|
||||
# define fflush(x) fflush_unlocked (x)
|
||||
#else
|
||||
# define fflush_unlocked(x) fflush (x)
|
||||
#endif
|
||||
# if HAVE_DECL_FFLUSH_UNLOCKED
|
||||
# undef fflush
|
||||
# define fflush(x) fflush_unlocked (x)
|
||||
# else
|
||||
# define fflush_unlocked(x) fflush (x)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_FGETS_UNLOCKED
|
||||
# undef fgets
|
||||
# define fgets(x,y,z) fgets_unlocked (x,y,z)
|
||||
#else
|
||||
# define fgets_unlocked(x,y,z) fgets (x,y,z)
|
||||
#endif
|
||||
# if HAVE_DECL_FGETS_UNLOCKED
|
||||
# undef fgets
|
||||
# define fgets(x,y,z) fgets_unlocked (x,y,z)
|
||||
# else
|
||||
# define fgets_unlocked(x,y,z) fgets (x,y,z)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_FPUTC_UNLOCKED
|
||||
# undef fputc
|
||||
# define fputc(x,y) fputc_unlocked (x,y)
|
||||
#else
|
||||
# define fputc_unlocked(x,y) fputc (x,y)
|
||||
#endif
|
||||
# if HAVE_DECL_FPUTC_UNLOCKED
|
||||
# undef fputc
|
||||
# define fputc(x,y) fputc_unlocked (x,y)
|
||||
# else
|
||||
# define fputc_unlocked(x,y) fputc (x,y)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_FPUTS_UNLOCKED
|
||||
# undef fputs
|
||||
# define fputs(x,y) fputs_unlocked (x,y)
|
||||
#else
|
||||
# define fputs_unlocked(x,y) fputs (x,y)
|
||||
#endif
|
||||
# if HAVE_DECL_FPUTS_UNLOCKED
|
||||
# undef fputs
|
||||
# define fputs(x,y) fputs_unlocked (x,y)
|
||||
# else
|
||||
# define fputs_unlocked(x,y) fputs (x,y)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_FREAD_UNLOCKED
|
||||
# undef fread
|
||||
# define fread(w,x,y,z) fread_unlocked (w,x,y,z)
|
||||
#else
|
||||
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
|
||||
#endif
|
||||
# if HAVE_DECL_FREAD_UNLOCKED
|
||||
# undef fread
|
||||
# define fread(w,x,y,z) fread_unlocked (w,x,y,z)
|
||||
# else
|
||||
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_FWRITE_UNLOCKED
|
||||
# undef fwrite
|
||||
# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
|
||||
#else
|
||||
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
|
||||
#endif
|
||||
# if HAVE_DECL_FWRITE_UNLOCKED
|
||||
# undef fwrite
|
||||
# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
|
||||
# else
|
||||
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_GETC_UNLOCKED
|
||||
# undef getc
|
||||
# define getc(x) getc_unlocked (x)
|
||||
#else
|
||||
# define getc_unlocked(x) getc (x)
|
||||
#endif
|
||||
# if HAVE_DECL_GETC_UNLOCKED
|
||||
# undef getc
|
||||
# define getc(x) getc_unlocked (x)
|
||||
# else
|
||||
# define getc_unlocked(x) getc (x)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_GETCHAR_UNLOCKED
|
||||
# undef getchar
|
||||
# define getchar() getchar_unlocked ()
|
||||
#else
|
||||
# define getchar_unlocked() getchar ()
|
||||
#endif
|
||||
# if HAVE_DECL_GETCHAR_UNLOCKED
|
||||
# undef getchar
|
||||
# define getchar() getchar_unlocked ()
|
||||
# else
|
||||
# define getchar_unlocked() getchar ()
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_PUTC_UNLOCKED
|
||||
# undef putc
|
||||
# define putc(x,y) putc_unlocked (x,y)
|
||||
#else
|
||||
# define putc_unlocked(x,y) putc (x,y)
|
||||
#endif
|
||||
# if HAVE_DECL_PUTC_UNLOCKED
|
||||
# undef putc
|
||||
# define putc(x,y) putc_unlocked (x,y)
|
||||
# else
|
||||
# define putc_unlocked(x,y) putc (x,y)
|
||||
# endif
|
||||
|
||||
#if HAVE_DECL_PUTCHAR_UNLOCKED
|
||||
# undef putchar
|
||||
# define putchar(x) putchar_unlocked (x)
|
||||
#else
|
||||
# define putchar_unlocked(x) putchar (x)
|
||||
#endif
|
||||
# if HAVE_DECL_PUTCHAR_UNLOCKED
|
||||
# undef putchar
|
||||
# define putchar(x) putchar_unlocked (x)
|
||||
# else
|
||||
# define putchar_unlocked(x) putchar (x)
|
||||
# endif
|
||||
|
||||
#undef flockfile
|
||||
#define flockfile(x) ((void) 0)
|
||||
# undef flockfile
|
||||
# define flockfile(x) ((void) 0)
|
||||
|
||||
#undef ftrylockfile
|
||||
#define ftrylockfile(x) 0
|
||||
# undef ftrylockfile
|
||||
# define ftrylockfile(x) 0
|
||||
|
||||
#undef funlockfile
|
||||
#define funlockfile(x) ((void) 0)
|
||||
# undef funlockfile
|
||||
# define funlockfile(x) ((void) 0)
|
||||
|
||||
#endif /* UNLOCKED_IO_H */
|
||||
|
189
lib/utimens.c
Normal file
189
lib/utimens.c
Normal 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
3
lib/utimens.h
Normal 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]);
|
@ -1,6 +1,6 @@
|
||||
/* Report a memory allocation failure and exit.
|
||||
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004 Free
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2006 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -15,11 +15,9 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
#include "xalloc.h"
|
||||
|
||||
@ -30,7 +28,6 @@
|
||||
|
||||
#include "gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
#define N_(msgid) msgid
|
||||
|
||||
void
|
||||
xalloc_die (void)
|
||||
|
202
lib/xalloc.h
202
lib/xalloc.h
@ -1,7 +1,7 @@
|
||||
/* xalloc.h -- malloc with out-of-memory checking
|
||||
|
||||
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2003, 2004 Free Software Foundation, Inc.
|
||||
1999, 2000, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef XALLOC_H_
|
||||
# define XALLOC_H_
|
||||
@ -46,13 +46,10 @@ extern "C" {
|
||||
extern void xalloc_die (void) ATTRIBUTE_NORETURN;
|
||||
|
||||
void *xmalloc (size_t s);
|
||||
void *xnmalloc (size_t n, size_t s);
|
||||
void *xzalloc (size_t s);
|
||||
void *xcalloc (size_t n, size_t s);
|
||||
void *xrealloc (void *p, size_t s);
|
||||
void *xnrealloc (void *p, size_t n, size_t s);
|
||||
void *x2realloc (void *p, size_t *pn);
|
||||
void *x2nrealloc (void *p, size_t *pn, size_t s);
|
||||
void *xmemdup (void const *p, size_t s);
|
||||
char *xstrdup (char const *str);
|
||||
|
||||
@ -71,8 +68,203 @@ char *xstrdup (char const *str);
|
||||
# define xalloc_oversized(n, s) \
|
||||
((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
|
||||
|
||||
|
||||
/* In the following macros, T must be an elementary or structure/union or
|
||||
typedef'ed type, or a pointer to such a type. To apply one of the
|
||||
following macros to a function pointer or array type, you need to typedef
|
||||
it first and use the typedef name. */
|
||||
|
||||
/* Allocate an object of type T dynamically, with error checking. */
|
||||
/* extern t *XMALLOC (typename t); */
|
||||
# define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
|
||||
|
||||
/* Allocate memory for N elements of type T, with error checking. */
|
||||
/* extern t *XNMALLOC (size_t n, typename t); */
|
||||
# define XNMALLOC(n, t) \
|
||||
((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
|
||||
|
||||
/* Allocate an object of type T dynamically, with error checking,
|
||||
and zero it. */
|
||||
/* extern t *XZALLOC (typename t); */
|
||||
# define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
|
||||
|
||||
/* Allocate memory for N elements of type T, with error checking,
|
||||
and zero it. */
|
||||
/* extern t *XCALLOC (size_t n, typename t); */
|
||||
# define XCALLOC(n, t) \
|
||||
((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
|
||||
|
||||
|
||||
# if HAVE_INLINE
|
||||
# define static_inline static inline
|
||||
# else
|
||||
void *xnmalloc (size_t n, size_t s);
|
||||
void *xnrealloc (void *p, size_t n, size_t s);
|
||||
void *x2nrealloc (void *p, size_t *pn, size_t s);
|
||||
char *xcharalloc (size_t n);
|
||||
# endif
|
||||
|
||||
# ifdef static_inline
|
||||
|
||||
/* Allocate an array of N objects, each with S bytes of memory,
|
||||
dynamically, with error checking. S must be nonzero. */
|
||||
|
||||
static_inline void *
|
||||
xnmalloc (size_t n, size_t s)
|
||||
{
|
||||
if (xalloc_oversized (n, s))
|
||||
xalloc_die ();
|
||||
return xmalloc (n * s);
|
||||
}
|
||||
|
||||
/* Change the size of an allocated block of memory P to an array of N
|
||||
objects each of S bytes, with error checking. S must be nonzero. */
|
||||
|
||||
static_inline void *
|
||||
xnrealloc (void *p, size_t n, size_t s)
|
||||
{
|
||||
if (xalloc_oversized (n, s))
|
||||
xalloc_die ();
|
||||
return xrealloc (p, n * s);
|
||||
}
|
||||
|
||||
/* If P is null, allocate a block of at least *PN such objects;
|
||||
otherwise, reallocate P so that it contains more than *PN objects
|
||||
each of S bytes. *PN must be nonzero unless P is null, and S must
|
||||
be nonzero. Set *PN to the new number of objects, and return the
|
||||
pointer to the new block. *PN is never set to zero, and the
|
||||
returned pointer is never null.
|
||||
|
||||
Repeated reallocations are guaranteed to make progress, either by
|
||||
allocating an initial block with a nonzero size, or by allocating a
|
||||
larger block.
|
||||
|
||||
In the following implementation, nonzero sizes are increased by a
|
||||
factor of approximately 1.5 so that repeated reallocations have
|
||||
O(N) overall cost rather than O(N**2) cost, but the
|
||||
specification for this function does not guarantee that rate.
|
||||
|
||||
Here is an example of use:
|
||||
|
||||
int *p = NULL;
|
||||
size_t used = 0;
|
||||
size_t allocated = 0;
|
||||
|
||||
void
|
||||
append_int (int value)
|
||||
{
|
||||
if (used == allocated)
|
||||
p = x2nrealloc (p, &allocated, sizeof *p);
|
||||
p[used++] = value;
|
||||
}
|
||||
|
||||
This causes x2nrealloc to allocate a block of some nonzero size the
|
||||
first time it is called.
|
||||
|
||||
To have finer-grained control over the initial size, set *PN to a
|
||||
nonzero value before calling this function with P == NULL. For
|
||||
example:
|
||||
|
||||
int *p = NULL;
|
||||
size_t used = 0;
|
||||
size_t allocated = 0;
|
||||
size_t allocated1 = 1000;
|
||||
|
||||
void
|
||||
append_int (int value)
|
||||
{
|
||||
if (used == allocated)
|
||||
{
|
||||
p = x2nrealloc (p, &allocated1, sizeof *p);
|
||||
allocated = allocated1;
|
||||
}
|
||||
p[used++] = value;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
static_inline void *
|
||||
x2nrealloc (void *p, size_t *pn, size_t s)
|
||||
{
|
||||
size_t n = *pn;
|
||||
|
||||
if (! p)
|
||||
{
|
||||
if (! n)
|
||||
{
|
||||
/* The approximate size to use for initial small allocation
|
||||
requests, when the invoking code specifies an old size of
|
||||
zero. 64 bytes is the largest "small" request for the
|
||||
GNU C library malloc. */
|
||||
enum { DEFAULT_MXFAST = 64 };
|
||||
|
||||
n = DEFAULT_MXFAST / s;
|
||||
n += !n;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set N = ceil (1.5 * N) so that progress is made if N == 1.
|
||||
Check for overflow, so that N * S stays in size_t range.
|
||||
The check is slightly conservative, but an exact check isn't
|
||||
worth the trouble. */
|
||||
if ((size_t) -1 / 3 * 2 / s <= n)
|
||||
xalloc_die ();
|
||||
n += (n + 1) / 2;
|
||||
}
|
||||
|
||||
*pn = n;
|
||||
return xrealloc (p, n * s);
|
||||
}
|
||||
|
||||
/* Return a pointer to a new buffer of N bytes. This is like xmalloc,
|
||||
except it returns char *. */
|
||||
|
||||
static_inline char *
|
||||
xcharalloc (size_t n)
|
||||
{
|
||||
return XNMALLOC (n, char);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
|
||||
/* C++ does not allow conversions from void * to other pointer types
|
||||
without a cast. Use templates to work around the problem when
|
||||
possible. */
|
||||
|
||||
template <typename T> inline T *
|
||||
xrealloc (T *p, size_t s)
|
||||
{
|
||||
return (T *) xrealloc ((void *) p, s);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
xnrealloc (T *p, size_t n, size_t s)
|
||||
{
|
||||
return (T *) xnrealloc ((void *) p, n, s);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
x2realloc (T *p, size_t *pn)
|
||||
{
|
||||
return (T *) x2realloc ((void *) p, pn);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
x2nrealloc (T *p, size_t *pn, size_t s)
|
||||
{
|
||||
return (T *) x2nrealloc ((void *) p, pn, s);
|
||||
}
|
||||
|
||||
template <typename T> inline T *
|
||||
xmemdup (T const *p, size_t s)
|
||||
{
|
||||
return (T *) xmemdup ((void const *) p, s);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
|
||||
|
162
lib/xmalloc.c
162
lib/xmalloc.c
@ -1,7 +1,8 @@
|
||||
/* xmalloc.c -- malloc with out of memory checking
|
||||
|
||||
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
1999, 2000, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -15,13 +16,15 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#include <config.h>
|
||||
|
||||
#if ! HAVE_INLINE
|
||||
# define static_inline
|
||||
#endif
|
||||
|
||||
#include "xalloc.h"
|
||||
#undef static_inline
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -30,148 +33,36 @@
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
|
||||
/* Allocate an array of N objects, each with S bytes of memory,
|
||||
dynamically, with error checking. S must be nonzero. */
|
||||
|
||||
static inline void *
|
||||
xnmalloc_inline (size_t n, size_t s)
|
||||
{
|
||||
void *p;
|
||||
if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0))
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
void *
|
||||
xnmalloc (size_t n, size_t s)
|
||||
{
|
||||
return xnmalloc_inline (n, s);
|
||||
}
|
||||
/* 1 if calloc is known to be compatible with GNU calloc. This
|
||||
matters if we are not also using the calloc module, which defines
|
||||
HAVE_CALLOC and supports the GNU API even on non-GNU platforms. */
|
||||
#if defined HAVE_CALLOC || defined __GLIBC__
|
||||
enum { HAVE_GNU_CALLOC = 1 };
|
||||
#else
|
||||
enum { HAVE_GNU_CALLOC = 0 };
|
||||
#endif
|
||||
|
||||
/* Allocate N bytes of memory dynamically, with error checking. */
|
||||
|
||||
void *
|
||||
xmalloc (size_t n)
|
||||
{
|
||||
return xnmalloc_inline (n, 1);
|
||||
}
|
||||
|
||||
/* Change the size of an allocated block of memory P to an array of N
|
||||
objects each of S bytes, with error checking. S must be nonzero. */
|
||||
|
||||
static inline void *
|
||||
xnrealloc_inline (void *p, size_t n, size_t s)
|
||||
{
|
||||
if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0))
|
||||
void *p = malloc (n);
|
||||
if (!p && n != 0)
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
void *
|
||||
xnrealloc (void *p, size_t n, size_t s)
|
||||
{
|
||||
return xnrealloc_inline (p, n, s);
|
||||
}
|
||||
|
||||
/* Change the size of an allocated block of memory P to N bytes,
|
||||
with error checking. */
|
||||
|
||||
void *
|
||||
xrealloc (void *p, size_t n)
|
||||
{
|
||||
return xnrealloc_inline (p, n, 1);
|
||||
}
|
||||
|
||||
|
||||
/* If P is null, allocate a block of at least *PN such objects;
|
||||
otherwise, reallocate P so that it contains more than *PN objects
|
||||
each of S bytes. *PN must be nonzero unless P is null, and S must
|
||||
be nonzero. Set *PN to the new number of objects, and return the
|
||||
pointer to the new block. *PN is never set to zero, and the
|
||||
returned pointer is never null.
|
||||
|
||||
Repeated reallocations are guaranteed to make progress, either by
|
||||
allocating an initial block with a nonzero size, or by allocating a
|
||||
larger block.
|
||||
|
||||
In the following implementation, nonzero sizes are doubled so that
|
||||
repeated reallocations have O(N log N) overall cost rather than
|
||||
O(N**2) cost, but the specification for this function does not
|
||||
guarantee that sizes are doubled.
|
||||
|
||||
Here is an example of use:
|
||||
|
||||
int *p = NULL;
|
||||
size_t used = 0;
|
||||
size_t allocated = 0;
|
||||
|
||||
void
|
||||
append_int (int value)
|
||||
{
|
||||
if (used == allocated)
|
||||
p = x2nrealloc (p, &allocated, sizeof *p);
|
||||
p[used++] = value;
|
||||
}
|
||||
|
||||
This causes x2nrealloc to allocate a block of some nonzero size the
|
||||
first time it is called.
|
||||
|
||||
To have finer-grained control over the initial size, set *PN to a
|
||||
nonzero value before calling this function with P == NULL. For
|
||||
example:
|
||||
|
||||
int *p = NULL;
|
||||
size_t used = 0;
|
||||
size_t allocated = 0;
|
||||
size_t allocated1 = 1000;
|
||||
|
||||
void
|
||||
append_int (int value)
|
||||
{
|
||||
if (used == allocated)
|
||||
{
|
||||
p = x2nrealloc (p, &allocated1, sizeof *p);
|
||||
allocated = allocated1;
|
||||
}
|
||||
p[used++] = value;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
static inline void *
|
||||
x2nrealloc_inline (void *p, size_t *pn, size_t s)
|
||||
{
|
||||
size_t n = *pn;
|
||||
|
||||
if (! p)
|
||||
{
|
||||
if (! n)
|
||||
{
|
||||
/* The approximate size to use for initial small allocation
|
||||
requests, when the invoking code specifies an old size of
|
||||
zero. 64 bytes is the largest "small" request for the
|
||||
GNU C library malloc. */
|
||||
enum { DEFAULT_MXFAST = 64 };
|
||||
|
||||
n = DEFAULT_MXFAST / s;
|
||||
n += !n;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SIZE_MAX / 2 / s < n)
|
||||
xalloc_die ();
|
||||
n *= 2;
|
||||
}
|
||||
|
||||
*pn = n;
|
||||
return xrealloc (p, n * s);
|
||||
}
|
||||
|
||||
void *
|
||||
x2nrealloc (void *p, size_t *pn, size_t s)
|
||||
{
|
||||
return x2nrealloc_inline (p, pn, s);
|
||||
p = realloc (p, n);
|
||||
if (!p && n != 0)
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* If P is null, allocate a block of at least *PN bytes; otherwise,
|
||||
@ -183,7 +74,7 @@ x2nrealloc (void *p, size_t *pn, size_t s)
|
||||
void *
|
||||
x2realloc (void *p, size_t *pn)
|
||||
{
|
||||
return x2nrealloc_inline (p, pn, 1);
|
||||
return x2nrealloc (p, pn, 1);
|
||||
}
|
||||
|
||||
/* Allocate S bytes of zeroed memory dynamically, with error checking.
|
||||
@ -204,8 +95,11 @@ xcalloc (size_t n, size_t s)
|
||||
{
|
||||
void *p;
|
||||
/* Test for overflow, since some calloc implementations don't have
|
||||
proper overflow checks. */
|
||||
if (xalloc_oversized (n, s) || (! (p = calloc (n, s)) && n != 0))
|
||||
proper overflow checks. But omit overflow and size-zero tests if
|
||||
HAVE_GNU_CALLOC, since GNU calloc catches overflow and never
|
||||
returns NULL if successful. */
|
||||
if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s))
|
||||
|| (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Copy memory area and return pointer after last written byte.
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
/* Duplicate a bounded initial segment of a string, with out-of-memory
|
||||
checking.
|
||||
Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -13,24 +14,24 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
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
|
||||
|
||||
/* Get size_t */
|
||||
# include <stddef.h>
|
||||
|
||||
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
|
||||
last written byte. */
|
||||
extern void *mempcpy (void *dest, const void *src, size_t n);
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
/* Return a newly allocated copy of at most N bytes of STRING.
|
||||
In other words, return a copy of the initial segment of length N of
|
||||
STRING. */
|
||||
char *
|
||||
xstrndup (const char *string, size_t n)
|
||||
{
|
||||
char *s = strndup (string, n);
|
||||
if (! s)
|
||||
xalloc_die ();
|
||||
return s;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
/* Duplicate a size-bounded string.
|
||||
/* Duplicate a bounded initial segment of a string, with out-of-memory
|
||||
checking.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -13,18 +14,11 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_STRNDUP
|
||||
|
||||
/* Get strndup() declaration. */
|
||||
#include <string.h>
|
||||
|
||||
#else
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Return a newly allocated copy of at most N bytes of STRING. */
|
||||
extern char *strndup (const char *string, size_t n);
|
||||
|
||||
#endif
|
||||
/* Return a newly allocated copy of at most N bytes of STRING.
|
||||
In other words, return a copy of the initial segment of length N of
|
||||
STRING. */
|
||||
extern char *xstrndup (const char *string, size_t n);
|
439
src/copyin.c
439
src/copyin.c
@ -1,5 +1,6 @@
|
||||
/* copyin.c - extract or list a cpio archive
|
||||
Copyright (C) 1990,1991,1992,2001,2002,2003,2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990,1991,1992,2001,2002,2003,2004,
|
||||
2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +12,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
@ -27,14 +29,14 @@
|
||||
#include "defer.h"
|
||||
#include <rmt.h>
|
||||
#ifndef FNM_PATHNAME
|
||||
#include <fnmatch.h>
|
||||
# include <fnmatch.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LCHOWN
|
||||
#define lchown chown
|
||||
# define lchown(f,u,g) 0
|
||||
#endif
|
||||
|
||||
static void copyin_regular_file(struct new_cpio_header* file_hdr,
|
||||
static void copyin_regular_file(struct cpio_file_stat* file_hdr,
|
||||
int in_file_des);
|
||||
|
||||
void
|
||||
@ -47,7 +49,7 @@ warn_junk_bytes (long bytes_skipped)
|
||||
|
||||
|
||||
static int
|
||||
query_rename(struct new_cpio_header* file_hdr, FILE *tty_in, FILE *tty_out,
|
||||
query_rename(struct cpio_file_stat* file_hdr, FILE *tty_in, FILE *tty_out,
|
||||
FILE *rename_in)
|
||||
{
|
||||
char *str_res; /* Result for string function. */
|
||||
@ -125,7 +127,7 @@ tape_skip_padding (int in_file_des, int offset)
|
||||
|
||||
|
||||
static void
|
||||
list_file(struct new_cpio_header* file_hdr, int in_file_des)
|
||||
list_file(struct cpio_file_stat* file_hdr, int in_file_des)
|
||||
{
|
||||
if (verbose_flag)
|
||||
{
|
||||
@ -176,15 +178,15 @@ list_file(struct new_cpio_header* file_hdr, int in_file_des)
|
||||
#endif
|
||||
if (crc != file_hdr->c_chksum)
|
||||
{
|
||||
error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
|
||||
error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
|
||||
file_hdr->c_name, crc, file_hdr->c_chksum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
try_existing_file(struct new_cpio_header* file_hdr, int in_file_des,
|
||||
int *existing_dir)
|
||||
try_existing_file (struct cpio_file_stat* file_hdr, int in_file_des,
|
||||
int *existing_dir)
|
||||
{
|
||||
struct stat file_stat;
|
||||
|
||||
@ -238,7 +240,7 @@ struct deferment *deferments = NULL;
|
||||
go on one list, although we could optimize this if necessary. */
|
||||
|
||||
static void
|
||||
defer_copyin (struct new_cpio_header *file_hdr)
|
||||
defer_copyin (struct cpio_file_stat *file_hdr)
|
||||
{
|
||||
struct deferment *d;
|
||||
d = create_deferment (file_hdr);
|
||||
@ -252,7 +254,7 @@ defer_copyin (struct new_cpio_header *file_hdr)
|
||||
list and create any which are links to this file. */
|
||||
|
||||
static void
|
||||
create_defered_links (struct new_cpio_header *file_hdr)
|
||||
create_defered_links (struct cpio_file_stat *file_hdr)
|
||||
{
|
||||
struct deferment *d;
|
||||
struct deferment *d_prev;
|
||||
@ -299,7 +301,7 @@ create_defered_links (struct new_cpio_header *file_hdr)
|
||||
then create the other deferred links. */
|
||||
|
||||
static int
|
||||
create_defered_links_to_skipped (struct new_cpio_header *file_hdr,
|
||||
create_defered_links_to_skipped (struct cpio_file_stat *file_hdr,
|
||||
int in_file_des)
|
||||
{
|
||||
struct deferment *d;
|
||||
@ -307,7 +309,6 @@ create_defered_links_to_skipped (struct new_cpio_header *file_hdr,
|
||||
int ino;
|
||||
int maj;
|
||||
int min;
|
||||
int link_res;
|
||||
if (file_hdr->c_filesize == 0)
|
||||
{
|
||||
/* The file doesn't have any data attached to it so we don't have
|
||||
@ -355,10 +356,7 @@ create_final_defers ()
|
||||
struct deferment *d;
|
||||
int link_res;
|
||||
int out_file_des;
|
||||
struct utimbuf times; /* For setting file times. */
|
||||
/* Initialize this in case it has members we don't know to set. */
|
||||
bzero (×, sizeof (struct utimbuf));
|
||||
|
||||
|
||||
for (d = deferments; d != NULL; d = d->next)
|
||||
{
|
||||
/* Debian hack: A line, which could cause an endless loop, was
|
||||
@ -385,34 +383,20 @@ create_final_defers ()
|
||||
}
|
||||
if (out_file_des < 0)
|
||||
{
|
||||
error (0, errno, "%s", d->header.c_name);
|
||||
open_error (d->header.c_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (close (out_file_des) < 0)
|
||||
error (0, errno, "%s", d->header.c_name);
|
||||
set_perms (out_file_des, &d->header);
|
||||
|
||||
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, ×) < 0)
|
||||
error (0, errno, "%s", d->header.c_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
|
||||
copyin_regular_file (struct cpio_file_stat* file_hdr, int in_file_des)
|
||||
{
|
||||
int out_file_des; /* Output file descriptor. */
|
||||
|
||||
@ -460,7 +444,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
|
||||
{
|
||||
tape_toss_input (in_file_des, file_hdr->c_filesize);
|
||||
tape_skip_padding (in_file_des, file_hdr->c_filesize);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (file_hdr->c_nlink > 1
|
||||
@ -509,7 +493,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
|
||||
|
||||
if (out_file_des < 0)
|
||||
{
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
open_error (file_hdr->c_name);
|
||||
tape_toss_input (in_file_des, file_hdr->c_filesize);
|
||||
tape_skip_padding (in_file_des, file_hdr->c_filesize);
|
||||
return;
|
||||
@ -541,7 +525,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
|
||||
if (archive_format == arf_crcascii)
|
||||
{
|
||||
if (crc != file_hdr->c_chksum)
|
||||
error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
|
||||
error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
|
||||
file_hdr->c_name, crc, file_hdr->c_chksum);
|
||||
}
|
||||
tape_skip_padding (in_file_des, file_hdr->c_filesize);
|
||||
@ -557,39 +541,19 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
|
||||
write (out_file_des, "", 1);
|
||||
delayed_seek_count = 0;
|
||||
}
|
||||
|
||||
set_perms (out_file_des, file_hdr);
|
||||
|
||||
if (close (out_file_des) < 0)
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
close_error (file_hdr->c_name);
|
||||
|
||||
if (archive_format == arf_crcascii)
|
||||
{
|
||||
if (crc != file_hdr->c_chksum)
|
||||
error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
|
||||
error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
|
||||
file_hdr->c_name, crc, file_hdr->c_chksum);
|
||||
}
|
||||
|
||||
/* File is now copied; set attributes. */
|
||||
if (!no_chown_flag)
|
||||
if ((chown (file_hdr->c_name,
|
||||
set_owner_flag ? set_owner : file_hdr->c_uid,
|
||||
set_group_flag ? set_group : file_hdr->c_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
|
||||
/* chown may have turned off some permissions we wanted. */
|
||||
if (chmod (file_hdr->c_name, (int) file_hdr->c_mode) < 0)
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
|
||||
if (retain_time_flag)
|
||||
{
|
||||
struct utimbuf times; /* For setting file times. */
|
||||
/* Initialize this in case it has members we don't know to set. */
|
||||
bzero (×, sizeof (struct utimbuf));
|
||||
|
||||
times.actime = times.modtime = file_hdr->c_mtime;
|
||||
if (utime (file_hdr->c_name, ×) < 0)
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
}
|
||||
|
||||
tape_skip_padding (in_file_des, file_hdr->c_filesize);
|
||||
if (file_hdr->c_nlink > 1
|
||||
&& (archive_format == arf_newascii || archive_format == arf_crcascii) )
|
||||
@ -603,7 +567,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
|
||||
}
|
||||
|
||||
static void
|
||||
copyin_directory(struct new_cpio_header* file_hdr, int existing_dir)
|
||||
copyin_directory (struct cpio_file_stat *file_hdr, int existing_dir)
|
||||
{
|
||||
int res; /* Result of various function calls. */
|
||||
#ifdef HPUX_CDF
|
||||
@ -663,43 +627,29 @@ copyin_directory(struct new_cpio_header* file_hdr, int existing_dir)
|
||||
because the directory exists. If that's the case,
|
||||
don't complain about it. */
|
||||
struct stat file_stat;
|
||||
if ( (errno != EEXIST) ||
|
||||
(lstat (file_hdr->c_name, &file_stat) != 0) ||
|
||||
!(S_ISDIR (file_stat.st_mode) ) )
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
mkdir_error (file_hdr->c_name);
|
||||
return;
|
||||
}
|
||||
if (lstat (file_hdr->c_name, &file_stat))
|
||||
{
|
||||
stat_error (file_hdr->c_name);
|
||||
return;
|
||||
}
|
||||
if (!(S_ISDIR (file_stat.st_mode)))
|
||||
{
|
||||
error (0, 0, _("%s is not a directory"),
|
||||
quotearg_colon (file_hdr->c_name));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!no_chown_flag)
|
||||
if ((chown (file_hdr->c_name,
|
||||
set_owner_flag ? set_owner : file_hdr->c_uid,
|
||||
set_group_flag ? set_group : file_hdr->c_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
/* chown may have turned off some permissions we wanted. */
|
||||
if (chmod (file_hdr->c_name, (int) file_hdr->c_mode) < 0)
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
#ifdef HPUX_CDF
|
||||
if (cdf_flag)
|
||||
/* Once we "hide" the directory with the chmod(),
|
||||
we have to refer to it using name+ instead of name. */
|
||||
file_hdr->c_name [cdf_char] = '+';
|
||||
#endif
|
||||
if (retain_time_flag)
|
||||
{
|
||||
struct utimbuf times; /* For setting file times. */
|
||||
/* Initialize this in case it has members we don't know to set. */
|
||||
bzero (×, sizeof (struct utimbuf));
|
||||
|
||||
times.actime = times.modtime = file_hdr->c_mtime;
|
||||
if (utime (file_hdr->c_name, ×) < 0)
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
}
|
||||
set_perms (-1, file_hdr);
|
||||
}
|
||||
|
||||
static void
|
||||
copyin_device(struct new_cpio_header* file_hdr)
|
||||
copyin_device (struct cpio_file_stat* file_hdr)
|
||||
{
|
||||
int res; /* Result of various function calls. */
|
||||
|
||||
@ -752,32 +702,27 @@ copyin_device(struct new_cpio_header* file_hdr)
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
mknod_error (file_hdr->c_name);
|
||||
return;
|
||||
}
|
||||
if (!no_chown_flag)
|
||||
if ((chown (file_hdr->c_name,
|
||||
set_owner_flag ? set_owner : file_hdr->c_uid,
|
||||
set_group_flag ? set_group : file_hdr->c_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
{
|
||||
uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid;
|
||||
gid_t gid = set_group_flag ? set_group : file_hdr->c_gid;
|
||||
if ((chown (file_hdr->c_name, uid, gid) < 0)
|
||||
&& errno != EPERM)
|
||||
chown_error_details (file_hdr->c_name, uid, gid);
|
||||
}
|
||||
/* chown may have turned off some permissions we wanted. */
|
||||
if (chmod (file_hdr->c_name, file_hdr->c_mode) < 0)
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
chmod_error_details (file_hdr->c_name, file_hdr->c_mode);
|
||||
if (retain_time_flag)
|
||||
{
|
||||
struct utimbuf times; /* For setting file times. */
|
||||
/* Initialize this in case it has members we don't know to set. */
|
||||
bzero (×, sizeof (struct utimbuf));
|
||||
|
||||
times.actime = times.modtime = file_hdr->c_mtime;
|
||||
if (utime (file_hdr->c_name, ×) < 0)
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
}
|
||||
set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime,
|
||||
file_hdr->c_mtime);
|
||||
}
|
||||
|
||||
static void
|
||||
copyin_link(struct new_cpio_header *file_hdr, int in_file_des)
|
||||
copyin_link(struct cpio_file_stat *file_hdr, int in_file_des)
|
||||
{
|
||||
char *link_name = NULL; /* Name of hard and symbolic links. */
|
||||
int res; /* Result of various function calls. */
|
||||
@ -807,23 +752,24 @@ copyin_link(struct new_cpio_header *file_hdr, int in_file_des)
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
error (0, errno, _("%s: Cannot symlink to %s"),
|
||||
quotearg_colon (link_name), quote_n (1, file_hdr->c_name));
|
||||
free (link_name);
|
||||
return;
|
||||
}
|
||||
if (!no_chown_flag)
|
||||
if ((lchown (file_hdr->c_name,
|
||||
set_owner_flag ? set_owner : file_hdr->c_uid,
|
||||
set_group_flag ? set_group : file_hdr->c_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
{
|
||||
error (0, errno, "%s", file_hdr->c_name);
|
||||
}
|
||||
{
|
||||
uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid;
|
||||
gid_t gid = set_group_flag ? set_group : file_hdr->c_gid;
|
||||
if ((lchown (file_hdr->c_name, uid, gid) < 0)
|
||||
&& errno != EPERM)
|
||||
chown_error_details (file_hdr->c_name, uid, gid);
|
||||
}
|
||||
free (link_name);
|
||||
}
|
||||
|
||||
static void
|
||||
copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
|
||||
copyin_file (struct cpio_file_stat* file_hdr, int in_file_des)
|
||||
{
|
||||
int existing_dir;
|
||||
|
||||
@ -835,11 +781,11 @@ copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
|
||||
switch (file_hdr->c_mode & CP_IFMT)
|
||||
{
|
||||
case CP_IFREG:
|
||||
copyin_regular_file(file_hdr, in_file_des);
|
||||
copyin_regular_file (file_hdr, in_file_des);
|
||||
break;
|
||||
|
||||
case CP_IFDIR:
|
||||
copyin_directory(file_hdr, existing_dir);
|
||||
copyin_directory (file_hdr, existing_dir);
|
||||
break;
|
||||
|
||||
case CP_IFCHR:
|
||||
@ -850,12 +796,12 @@ copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
|
||||
#ifdef CP_IFIFO
|
||||
case CP_IFIFO:
|
||||
#endif
|
||||
copyin_device(file_hdr);
|
||||
copyin_device (file_hdr);
|
||||
break;
|
||||
|
||||
#ifdef CP_IFLNK
|
||||
case CP_IFLNK:
|
||||
copyin_link(file_hdr, in_file_des);
|
||||
copyin_link (file_hdr, in_file_des);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -876,7 +822,7 @@ static time_t current_time;
|
||||
this file is a symbolic link to. */
|
||||
|
||||
void
|
||||
long_format (struct new_cpio_header *file_hdr, char *link_name)
|
||||
long_format (struct cpio_file_stat *file_hdr, char *link_name)
|
||||
{
|
||||
char mbuf[11];
|
||||
char tbuf[40];
|
||||
@ -897,7 +843,7 @@ long_format (struct new_cpio_header *file_hdr, char *link_name)
|
||||
}
|
||||
tbuf[16] = '\0';
|
||||
|
||||
printf ("%s %3u ", mbuf, file_hdr->c_nlink);
|
||||
printf ("%s %3lu ", mbuf, file_hdr->c_nlink);
|
||||
|
||||
if (numeric_uid)
|
||||
printf ("%-8u %-8u ", (unsigned int) file_hdr->c_uid,
|
||||
@ -908,10 +854,10 @@ long_format (struct new_cpio_header *file_hdr, char *link_name)
|
||||
|
||||
if ((file_hdr->c_mode & CP_IFMT) == CP_IFCHR
|
||||
|| (file_hdr->c_mode & CP_IFMT) == CP_IFBLK)
|
||||
printf ("%3u, %3u ", file_hdr->c_rdev_maj,
|
||||
printf ("%3lu, %3lu ", file_hdr->c_rdev_maj,
|
||||
file_hdr->c_rdev_min);
|
||||
else
|
||||
printf ("%8lu ", file_hdr->c_filesize);
|
||||
printf ("%8"PRIuMAX" ", (uintmax_t) file_hdr->c_filesize);
|
||||
|
||||
printf ("%s ", tbuf + 4);
|
||||
|
||||
@ -997,7 +943,7 @@ read_pattern_file ()
|
||||
|
||||
pattern_fp = fopen (pattern_file_name, "r");
|
||||
if (pattern_fp == NULL)
|
||||
error (1, errno, "%s", pattern_file_name);
|
||||
open_error (pattern_file_name);
|
||||
while (ds_fgetstr (pattern_fp, &pattern_name, '\n') != NULL)
|
||||
{
|
||||
if (new_num_patterns >= max_new_patterns)
|
||||
@ -1011,7 +957,7 @@ read_pattern_file ()
|
||||
++new_num_patterns;
|
||||
}
|
||||
if (ferror (pattern_fp) || fclose (pattern_fp) == EOF)
|
||||
error (1, errno, "%s", pattern_file_name);
|
||||
close_error (pattern_file_name);
|
||||
|
||||
for (i = 0; i < num_patterns; ++i)
|
||||
new_save_patterns[i] = save_patterns[i];
|
||||
@ -1020,6 +966,52 @@ read_pattern_file ()
|
||||
num_patterns = new_num_patterns;
|
||||
}
|
||||
|
||||
|
||||
uintmax_t
|
||||
from_ascii (char const *where, size_t digs, unsigned logbase)
|
||||
{
|
||||
uintmax_t value = 0;
|
||||
char const *buf = where;
|
||||
char const *end = buf + digs;
|
||||
int overflow = 0;
|
||||
static char codetab[] = "0123456789ABCDEF";
|
||||
|
||||
for (; *buf == ' '; buf++)
|
||||
{
|
||||
if (buf == end)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (buf == end || *buf == 0)
|
||||
return 0;
|
||||
while (1)
|
||||
{
|
||||
unsigned d;
|
||||
|
||||
char *p = strchr (codetab, toupper (*buf));
|
||||
if (!p)
|
||||
{
|
||||
error (0, 0, _("Malformed number %.*s"), digs, where);
|
||||
break;
|
||||
}
|
||||
|
||||
d = p - codetab;
|
||||
if ((d >> logbase) > 1)
|
||||
{
|
||||
error (0, 0, _("Malformed number %.*s"), digs, where);
|
||||
break;
|
||||
}
|
||||
value += d;
|
||||
if (++buf == end || *buf == 0)
|
||||
break;
|
||||
overflow |= value ^ (value << logbase >> logbase);
|
||||
value <<= logbase;
|
||||
}
|
||||
if (overflow)
|
||||
error (0, 0, _("Archive value %.*s is out of range"),
|
||||
digs, where);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1030,8 +1022,13 @@ read_pattern_file ()
|
||||
descriptor IN_DES into FILE_HDR. */
|
||||
|
||||
void
|
||||
read_in_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
read_in_header (struct cpio_file_stat *file_hdr, int in_des)
|
||||
{
|
||||
union {
|
||||
char str[6];
|
||||
unsigned short num;
|
||||
struct old_cpio_header old_header;
|
||||
} magic;
|
||||
long bytes_skipped = 0; /* Bytes of junk found before magic number. */
|
||||
|
||||
/* Search for a valid magic number. */
|
||||
@ -1090,52 +1087,53 @@ read_in_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
|
||||
file_hdr->c_tar_linkname = NULL;
|
||||
|
||||
tape_buffered_read ((char *) file_hdr, in_des, 6L);
|
||||
tape_buffered_read (magic.str, in_des, 6L);
|
||||
while (1)
|
||||
{
|
||||
if (append_flag)
|
||||
last_header_start = input_bytes - io_block_size
|
||||
+ (in_buff - input_buffer) - 6;
|
||||
if (archive_format == arf_newascii
|
||||
&& !strncmp ((char *) file_hdr, "070701", 6))
|
||||
&& !strncmp (magic.str, "070701", 6))
|
||||
{
|
||||
if (bytes_skipped > 0)
|
||||
warn_junk_bytes (bytes_skipped);
|
||||
file_hdr->c_magic = 070701;
|
||||
read_in_new_ascii (file_hdr, in_des);
|
||||
break;
|
||||
}
|
||||
if (archive_format == arf_crcascii
|
||||
&& !strncmp ((char *) file_hdr, "070702", 6))
|
||||
&& !strncmp (magic.str, "070702", 6))
|
||||
{
|
||||
if (bytes_skipped > 0)
|
||||
warn_junk_bytes (bytes_skipped);
|
||||
|
||||
file_hdr->c_magic = 070702;
|
||||
read_in_new_ascii (file_hdr, in_des);
|
||||
break;
|
||||
}
|
||||
if ( (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
|
||||
&& !strncmp ((char *) file_hdr, "070707", 6))
|
||||
&& !strncmp (magic.str, "070707", 6))
|
||||
{
|
||||
if (bytes_skipped > 0)
|
||||
warn_junk_bytes (bytes_skipped);
|
||||
|
||||
file_hdr->c_magic = 070707;
|
||||
read_in_old_ascii (file_hdr, in_des);
|
||||
break;
|
||||
}
|
||||
if ( (archive_format == arf_binary || archive_format == arf_hpbinary)
|
||||
&& (file_hdr->c_magic == 070707
|
||||
|| file_hdr->c_magic == swab_short ((unsigned short) 070707)))
|
||||
&& (magic.num == 070707
|
||||
|| magic.num == swab_short ((unsigned short) 070707)))
|
||||
{
|
||||
/* Having to skip 1 byte because of word alignment is normal. */
|
||||
if (bytes_skipped > 0)
|
||||
warn_junk_bytes (bytes_skipped);
|
||||
|
||||
read_in_binary (file_hdr, in_des);
|
||||
file_hdr->c_magic = 070707;
|
||||
read_in_binary (file_hdr, &magic.old_header, in_des);
|
||||
break;
|
||||
}
|
||||
bytes_skipped++;
|
||||
bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5);
|
||||
tape_buffered_read ((char *) file_hdr + 5, in_des, 1L);
|
||||
memmove (magic.str, magic.str + 1, 5);
|
||||
tape_buffered_read (magic.str, in_des, 1L);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1144,25 +1142,30 @@ read_in_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
already filled in. */
|
||||
|
||||
void
|
||||
read_in_old_ascii (struct new_cpio_header *file_hdr, int in_des)
|
||||
read_in_old_ascii (struct cpio_file_stat *file_hdr, int in_des)
|
||||
{
|
||||
char ascii_header[78];
|
||||
struct old_ascii_header ascii_header;
|
||||
unsigned long dev;
|
||||
unsigned long rdev;
|
||||
|
||||
tape_buffered_read (ascii_header, in_des, 70L);
|
||||
ascii_header[70] = '\0';
|
||||
sscanf (ascii_header,
|
||||
"%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo",
|
||||
&dev, &file_hdr->c_ino,
|
||||
&file_hdr->c_mode, &file_hdr->c_uid, &file_hdr->c_gid,
|
||||
&file_hdr->c_nlink, &rdev, &file_hdr->c_mtime,
|
||||
&file_hdr->c_namesize, &file_hdr->c_filesize);
|
||||
tape_buffered_read (ascii_header.c_dev, in_des,
|
||||
sizeof ascii_header - sizeof ascii_header.c_magic);
|
||||
dev = FROM_OCTAL (ascii_header.c_dev);
|
||||
file_hdr->c_dev_maj = major (dev);
|
||||
file_hdr->c_dev_min = minor (dev);
|
||||
file_hdr->c_rdev_maj = major (rdev);
|
||||
file_hdr->c_rdev_min = minor (rdev);
|
||||
|
||||
file_hdr->c_ino = FROM_OCTAL (ascii_header.c_ino);
|
||||
file_hdr->c_mode = FROM_OCTAL (ascii_header.c_mode);
|
||||
file_hdr->c_uid = FROM_OCTAL (ascii_header.c_uid);
|
||||
file_hdr->c_gid = FROM_OCTAL (ascii_header.c_gid);
|
||||
file_hdr->c_nlink = FROM_OCTAL (ascii_header.c_nlink);
|
||||
dev = FROM_OCTAL (ascii_header.c_rdev);
|
||||
file_hdr->c_rdev_maj = major (dev);
|
||||
file_hdr->c_rdev_min = minor (dev);
|
||||
|
||||
file_hdr->c_mtime = FROM_OCTAL (ascii_header.c_mtime);
|
||||
file_hdr->c_namesize = FROM_OCTAL (ascii_header.c_namesize);
|
||||
file_hdr->c_filesize = FROM_OCTAL (ascii_header.c_filesize);
|
||||
|
||||
/* Read file name from input. */
|
||||
if (file_hdr->c_name != NULL)
|
||||
free (file_hdr->c_name);
|
||||
@ -1204,19 +1207,27 @@ read_in_old_ascii (struct new_cpio_header *file_hdr, int in_des)
|
||||
already filled in. */
|
||||
|
||||
void
|
||||
read_in_new_ascii (struct new_cpio_header *file_hdr, int in_des)
|
||||
read_in_new_ascii (struct cpio_file_stat *file_hdr, int in_des)
|
||||
{
|
||||
char ascii_header[112];
|
||||
struct new_ascii_header ascii_header;
|
||||
|
||||
tape_buffered_read (ascii_header, in_des, 104L);
|
||||
ascii_header[104] = '\0';
|
||||
sscanf (ascii_header,
|
||||
"%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
|
||||
&file_hdr->c_ino, &file_hdr->c_mode, &file_hdr->c_uid,
|
||||
&file_hdr->c_gid, &file_hdr->c_nlink, &file_hdr->c_mtime,
|
||||
&file_hdr->c_filesize, &file_hdr->c_dev_maj, &file_hdr->c_dev_min,
|
||||
&file_hdr->c_rdev_maj, &file_hdr->c_rdev_min, &file_hdr->c_namesize,
|
||||
&file_hdr->c_chksum);
|
||||
tape_buffered_read (ascii_header.c_ino, in_des,
|
||||
sizeof ascii_header - sizeof ascii_header.c_magic);
|
||||
|
||||
file_hdr->c_ino = FROM_HEX (ascii_header.c_ino);
|
||||
file_hdr->c_mode = FROM_HEX (ascii_header.c_mode);
|
||||
file_hdr->c_uid = FROM_HEX (ascii_header.c_uid);
|
||||
file_hdr->c_gid = FROM_HEX (ascii_header.c_gid);
|
||||
file_hdr->c_nlink = FROM_HEX (ascii_header.c_nlink);
|
||||
file_hdr->c_mtime = FROM_HEX (ascii_header.c_mtime);
|
||||
file_hdr->c_filesize = FROM_HEX (ascii_header.c_filesize);
|
||||
file_hdr->c_dev_maj = FROM_HEX (ascii_header.c_dev_maj);
|
||||
file_hdr->c_dev_min = FROM_HEX (ascii_header.c_dev_min);
|
||||
file_hdr->c_rdev_maj = FROM_HEX (ascii_header.c_rdev_maj);
|
||||
file_hdr->c_rdev_min = FROM_HEX (ascii_header.c_rdev_min);
|
||||
file_hdr->c_namesize = FROM_HEX (ascii_header.c_namesize);
|
||||
file_hdr->c_chksum = FROM_HEX (ascii_header.c_chksum);
|
||||
|
||||
/* Read file name from input. */
|
||||
if (file_hdr->c_name != NULL)
|
||||
free (file_hdr->c_name);
|
||||
@ -1234,15 +1245,14 @@ read_in_new_ascii (struct new_cpio_header *file_hdr, int in_des)
|
||||
number, device, and inode number), which are already filled in. */
|
||||
|
||||
void
|
||||
read_in_binary (struct new_cpio_header *file_hdr, int in_des)
|
||||
read_in_binary (struct cpio_file_stat *file_hdr,
|
||||
struct old_cpio_header *short_hdr,
|
||||
int in_des)
|
||||
{
|
||||
struct old_cpio_header short_hdr;
|
||||
file_hdr->c_magic = short_hdr->c_magic;
|
||||
|
||||
/* Copy the data into the short header, then later transfer
|
||||
it into the argument long header. */
|
||||
short_hdr.c_dev = ((struct old_cpio_header *) file_hdr)->c_dev;
|
||||
short_hdr.c_ino = ((struct old_cpio_header *) file_hdr)->c_ino;
|
||||
tape_buffered_read (((char *) &short_hdr) + 6, in_des, 20L);
|
||||
tape_buffered_read (((char *) short_hdr) + 6, in_des,
|
||||
sizeof *short_hdr - 6 /* = 20 */);
|
||||
|
||||
/* If the magic number is byte swapped, fix the header. */
|
||||
if (file_hdr->c_magic == swab_short ((unsigned short) 070707))
|
||||
@ -1259,21 +1269,21 @@ read_in_binary (struct new_cpio_header *file_hdr, int in_des)
|
||||
swab_array ((char *) &short_hdr, 13);
|
||||
}
|
||||
|
||||
file_hdr->c_dev_maj = major (short_hdr.c_dev);
|
||||
file_hdr->c_dev_min = minor (short_hdr.c_dev);
|
||||
file_hdr->c_ino = short_hdr.c_ino;
|
||||
file_hdr->c_mode = short_hdr.c_mode;
|
||||
file_hdr->c_uid = short_hdr.c_uid;
|
||||
file_hdr->c_gid = short_hdr.c_gid;
|
||||
file_hdr->c_nlink = short_hdr.c_nlink;
|
||||
file_hdr->c_rdev_maj = major (short_hdr.c_rdev);
|
||||
file_hdr->c_rdev_min = minor (short_hdr.c_rdev);
|
||||
file_hdr->c_mtime = (unsigned long) short_hdr.c_mtimes[0] << 16
|
||||
| short_hdr.c_mtimes[1];
|
||||
file_hdr->c_dev_maj = major (short_hdr->c_dev);
|
||||
file_hdr->c_dev_min = minor (short_hdr->c_dev);
|
||||
file_hdr->c_ino = short_hdr->c_ino;
|
||||
file_hdr->c_mode = short_hdr->c_mode;
|
||||
file_hdr->c_uid = short_hdr->c_uid;
|
||||
file_hdr->c_gid = short_hdr->c_gid;
|
||||
file_hdr->c_nlink = short_hdr->c_nlink;
|
||||
file_hdr->c_rdev_maj = major (short_hdr->c_rdev);
|
||||
file_hdr->c_rdev_min = minor (short_hdr->c_rdev);
|
||||
file_hdr->c_mtime = (unsigned long) short_hdr->c_mtimes[0] << 16
|
||||
| short_hdr->c_mtimes[1];
|
||||
|
||||
file_hdr->c_namesize = short_hdr.c_namesize;
|
||||
file_hdr->c_filesize = (unsigned long) short_hdr.c_filesizes[0] << 16
|
||||
| short_hdr.c_filesizes[1];
|
||||
file_hdr->c_namesize = short_hdr->c_namesize;
|
||||
file_hdr->c_filesize = (unsigned long) short_hdr->c_filesizes[0] << 16
|
||||
| short_hdr->c_filesizes[1];
|
||||
|
||||
/* Read file name from input. */
|
||||
if (file_hdr->c_name != NULL)
|
||||
@ -1342,15 +1352,18 @@ void
|
||||
process_copy_in ()
|
||||
{
|
||||
char done = false; /* True if trailer reached. */
|
||||
FILE *tty_in; /* Interactive file for rename option. */
|
||||
FILE *tty_out; /* Interactive file for rename option. */
|
||||
FILE *rename_in; /* Batch file for rename option. */
|
||||
FILE *tty_in = NULL; /* Interactive file for rename option. */
|
||||
FILE *tty_out = NULL; /* Interactive file for rename option. */
|
||||
FILE *rename_in = NULL; /* Batch file for rename option. */
|
||||
struct stat file_stat; /* Output file stat record. */
|
||||
struct new_cpio_header file_hdr; /* Output header information. */
|
||||
struct cpio_file_stat file_hdr; /* Output header information. */
|
||||
int in_file_des; /* Input file descriptor. */
|
||||
char skip_file; /* Flag for use with patterns. */
|
||||
int i; /* Loop index variable. */
|
||||
|
||||
umask (0); /* Reset umask to preserve modes of
|
||||
created files */
|
||||
|
||||
/* Initialize the copy in. */
|
||||
if (pattern_file_name)
|
||||
{
|
||||
@ -1418,7 +1431,7 @@ process_copy_in ()
|
||||
#ifdef DEBUG_CPIO
|
||||
if (debug_flag)
|
||||
{
|
||||
struct new_cpio_header *h;
|
||||
struct cpio_file_stat *h;
|
||||
h = &file_hdr;
|
||||
fprintf (stderr,
|
||||
"magic = 0%o, ino = %d, mode = 0%o, uid = %d, gid = %d\n",
|
||||
@ -1437,37 +1450,15 @@ process_copy_in ()
|
||||
}
|
||||
#endif
|
||||
/* Is this the header for the TRAILER file? */
|
||||
if (strcmp ("TRAILER!!!", file_hdr.c_name) == 0)
|
||||
if (strcmp (CPIO_TRAILER_NAME, file_hdr.c_name) == 0)
|
||||
{
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Do we have to ignore absolute paths, and if so, does the filename
|
||||
have an absolute path? */
|
||||
if (no_abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0] == '/')
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = file_hdr.c_name;
|
||||
while (*p == '/')
|
||||
++p;
|
||||
if (*p == '\0')
|
||||
{
|
||||
strcpy (file_hdr.c_name, ".");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Debian hack: file_hrd.c_name is sometimes set to
|
||||
point to static memory by code in tar.c. This
|
||||
causes a segfault. Therefore, memmove is used
|
||||
instead of freeing and reallocating. (Reported by
|
||||
Horst Knobloch.) This bug has been reported to
|
||||
"bug-gnu-utils@prep.ai.mit.edu". (99/1/6) -BEM */
|
||||
(void)memmove (file_hdr.c_name, p, (size_t)(strlen (p) + 1));
|
||||
}
|
||||
}
|
||||
|
||||
cpio_safer_name_suffix (file_hdr.c_name, false, !no_abs_paths_flag,
|
||||
false);
|
||||
|
||||
/* Does the file name match one of the given patterns? */
|
||||
if (num_patterns <= 0)
|
||||
skip_file = false;
|
||||
@ -1530,7 +1521,7 @@ process_copy_in ()
|
||||
tape_skip_padding (in_file_des, file_hdr.c_filesize);
|
||||
if (crc != file_hdr.c_chksum)
|
||||
{
|
||||
error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
|
||||
error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
|
||||
file_hdr.c_name, crc, file_hdr.c_chksum);
|
||||
}
|
||||
/* Debian hack: -v and -V now work with --only-verify-crc.
|
||||
|
672
src/copyout.c
672
src/copyout.c
@ -1,5 +1,6 @@
|
||||
/* copyout.c - create a cpio archive
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +12,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
@ -26,14 +28,15 @@
|
||||
#include "extern.h"
|
||||
#include "defer.h"
|
||||
#include <rmt.h>
|
||||
#include <paxlib.h>
|
||||
|
||||
/* Read FILE_SIZE bytes of FILE_NAME from IN_FILE_DES and
|
||||
compute and return a checksum for them. */
|
||||
|
||||
static unsigned long
|
||||
static unsigned int
|
||||
read_for_checksum (int in_file_des, int file_size, char *file_name)
|
||||
{
|
||||
unsigned long crc;
|
||||
unsigned int crc;
|
||||
char buf[BUFSIZ];
|
||||
int bytes_left;
|
||||
int bytes_read;
|
||||
@ -65,13 +68,8 @@ read_for_checksum (int in_file_des, int file_size, char *file_name)
|
||||
static void
|
||||
tape_clear_rest_of_block (int out_file_des)
|
||||
{
|
||||
while (output_size < io_block_size)
|
||||
{
|
||||
if ((io_block_size - output_size) > 512)
|
||||
tape_buffered_write (zeros_512, out_file_des, 512);
|
||||
else
|
||||
tape_buffered_write (zeros_512, out_file_des, io_block_size - output_size);
|
||||
}
|
||||
write_nuls_to_file (io_block_size - output_size, out_file_des,
|
||||
tape_buffered_write);
|
||||
}
|
||||
|
||||
/* Write NULs on OUT_FILE_DES to move from OFFSET (the current location)
|
||||
@ -80,7 +78,7 @@ tape_clear_rest_of_block (int out_file_des)
|
||||
static void
|
||||
tape_pad_output (int out_file_des, int offset)
|
||||
{
|
||||
int pad;
|
||||
size_t pad;
|
||||
|
||||
if (archive_format == arf_newascii || archive_format == arf_crcascii)
|
||||
pad = (4 - (offset % 4)) % 4;
|
||||
@ -92,7 +90,7 @@ tape_pad_output (int out_file_des, int offset)
|
||||
pad = 0;
|
||||
|
||||
if (pad != 0)
|
||||
tape_buffered_write (zeros_512, out_file_des, pad);
|
||||
write_nuls_to_file (pad, out_file_des, tape_buffered_write);
|
||||
}
|
||||
|
||||
|
||||
@ -109,7 +107,7 @@ struct deferment *deferouts = NULL;
|
||||
already been defered. */
|
||||
|
||||
static int
|
||||
count_defered_links_to_dev_ino (struct new_cpio_header *file_hdr)
|
||||
count_defered_links_to_dev_ino (struct cpio_file_stat *file_hdr)
|
||||
{
|
||||
struct deferment *d;
|
||||
int ino;
|
||||
@ -133,7 +131,7 @@ count_defered_links_to_dev_ino (struct new_cpio_header *file_hdr)
|
||||
we already seen and defered all of the other links? */
|
||||
|
||||
static int
|
||||
last_link (struct new_cpio_header *file_hdr)
|
||||
last_link (struct cpio_file_stat *file_hdr)
|
||||
{
|
||||
int other_files_sofar;
|
||||
|
||||
@ -150,7 +148,7 @@ last_link (struct new_cpio_header *file_hdr)
|
||||
list. */
|
||||
|
||||
static void
|
||||
add_link_defer (struct new_cpio_header *file_hdr)
|
||||
add_link_defer (struct cpio_file_stat *file_hdr)
|
||||
{
|
||||
struct deferment *d;
|
||||
d = create_deferment (file_hdr);
|
||||
@ -159,13 +157,13 @@ add_link_defer (struct new_cpio_header *file_hdr)
|
||||
}
|
||||
|
||||
/* We are about to put a file into a newc or crc archive that is
|
||||
multiply linked. We have already seen and defered all of the
|
||||
multiply linked. We have already seen and deferred all of the
|
||||
other links to the file but haven't written them into the archive.
|
||||
Write the other links into the archive, and remove them from the
|
||||
deferouts list. */
|
||||
|
||||
static void
|
||||
writeout_other_defers (struct new_cpio_header *file_hdr, int out_des)
|
||||
writeout_other_defers (struct cpio_file_stat *file_hdr, int out_des)
|
||||
{
|
||||
struct deferment *d;
|
||||
struct deferment *d_prev;
|
||||
@ -207,13 +205,10 @@ writeout_other_defers (struct new_cpio_header *file_hdr, int out_des)
|
||||
for writeout_final_defers() to call. */
|
||||
|
||||
static void
|
||||
writeout_defered_file (struct new_cpio_header *header, int out_file_des)
|
||||
writeout_defered_file (struct cpio_file_stat *header, int out_file_des)
|
||||
{
|
||||
int in_file_des;
|
||||
struct new_cpio_header file_hdr;
|
||||
struct utimbuf times; /* For setting file times. */
|
||||
/* Initialize this in case it has members we don't know to set. */
|
||||
bzero (×, sizeof (struct utimbuf));
|
||||
struct cpio_file_stat file_hdr;
|
||||
|
||||
file_hdr = *header;
|
||||
|
||||
@ -222,7 +217,7 @@ writeout_defered_file (struct new_cpio_header *header, int out_file_des)
|
||||
O_RDONLY | O_BINARY, 0);
|
||||
if (in_file_des < 0)
|
||||
{
|
||||
error (0, errno, "%s", header->c_name);
|
||||
open_error (header->c_name);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -231,8 +226,10 @@ writeout_defered_file (struct new_cpio_header *header, int out_file_des)
|
||||
file_hdr.c_filesize,
|
||||
header->c_name);
|
||||
|
||||
write_out_header (&file_hdr, out_file_des);
|
||||
copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize, header->c_name);
|
||||
if (write_out_header (&file_hdr, out_file_des))
|
||||
return;
|
||||
copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize,
|
||||
header->c_name);
|
||||
warn_if_file_changed(header->c_name, file_hdr.c_filesize, file_hdr.c_mtime);
|
||||
|
||||
if (archive_format == arf_tar || archive_format == arf_ustar)
|
||||
@ -241,21 +238,11 @@ writeout_defered_file (struct new_cpio_header *header, int out_file_des)
|
||||
|
||||
tape_pad_output (out_file_des, file_hdr.c_filesize);
|
||||
|
||||
if (close (in_file_des) < 0)
|
||||
error (0, errno, "%s", header->c_name);
|
||||
if (reset_time_flag)
|
||||
{
|
||||
times.actime = file_hdr.c_mtime;
|
||||
times.modtime = file_hdr.c_mtime;
|
||||
/* Debian hack: Silently ignore EROFS because reading the file
|
||||
won't have upset its timestamp if it's on a read-only
|
||||
filesystem. This has been submitted as a suggestion to
|
||||
"bug-gnu-utils@prep.ai.mit.edu". -BEM */
|
||||
if (utime (file_hdr.c_name, ×) < 0
|
||||
&& errno != EROFS)
|
||||
error (0, errno, "%s", file_hdr.c_name);
|
||||
}
|
||||
return;
|
||||
set_file_times (in_file_des, file_hdr.c_name, file_hdr.c_mtime,
|
||||
file_hdr.c_mtime);
|
||||
if (close (in_file_des) < 0)
|
||||
close_error (header->c_name);
|
||||
}
|
||||
|
||||
/* When writing newc and crc format archives we defer multiply linked
|
||||
@ -279,7 +266,7 @@ writeout_final_defers (int out_des)
|
||||
}
|
||||
else
|
||||
{
|
||||
struct new_cpio_header file_hdr;
|
||||
struct cpio_file_stat file_hdr;
|
||||
file_hdr = d->header;
|
||||
file_hdr.c_filesize = 0;
|
||||
write_out_header (&file_hdr, out_des);
|
||||
@ -288,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
|
||||
descriptor OUT_DES. */
|
||||
|
||||
void
|
||||
write_out_header (struct new_cpio_header *file_hdr, int out_des)
|
||||
int
|
||||
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];
|
||||
char *magic_string;
|
||||
|
||||
if (archive_format == arf_crcascii)
|
||||
magic_string = "070702";
|
||||
else
|
||||
magic_string = "070701";
|
||||
sprintf (ascii_header,
|
||||
"%6s%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx",
|
||||
magic_string,
|
||||
file_hdr->c_ino, file_hdr->c_mode, file_hdr->c_uid,
|
||||
file_hdr->c_gid, file_hdr->c_nlink, file_hdr->c_mtime,
|
||||
file_hdr->c_filesize, file_hdr->c_dev_maj, file_hdr->c_dev_min,
|
||||
file_hdr->c_rdev_maj, file_hdr->c_rdev_min, file_hdr->c_namesize,
|
||||
file_hdr->c_chksum);
|
||||
tape_buffered_write (ascii_header, out_des, 110L);
|
||||
|
||||
/* Write file name to output. */
|
||||
tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
|
||||
tape_pad_output (out_des, file_hdr->c_namesize + 110);
|
||||
}
|
||||
else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
|
||||
{
|
||||
char ascii_header[78];
|
||||
dev_t dev;
|
||||
dev_t rdev;
|
||||
|
||||
if (archive_format == arf_oldascii)
|
||||
case arf_newascii:
|
||||
return write_out_new_ascii_header ("070701", file_hdr, out_des);
|
||||
|
||||
case arf_crcascii:
|
||||
return write_out_new_ascii_header ("070702", file_hdr, out_des);
|
||||
|
||||
case arf_oldascii:
|
||||
return write_out_old_ascii_header (makedev (file_hdr->c_dev_maj,
|
||||
file_hdr->c_dev_min),
|
||||
makedev (file_hdr->c_rdev_maj,
|
||||
file_hdr->c_rdev_min),
|
||||
file_hdr, out_des);
|
||||
|
||||
case arf_hpoldascii:
|
||||
hp_compute_dev (file_hdr, &dev, &rdev);
|
||||
return write_out_old_ascii_header (dev, rdev, file_hdr, out_des);
|
||||
|
||||
case arf_tar:
|
||||
case arf_ustar:
|
||||
if (is_tar_filename_too_long (file_hdr->c_name))
|
||||
{
|
||||
dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
|
||||
rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HP/UX cpio creates archives that look just like ordinary archives,
|
||||
but for devices it sets major = 0, minor = 1, and puts the
|
||||
actual major/minor number in the filesize field. */
|
||||
switch (file_hdr->c_mode & CP_IFMT)
|
||||
{
|
||||
case CP_IFCHR:
|
||||
case CP_IFBLK:
|
||||
#ifdef CP_IFSOCK
|
||||
case CP_IFSOCK:
|
||||
#endif
|
||||
#ifdef CP_IFIFO
|
||||
case CP_IFIFO:
|
||||
#endif
|
||||
file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
|
||||
file_hdr->c_rdev_min);
|
||||
rdev = 1;
|
||||
break;
|
||||
default:
|
||||
dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
|
||||
rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
|
||||
break;
|
||||
}
|
||||
error (0, 0, _("%s: file name too long"), file_hdr->c_name);
|
||||
return 1;
|
||||
}
|
||||
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)
|
||||
error (0, 0, _("%s: truncating inode number"), file_hdr->c_name);
|
||||
case arf_binary:
|
||||
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
|
||||
to ensure that a long int is passed to sprintf. This has been
|
||||
reported to "bug-gnu-utils@prep.ai.mit.edu". (1998/5/26) -BEM */
|
||||
sprintf (ascii_header,
|
||||
"%06ho%06lo%06lo%06lo%06lo%06lo%06lo%06lo%011lo%06lo%011lo",
|
||||
file_hdr->c_magic & 0xFFFF, (long) dev & 0xFFFF,
|
||||
file_hdr->c_ino & 0xFFFF, file_hdr->c_mode & 0xFFFF,
|
||||
file_hdr->c_uid & 0xFFFF, file_hdr->c_gid & 0xFFFF,
|
||||
file_hdr->c_nlink & 0xFFFF, (long) rdev & 0xFFFF,
|
||||
file_hdr->c_mtime, file_hdr->c_namesize & 0xFFFF,
|
||||
file_hdr->c_filesize);
|
||||
tape_buffered_write (ascii_header, out_des, 76L);
|
||||
case arf_hpbinary:
|
||||
hp_compute_dev (file_hdr, &dev, &rdev);
|
||||
/* FIXME: dev ignored. Should it be? */
|
||||
return write_out_binary_header (rdev, file_hdr, out_des);
|
||||
|
||||
/* Write file name to output. */
|
||||
tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
|
||||
default:
|
||||
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;
|
||||
short_hdr.c_dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
|
||||
|
||||
if ((warn_option & CPIO_WARN_TRUNCATE) && (file_hdr->c_ino >> 16) != 0)
|
||||
error (0, 0, _("%s: truncating inode number"), file_hdr->c_name);
|
||||
|
||||
short_hdr.c_ino = file_hdr->c_ino & 0xFFFF;
|
||||
short_hdr.c_mode = file_hdr->c_mode & 0xFFFF;
|
||||
short_hdr.c_uid = file_hdr->c_uid & 0xFFFF;
|
||||
short_hdr.c_gid = file_hdr->c_gid & 0xFFFF;
|
||||
short_hdr.c_nlink = file_hdr->c_nlink & 0xFFFF;
|
||||
if (archive_format != arf_hpbinary)
|
||||
short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
|
||||
else
|
||||
{
|
||||
switch (file_hdr->c_mode & CP_IFMT)
|
||||
{
|
||||
/* HP/UX cpio creates archives that look just like ordinary
|
||||
archives, but for devices it sets major = 0, minor = 1, and
|
||||
puts the actual major/minor number in the filesize field. */
|
||||
case CP_IFCHR:
|
||||
case CP_IFBLK:
|
||||
#ifdef CP_IFSOCK
|
||||
case CP_IFSOCK:
|
||||
#endif
|
||||
#ifdef CP_IFIFO
|
||||
case CP_IFIFO:
|
||||
#endif
|
||||
file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
|
||||
file_hdr->c_rdev_min);
|
||||
short_hdr.c_rdev = makedev (0, 1);
|
||||
break;
|
||||
default:
|
||||
short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj,
|
||||
file_hdr->c_rdev_min);
|
||||
break;
|
||||
}
|
||||
}
|
||||
short_hdr.c_mtimes[0] = file_hdr->c_mtime >> 16;
|
||||
short_hdr.c_mtimes[1] = file_hdr->c_mtime & 0xFFFF;
|
||||
|
||||
short_hdr.c_namesize = file_hdr->c_namesize & 0xFFFF;
|
||||
|
||||
short_hdr.c_filesizes[0] = file_hdr->c_filesize >> 16;
|
||||
short_hdr.c_filesizes[1] = file_hdr->c_filesize & 0xFFFF;
|
||||
|
||||
/* Output the file header. */
|
||||
tape_buffered_write ((char *) &short_hdr, out_des, 26L);
|
||||
|
||||
/* Write file name to output. */
|
||||
tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
|
||||
|
||||
tape_pad_output (out_des, file_hdr->c_namesize + 26);
|
||||
}
|
||||
static void
|
||||
assign_string (char **pvar, char *value)
|
||||
{
|
||||
char *p = xrealloc (*pvar, strlen (value) + 1);
|
||||
strcpy (p, value);
|
||||
*pvar = p;
|
||||
}
|
||||
|
||||
/* Read a list of file names from the standard input
|
||||
@ -447,17 +597,14 @@ process_copy_out ()
|
||||
{
|
||||
int res; /* Result of functions. */
|
||||
dynamic_string input_name; /* Name of file read from stdin. */
|
||||
struct utimbuf times; /* For resetting file times after copy. */
|
||||
struct stat file_stat; /* Stat record for file. */
|
||||
struct new_cpio_header file_hdr; /* Output header information. */
|
||||
struct cpio_file_stat file_hdr; /* Output header information. */
|
||||
int in_file_des; /* Source file descriptor. */
|
||||
int out_file_des; /* Output file descriptor. */
|
||||
char *p;
|
||||
char *orig_file_name = NULL;
|
||||
|
||||
/* Initialize the copy out. */
|
||||
ds_init (&input_name, 128);
|
||||
/* Initialize this in case it has members we don't know to set. */
|
||||
bzero (×, sizeof (struct utimbuf));
|
||||
file_hdr.c_magic = 070707;
|
||||
|
||||
/* Check whether the output file might be a tape. */
|
||||
@ -497,55 +644,11 @@ process_copy_out ()
|
||||
|
||||
/* Process next file. */
|
||||
if ((*xstat) (input_name.ds_string, &file_stat) < 0)
|
||||
error (0, errno, "%s", input_name.ds_string);
|
||||
stat_error (input_name.ds_string);
|
||||
else
|
||||
{
|
||||
/* Set values in output header. */
|
||||
file_hdr.c_dev_maj = major (file_stat.st_dev);
|
||||
file_hdr.c_dev_min = minor (file_stat.st_dev);
|
||||
file_hdr.c_ino = file_stat.st_ino;
|
||||
/* For POSIX systems that don't define the S_IF macros,
|
||||
we can't assume that S_ISfoo means the standard Unix
|
||||
S_IFfoo bit(s) are set. So do it manually, with a
|
||||
different name. Bleah. */
|
||||
file_hdr.c_mode = (file_stat.st_mode & 07777);
|
||||
if (S_ISREG (file_stat.st_mode))
|
||||
file_hdr.c_mode |= CP_IFREG;
|
||||
else if (S_ISDIR (file_stat.st_mode))
|
||||
file_hdr.c_mode |= CP_IFDIR;
|
||||
#ifdef S_ISBLK
|
||||
else if (S_ISBLK (file_stat.st_mode))
|
||||
file_hdr.c_mode |= CP_IFBLK;
|
||||
#endif
|
||||
#ifdef S_ISCHR
|
||||
else if (S_ISCHR (file_stat.st_mode))
|
||||
file_hdr.c_mode |= CP_IFCHR;
|
||||
#endif
|
||||
#ifdef S_ISFIFO
|
||||
else if (S_ISFIFO (file_stat.st_mode))
|
||||
file_hdr.c_mode |= CP_IFIFO;
|
||||
#endif
|
||||
#ifdef S_ISLNK
|
||||
else if (S_ISLNK (file_stat.st_mode))
|
||||
file_hdr.c_mode |= CP_IFLNK;
|
||||
#endif
|
||||
#ifdef S_ISSOCK
|
||||
else if (S_ISSOCK (file_stat.st_mode))
|
||||
file_hdr.c_mode |= CP_IFSOCK;
|
||||
#endif
|
||||
#ifdef S_ISNWK
|
||||
else if (S_ISNWK (file_stat.st_mode))
|
||||
file_hdr.c_mode |= CP_IFNWK;
|
||||
#endif
|
||||
file_hdr.c_uid = file_stat.st_uid;
|
||||
file_hdr.c_gid = file_stat.st_gid;
|
||||
file_hdr.c_nlink = file_stat.st_nlink;
|
||||
file_hdr.c_rdev_maj = major (file_stat.st_rdev);
|
||||
file_hdr.c_rdev_min = minor (file_stat.st_rdev);
|
||||
file_hdr.c_mtime = file_stat.st_mtime;
|
||||
file_hdr.c_filesize = file_stat.st_size;
|
||||
file_hdr.c_chksum = 0;
|
||||
file_hdr.c_tar_linkname = NULL;
|
||||
stat_to_cpio (&file_hdr, &file_stat);
|
||||
|
||||
if (archive_format == arf_tar || archive_format == arf_ustar)
|
||||
{
|
||||
@ -562,17 +665,12 @@ process_copy_out ()
|
||||
}
|
||||
}
|
||||
|
||||
/* Strip leading `./' from the filename. */
|
||||
p = input_name.ds_string;
|
||||
while (*p == '.' && *(p + 1) == '/')
|
||||
{
|
||||
++p;
|
||||
while (*p == '/')
|
||||
++p;
|
||||
}
|
||||
assign_string (&orig_file_name, input_name.ds_string);
|
||||
cpio_safer_name_suffix (input_name.ds_string, false,
|
||||
!no_abs_paths_flag, true);
|
||||
#ifndef HPUX_CDF
|
||||
file_hdr.c_name = p;
|
||||
file_hdr.c_namesize = strlen (p) + 1;
|
||||
file_hdr.c_name = input_name.ds_string;
|
||||
file_hdr.c_namesize = strlen (input_name.ds_string) + 1;
|
||||
#else
|
||||
if ( (archive_format != arf_tar) && (archive_format != arf_ustar) )
|
||||
{
|
||||
@ -581,7 +679,7 @@ process_copy_out ()
|
||||
properly recreate the directory as hidden (in case the
|
||||
files of a directory go into the archive before the
|
||||
directory itself (e.g from "find ... -depth ... | cpio")). */
|
||||
file_hdr.c_name = add_cdf_double_slashes (p);
|
||||
file_hdr.c_name = add_cdf_double_slashes (input_name.ds_string);
|
||||
file_hdr.c_namesize = strlen (file_hdr.c_name) + 1;
|
||||
}
|
||||
else
|
||||
@ -589,18 +687,11 @@ process_copy_out ()
|
||||
/* We don't mark CDF's in tar files. We assume the "hidden"
|
||||
directory will always go into the archive before any of
|
||||
its files. */
|
||||
file_hdr.c_name = p;
|
||||
file_hdr.c_namesize = strlen (p) + 1;
|
||||
file_hdr.c_name = input_name.ds_string;
|
||||
file_hdr.c_namesize = strlen (input_name.ds_string) + 1;
|
||||
}
|
||||
#endif
|
||||
if ((archive_format == arf_tar || archive_format == arf_ustar)
|
||||
&& is_tar_filename_too_long (file_hdr.c_name))
|
||||
{
|
||||
error (0, 0, _("%s: file name too long"),
|
||||
file_hdr.c_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* Copy the named file to the output. */
|
||||
switch (file_hdr.c_mode & CP_IFMT)
|
||||
{
|
||||
@ -613,7 +704,8 @@ process_copy_out ()
|
||||
file_hdr.c_dev_min)))
|
||||
{
|
||||
file_hdr.c_tar_linkname = otherfile;
|
||||
write_out_header (&file_hdr, out_file_des);
|
||||
if (write_out_header (&file_hdr, out_file_des))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -630,50 +722,45 @@ process_copy_out ()
|
||||
break;
|
||||
}
|
||||
}
|
||||
in_file_des = open (input_name.ds_string,
|
||||
in_file_des = open (orig_file_name,
|
||||
O_RDONLY | O_BINARY, 0);
|
||||
if (in_file_des < 0)
|
||||
{
|
||||
error (0, errno, "%s", input_name.ds_string);
|
||||
open_error (orig_file_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (archive_format == arf_crcascii)
|
||||
file_hdr.c_chksum = read_for_checksum (in_file_des,
|
||||
file_hdr.c_filesize,
|
||||
input_name.ds_string);
|
||||
orig_file_name);
|
||||
|
||||
write_out_header (&file_hdr, out_file_des);
|
||||
copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize, input_name.ds_string);
|
||||
warn_if_file_changed(input_name.ds_string, file_hdr.c_filesize,
|
||||
if (write_out_header (&file_hdr, out_file_des))
|
||||
continue;
|
||||
copy_files_disk_to_tape (in_file_des,
|
||||
out_file_des, file_hdr.c_filesize,
|
||||
orig_file_name);
|
||||
warn_if_file_changed(orig_file_name, file_hdr.c_filesize,
|
||||
file_hdr.c_mtime);
|
||||
|
||||
if (archive_format == arf_tar || archive_format == arf_ustar)
|
||||
add_inode (file_hdr.c_ino, file_hdr.c_name, file_hdr.c_dev_maj,
|
||||
add_inode (file_hdr.c_ino, orig_file_name, file_hdr.c_dev_maj,
|
||||
file_hdr.c_dev_min);
|
||||
|
||||
tape_pad_output (out_file_des, file_hdr.c_filesize);
|
||||
|
||||
if (close (in_file_des) < 0)
|
||||
error (0, errno, "%s", input_name.ds_string);
|
||||
if (reset_time_flag)
|
||||
{
|
||||
times.actime = file_stat.st_atime;
|
||||
times.modtime = file_stat.st_mtime;
|
||||
/* Debian hack: Silently ignore EROFS because
|
||||
reading the file won't have upset its timestamp
|
||||
if it's on a read-only filesystem. This has been
|
||||
submitted as a suggestion to
|
||||
"bug-gnu-utils@prep.ai.mit.edu". -BEM */
|
||||
if (utime (file_hdr.c_name, ×) < 0
|
||||
&& errno != EROFS)
|
||||
error (0, errno, "%s", file_hdr.c_name);
|
||||
}
|
||||
set_file_times (in_file_des,
|
||||
orig_file_name,
|
||||
file_stat.st_atime, file_stat.st_mtime);
|
||||
if (close (in_file_des) < 0)
|
||||
close_error (orig_file_name);
|
||||
break;
|
||||
|
||||
case CP_IFDIR:
|
||||
file_hdr.c_filesize = 0;
|
||||
write_out_header (&file_hdr, out_file_des);
|
||||
if (write_out_header (&file_hdr, out_file_des))
|
||||
continue;
|
||||
break;
|
||||
|
||||
case CP_IFCHR:
|
||||
@ -687,7 +774,7 @@ process_copy_out ()
|
||||
if (archive_format == arf_tar)
|
||||
{
|
||||
error (0, 0, _("%s not dumped: not a regular file"),
|
||||
file_hdr.c_name);
|
||||
orig_file_name);
|
||||
continue;
|
||||
}
|
||||
else if (archive_format == arf_ustar)
|
||||
@ -702,14 +789,16 @@ process_copy_out ()
|
||||
file_hdr.c_mode = (file_stat.st_mode & 07777);
|
||||
file_hdr.c_mode |= CP_IFREG;
|
||||
file_hdr.c_tar_linkname = otherfile;
|
||||
write_out_header (&file_hdr, out_file_des);
|
||||
if (write_out_header (&file_hdr, out_file_des))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
add_inode (file_hdr.c_ino, file_hdr.c_name,
|
||||
add_inode (file_hdr.c_ino, orig_file_name,
|
||||
file_hdr.c_dev_maj, file_hdr.c_dev_min);
|
||||
}
|
||||
file_hdr.c_filesize = 0;
|
||||
write_out_header (&file_hdr, out_file_des);
|
||||
if (write_out_header (&file_hdr, out_file_des))
|
||||
continue;
|
||||
break;
|
||||
|
||||
#ifdef CP_IFLNK
|
||||
@ -718,14 +807,18 @@ process_copy_out ()
|
||||
char *link_name = (char *) xmalloc (file_stat.st_size + 1);
|
||||
int link_size;
|
||||
|
||||
link_size = readlink (input_name.ds_string, link_name,
|
||||
link_size = readlink (orig_file_name, link_name,
|
||||
file_stat.st_size);
|
||||
if (link_size < 0)
|
||||
{
|
||||
error (0, errno, "%s", input_name.ds_string);
|
||||
readlink_warn (orig_file_name);
|
||||
free (link_name);
|
||||
continue;
|
||||
}
|
||||
link_name[link_size] = 0;
|
||||
cpio_safer_name_suffix (link_name, false,
|
||||
!no_abs_paths_flag, true);
|
||||
link_size = strlen (link_name);
|
||||
file_hdr.c_filesize = link_size;
|
||||
if (archive_format == arf_tar || archive_format == arf_ustar)
|
||||
{
|
||||
@ -738,12 +831,14 @@ process_copy_out ()
|
||||
{
|
||||
link_name[link_size] = '\0';
|
||||
file_hdr.c_tar_linkname = link_name;
|
||||
write_out_header (&file_hdr, out_file_des);
|
||||
if (write_out_header (&file_hdr, out_file_des))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
write_out_header (&file_hdr, out_file_des);
|
||||
if (write_out_header (&file_hdr, out_file_des))
|
||||
continue;
|
||||
tape_buffered_write (link_name, out_file_des, link_size);
|
||||
tape_pad_output (out_file_des, link_size);
|
||||
}
|
||||
@ -753,16 +848,18 @@ process_copy_out ()
|
||||
#endif
|
||||
|
||||
default:
|
||||
error (0, 0, _("%s: unknown file type"), input_name.ds_string);
|
||||
error (0, 0, _("%s: unknown file type"), orig_file_name);
|
||||
}
|
||||
|
||||
|
||||
if (verbose_flag)
|
||||
fprintf (stderr, "%s\n", input_name.ds_string);
|
||||
fprintf (stderr, "%s\n", orig_file_name);
|
||||
if (dot_flag)
|
||||
fputc ('.', stderr);
|
||||
}
|
||||
}
|
||||
|
||||
free (orig_file_name);
|
||||
|
||||
writeout_final_defers(out_file_des);
|
||||
/* The collection is complete; append the trailer. */
|
||||
file_hdr.c_ino = 0;
|
||||
@ -779,14 +876,11 @@ process_copy_out ()
|
||||
|
||||
file_hdr.c_filesize = 0;
|
||||
file_hdr.c_namesize = 11;
|
||||
file_hdr.c_name = "TRAILER!!!";
|
||||
file_hdr.c_name = CPIO_TRAILER_NAME;
|
||||
if (archive_format != arf_tar && archive_format != arf_ustar)
|
||||
write_out_header (&file_hdr, out_file_des);
|
||||
else
|
||||
{
|
||||
tape_buffered_write (zeros_512, out_file_des, 512);
|
||||
tape_buffered_write (zeros_512, out_file_des, 512);
|
||||
}
|
||||
write_nuls_to_file (1024, out_file_des, tape_buffered_write);
|
||||
|
||||
/* Fill up the output block. */
|
||||
tape_clear_rest_of_block (out_file_des);
|
||||
|
149
src/copypass.c
149
src/copypass.c
@ -1,5 +1,6 @@
|
||||
/* copypass.c - cpio copy pass sub-function.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +12,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
@ -24,11 +26,23 @@
|
||||
#include "cpiohdr.h"
|
||||
#include "dstring.h"
|
||||
#include "extern.h"
|
||||
#include "paxlib.h"
|
||||
|
||||
#ifndef HAVE_LCHOWN
|
||||
#define lchown chown
|
||||
# define lchown chown
|
||||
#endif
|
||||
|
||||
|
||||
/* A wrapper around set_perms using another set of arguments */
|
||||
static void
|
||||
set_copypass_perms (int fd, const char *name, struct stat *st)
|
||||
{
|
||||
struct cpio_file_stat header;
|
||||
header.c_name = name;
|
||||
stat_to_cpio (&header, st);
|
||||
set_perms (fd, &header);
|
||||
}
|
||||
|
||||
/* Copy files listed on the standard input into directory `directory_name'.
|
||||
If `link_flag', link instead of copying. */
|
||||
|
||||
@ -40,7 +54,6 @@ process_copy_pass ()
|
||||
int dirname_len; /* Length of `directory_name'. */
|
||||
int res; /* Result of functions. */
|
||||
char *slash; /* For moving past slashes in input name. */
|
||||
struct utimbuf times; /* For resetting file times after copy. */
|
||||
struct stat in_file_stat; /* Stat record for input file. */
|
||||
struct stat out_file_stat; /* Stat record for output file. */
|
||||
int in_file_des; /* Input file descriptor. */
|
||||
@ -51,6 +64,9 @@ process_copy_pass ()
|
||||
int cdf_char;
|
||||
#endif
|
||||
|
||||
umask (0); /* Reset umask to preserve modes of
|
||||
created files */
|
||||
|
||||
/* Initialize the copy pass. */
|
||||
dirname_len = strlen (directory_name);
|
||||
ds_init (&input_name, 128);
|
||||
@ -58,8 +74,6 @@ process_copy_pass ()
|
||||
strcpy (output_name.ds_string, directory_name);
|
||||
output_name.ds_string[dirname_len] = '/';
|
||||
output_is_seekable = true;
|
||||
/* Initialize this in case it has members we don't know to set. */
|
||||
bzero (×, sizeof (struct utimbuf));
|
||||
|
||||
/* Copy files with names read from stdin. */
|
||||
while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
|
||||
@ -82,7 +96,7 @@ process_copy_pass ()
|
||||
|
||||
if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
|
||||
{
|
||||
error (0, errno, "%s", input_name.ds_string);
|
||||
stat_error (input_name.ds_string);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -150,7 +164,7 @@ process_copy_pass ()
|
||||
O_RDONLY | O_BINARY, 0);
|
||||
if (in_file_des < 0)
|
||||
{
|
||||
error (0, errno, "%s", input_name.ds_string);
|
||||
open_error (input_name.ds_string);
|
||||
continue;
|
||||
}
|
||||
out_file_des = open (output_name.ds_string,
|
||||
@ -163,7 +177,7 @@ process_copy_pass ()
|
||||
}
|
||||
if (out_file_des < 0)
|
||||
{
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
open_error (output_name.ds_string);
|
||||
close (in_file_des);
|
||||
continue;
|
||||
}
|
||||
@ -179,43 +193,28 @@ process_copy_pass ()
|
||||
write (out_file_des, "", 1);
|
||||
delayed_seek_count = 0;
|
||||
}
|
||||
if (close (in_file_des) < 0)
|
||||
error (0, errno, "%s", input_name.ds_string);
|
||||
if (close (out_file_des) < 0)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
|
||||
/* Set the attributes of the new file. */
|
||||
if (!no_chown_flag)
|
||||
if ((chown (output_name.ds_string,
|
||||
set_owner_flag ? set_owner : in_file_stat.st_uid,
|
||||
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
/* chown may have turned off some permissions we wanted. */
|
||||
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
set_copypass_perms (out_file_des,
|
||||
output_name.ds_string, &in_file_stat);
|
||||
|
||||
if (reset_time_flag)
|
||||
{
|
||||
times.actime = in_file_stat.st_atime;
|
||||
times.modtime = in_file_stat.st_mtime;
|
||||
/* Debian hack: Silently ignore EROFS because
|
||||
reading the file won't have upset its timestamp
|
||||
if it's on a read-only filesystem. This has been
|
||||
submitted as a suggestion to
|
||||
"bug-gnu-utils@prep.ai.mit.edu". -BEM */
|
||||
if (utime (input_name.ds_string, ×) < 0
|
||||
&& errno != EROFS)
|
||||
error (0, errno, "%s", input_name.ds_string);
|
||||
if (utime (output_name.ds_string, ×) < 0
|
||||
&& errno != EROFS)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
}
|
||||
if (retain_time_flag)
|
||||
{
|
||||
times.actime = times.modtime = in_file_stat.st_mtime;
|
||||
if (utime (output_name.ds_string, ×) < 0)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
}
|
||||
{
|
||||
set_file_times (in_file_des,
|
||||
input_name.ds_string,
|
||||
in_file_stat.st_atime,
|
||||
in_file_stat.st_mtime);
|
||||
set_file_times (out_file_des,
|
||||
output_name.ds_string,
|
||||
in_file_stat.st_atime,
|
||||
in_file_stat.st_mtime);
|
||||
}
|
||||
|
||||
if (close (in_file_des) < 0)
|
||||
close_error (input_name.ds_string);
|
||||
|
||||
if (close (out_file_des) < 0)
|
||||
close_error (output_name.ds_string);
|
||||
|
||||
warn_if_file_changed(input_name.ds_string, in_file_stat.st_size,
|
||||
in_file_stat.st_mtime);
|
||||
}
|
||||
@ -261,31 +260,11 @@ process_copy_pass ()
|
||||
(lstat (output_name.ds_string, &out_file_stat) != 0) ||
|
||||
!(S_ISDIR (out_file_stat.st_mode) ) )
|
||||
{
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
stat_error (output_name.ds_string);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!no_chown_flag)
|
||||
if ((chown (output_name.ds_string,
|
||||
set_owner_flag ? set_owner : in_file_stat.st_uid,
|
||||
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
/* chown may have turned off some permissions we wanted. */
|
||||
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
#ifdef HPUX_CDF
|
||||
if (cdf_flag)
|
||||
/* Once we "hide" the directory with the chmod(),
|
||||
we have to refer to it using name+ isntead of name. */
|
||||
output_name.ds_string [cdf_char] = '+';
|
||||
#endif
|
||||
if (retain_time_flag)
|
||||
{
|
||||
times.actime = times.modtime = in_file_stat.st_mtime;
|
||||
if (utime (output_name.ds_string, ×) < 0)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
}
|
||||
set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
|
||||
}
|
||||
else if (S_ISCHR (in_file_stat.st_mode) ||
|
||||
S_ISBLK (in_file_stat.st_mode) ||
|
||||
@ -321,24 +300,10 @@ process_copy_pass ()
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
mknod_error (output_name.ds_string);
|
||||
continue;
|
||||
}
|
||||
if (!no_chown_flag)
|
||||
if ((chown (output_name.ds_string,
|
||||
set_owner_flag ? set_owner : in_file_stat.st_uid,
|
||||
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
/* chown may have turned off some permissions we wanted. */
|
||||
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
if (retain_time_flag)
|
||||
{
|
||||
times.actime = times.modtime = in_file_stat.st_mtime;
|
||||
if (utime (output_name.ds_string, ×) < 0)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
}
|
||||
set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,7 +318,7 @@ process_copy_pass ()
|
||||
in_file_stat.st_size);
|
||||
if (link_size < 0)
|
||||
{
|
||||
error (0, errno, "%s", input_name.ds_string);
|
||||
readlink_error (input_name.ds_string);
|
||||
free (link_name);
|
||||
continue;
|
||||
}
|
||||
@ -369,18 +334,20 @@ process_copy_pass ()
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
symlink_error (output_name.ds_string, link_name);
|
||||
free (link_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set the attributes of the new link. */
|
||||
if (!no_chown_flag)
|
||||
if ((lchown (output_name.ds_string,
|
||||
set_owner_flag ? set_owner : in_file_stat.st_uid,
|
||||
set_group_flag ? set_group : in_file_stat.st_gid) < 0)
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
{
|
||||
uid_t uid = set_owner_flag ? set_owner : in_file_stat.st_uid;
|
||||
gid_t gid = set_group_flag ? set_group : in_file_stat.st_gid;
|
||||
if ((lchown (output_name.ds_string, uid, gid) < 0)
|
||||
&& errno != EPERM)
|
||||
chown_error_details (output_name.ds_string, uid, gid);
|
||||
}
|
||||
free (link_name);
|
||||
}
|
||||
#endif
|
||||
|
11
src/cpio.h
11
src/cpio.h
@ -1,5 +1,5 @@
|
||||
/* Extended cpio format from POSIX.1.
|
||||
Copyright (C) 1992 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifndef _CPIO_H
|
||||
|
||||
@ -25,6 +26,8 @@
|
||||
and variable length file data.
|
||||
A header for a filename "TRAILER!!!" indicates the end of the archive. */
|
||||
|
||||
#define CPIO_TRAILER_NAME "TRAILER!!!"
|
||||
|
||||
/* All the fields in the header are ISO 646 (approximately ASCII) strings
|
||||
of octal numbers, left padded, not NUL terminated.
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Extended cpio header from POSIX.1.
|
||||
Copyright (C) 1992 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifndef _CPIOHDR_H
|
||||
|
||||
@ -34,9 +35,21 @@ struct old_cpio_header
|
||||
unsigned short c_mtimes[2];
|
||||
unsigned short c_namesize;
|
||||
unsigned short c_filesizes[2];
|
||||
unsigned long c_mtime; /* Long-aligned copy of `c_mtimes'. */
|
||||
unsigned long c_filesize; /* Long-aligned copy of `c_filesizes'. */
|
||||
char *c_name;
|
||||
};
|
||||
|
||||
struct old_ascii_header
|
||||
{
|
||||
char c_magic[6];
|
||||
char c_dev[6];
|
||||
char c_ino[6];
|
||||
char c_mode[6];
|
||||
char c_uid[6];
|
||||
char c_gid[6];
|
||||
char c_nlink[6];
|
||||
char c_rdev[6];
|
||||
char c_mtime[11];
|
||||
char c_namesize[6];
|
||||
char c_filesize[11];
|
||||
};
|
||||
|
||||
/* "New" portable format and CRC format:
|
||||
@ -47,44 +60,47 @@ struct old_cpio_header
|
||||
A header for a filename "TRAILER!!!" indicates the end of the archive. */
|
||||
|
||||
/* All the fields in the header are ISO 646 (approximately ASCII) strings
|
||||
of hexadecimal numbers, left padded, not NUL terminated.
|
||||
of hexadecimal numbers, left padded, not NUL terminated: */
|
||||
|
||||
Field Name Length in Bytes Notes
|
||||
c_magic 6 "070701" for "new" portable format
|
||||
"070702" for CRC format
|
||||
c_ino 8
|
||||
c_mode 8
|
||||
c_uid 8
|
||||
c_gid 8
|
||||
c_nlink 8
|
||||
c_mtime 8
|
||||
c_filesize 8 must be 0 for FIFOs and directories
|
||||
c_maj 8
|
||||
c_min 8
|
||||
c_rmaj 8 only valid for chr and blk special files
|
||||
c_rmin 8 only valid for chr and blk special files
|
||||
c_namesize 8 count includes terminating NUL in pathname
|
||||
c_chksum 8 0 for "new" portable format; for CRC format
|
||||
the sum of all the bytes in the file */
|
||||
struct new_ascii_header
|
||||
{
|
||||
char c_magic[6]; /* "070701" for "new" portable format
|
||||
"070702" for CRC format */
|
||||
char c_ino[8];
|
||||
char c_mode[8];
|
||||
char c_uid[8];
|
||||
char c_gid[8];
|
||||
char c_nlink[8];
|
||||
char c_mtime[8];
|
||||
char c_filesize[8]; /* must be 0 for FIFOs and directories */
|
||||
char c_dev_maj[8];
|
||||
char c_dev_min[8];
|
||||
char c_rdev_maj[8]; /* only valid for chr and blk special files */
|
||||
char c_rdev_min[8]; /* only valid for chr and blk special files */
|
||||
char c_namesize[8]; /* count includes terminating NUL in pathname */
|
||||
char c_chksum[8]; /* 0 for "new" portable format; for CRC format
|
||||
the sum of all the bytes in the file */
|
||||
};
|
||||
|
||||
struct new_cpio_header
|
||||
struct cpio_file_stat /* Internal representation of a CPIO header */
|
||||
{
|
||||
unsigned short c_magic;
|
||||
unsigned long c_ino;
|
||||
unsigned long c_mode;
|
||||
unsigned long c_uid;
|
||||
unsigned long c_gid;
|
||||
unsigned long c_nlink;
|
||||
unsigned long c_mtime;
|
||||
unsigned long c_filesize;
|
||||
ino_t c_ino;
|
||||
mode_t c_mode;
|
||||
uid_t c_uid;
|
||||
gid_t c_gid;
|
||||
size_t c_nlink;
|
||||
time_t c_mtime;
|
||||
off_t c_filesize;
|
||||
long c_dev_maj;
|
||||
long c_dev_min;
|
||||
long c_rdev_maj;
|
||||
long c_rdev_min;
|
||||
unsigned long c_namesize;
|
||||
size_t c_namesize;
|
||||
unsigned long c_chksum;
|
||||
char *c_name;
|
||||
char *c_tar_linkname;
|
||||
};
|
||||
|
||||
|
||||
#endif /* cpiohdr.h */
|
||||
|
11
src/defer.c
11
src/defer.c
@ -1,5 +1,5 @@
|
||||
/* defer.c - handle "defered" links in newc and crc archives
|
||||
Copyright (C) 1993,2003,2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
@ -24,7 +25,7 @@
|
||||
#include "defer.h"
|
||||
|
||||
struct deferment *
|
||||
create_deferment (struct new_cpio_header *file_hdr)
|
||||
create_deferment (struct cpio_file_stat *file_hdr)
|
||||
{
|
||||
struct deferment *d;
|
||||
d = (struct deferment *) xmalloc (sizeof (struct deferment) );
|
||||
|
15
src/defer.h
15
src/defer.h
@ -1,5 +1,5 @@
|
||||
/* defer.h
|
||||
Copyright (C) 1993, 2001, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 2001, 2004, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,15 +11,16 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
struct deferment
|
||||
{
|
||||
struct deferment *next;
|
||||
struct new_cpio_header header;
|
||||
struct cpio_file_stat header;
|
||||
};
|
||||
|
||||
struct deferment *create_deferment P_((struct new_cpio_header *file_hdr));
|
||||
void free_deferment P_((struct deferment *d));
|
||||
struct deferment *create_deferment (struct cpio_file_stat *file_hdr);
|
||||
void free_deferment (struct deferment *d);
|
||||
|
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
@ -27,13 +28,8 @@
|
||||
#endif
|
||||
#include "dstring.h"
|
||||
|
||||
#if __STDC__
|
||||
# define P_(s) s
|
||||
#else
|
||||
# define P_(s) ()
|
||||
#endif
|
||||
char *xmalloc P_((unsigned n));
|
||||
char *xrealloc P_((char *p, unsigned n));
|
||||
char *xmalloc (unsigned n);
|
||||
char *xrealloc (char *p, unsigned n);
|
||||
|
||||
/* Initialiaze dynamic string STRING with space for SIZE characters. */
|
||||
|
||||
|
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
|
155
src/extern.h
155
src/extern.h
@ -1,5 +1,5 @@
|
||||
/* extern.h - External declarations for cpio. Requires system.h.
|
||||
Copyright (C) 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,15 +11,21 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include "paxlib.h"
|
||||
#include "quotearg.h"
|
||||
#include "quote.h"
|
||||
|
||||
enum archive_format
|
||||
{
|
||||
arf_unknown, arf_binary, arf_oldascii, arf_newascii, arf_crcascii,
|
||||
arf_tar, arf_ustar, arf_hpoldascii, arf_hpbinary
|
||||
};
|
||||
|
||||
extern enum archive_format archive_format;
|
||||
extern int reset_time_flag;
|
||||
extern int io_block_size;
|
||||
@ -66,7 +72,7 @@ extern char *new_media_message_after_number;
|
||||
extern int archive_des;
|
||||
extern char *archive_name;
|
||||
extern char *rsh_command_option;
|
||||
extern unsigned long crc;
|
||||
extern unsigned int crc;
|
||||
extern int delayed_seek_count;
|
||||
#ifdef DEBUG_CPIO
|
||||
extern int debug_flag;
|
||||
@ -81,7 +87,6 @@ extern long long input_bytes, output_bytes;
|
||||
#else
|
||||
extern long input_bytes, output_bytes;
|
||||
#endif
|
||||
extern char zeros_512[];
|
||||
extern char *directory_name;
|
||||
extern char **save_patterns;
|
||||
extern int num_patterns;
|
||||
@ -94,38 +99,35 @@ extern char *program_name;
|
||||
extern int (*xstat) ();
|
||||
extern void (*copy_function) ();
|
||||
|
||||
#if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define P_(s) s
|
||||
#else
|
||||
# define P_(s) ()
|
||||
#endif
|
||||
|
||||
/* copyin.c */
|
||||
void warn_junk_bytes P_((long bytes_skipped));
|
||||
void read_in_header P_((struct new_cpio_header *file_hdr, int in_des));
|
||||
void read_in_old_ascii P_((struct new_cpio_header *file_hdr, int in_des));
|
||||
void read_in_new_ascii P_((struct new_cpio_header *file_hdr, int in_des));
|
||||
void read_in_binary P_((struct new_cpio_header *file_hdr, int in_des));
|
||||
void swab_array P_((char *arg, int count));
|
||||
void process_copy_in P_((void));
|
||||
void long_format P_((struct new_cpio_header *file_hdr, char *link_name));
|
||||
void print_name_with_quoting P_((char *p));
|
||||
void warn_junk_bytes (long bytes_skipped);
|
||||
/* FIXME: make read_* static in copyin.c */
|
||||
void read_in_header (struct cpio_file_stat *file_hdr, int in_des);
|
||||
void read_in_old_ascii (struct cpio_file_stat *file_hdr, int in_des);
|
||||
void read_in_new_ascii (struct cpio_file_stat *file_hdr, int in_des);
|
||||
void read_in_binary (struct cpio_file_stat *file_hdr,
|
||||
struct old_cpio_header *short_hdr, int in_des);
|
||||
void swab_array (char *arg, int count);
|
||||
void process_copy_in (void);
|
||||
void long_format (struct cpio_file_stat *file_hdr, char *link_name);
|
||||
void print_name_with_quoting (char *p);
|
||||
|
||||
/* copyout.c */
|
||||
void write_out_header P_((struct new_cpio_header *file_hdr, int out_des));
|
||||
void process_copy_out P_((void));
|
||||
int write_out_header (struct cpio_file_stat *file_hdr, int out_des);
|
||||
void process_copy_out (void);
|
||||
|
||||
/* copypass.c */
|
||||
void process_copy_pass P_((void));
|
||||
int link_to_maj_min_ino P_((char *file_name, int st_dev_maj,
|
||||
int st_dev_min, int st_ino));
|
||||
int link_to_name P_((char *link_name, char *link_target));
|
||||
void process_copy_pass (void);
|
||||
int link_to_maj_min_ino (char *file_name, int st_dev_maj,
|
||||
int st_dev_min, int st_ino);
|
||||
int link_to_name (char *link_name, char *link_target);
|
||||
|
||||
/* dirname.c */
|
||||
char *dirname P_((char *path));
|
||||
char *dirname (char *path);
|
||||
|
||||
/* filemode.c */
|
||||
void mode_string P_((unsigned int mode, char *str));
|
||||
void mode_string (unsigned int mode, char *str);
|
||||
|
||||
/* idcache.c */
|
||||
#ifndef __MSDOS__
|
||||
@ -136,61 +138,63 @@ gid_t *getgidbyname ();
|
||||
#endif
|
||||
|
||||
/* main.c */
|
||||
void process_args P_((int argc, char *argv[]));
|
||||
void initialize_buffers P_((void));
|
||||
void process_args (int argc, char *argv[]);
|
||||
void initialize_buffers (void);
|
||||
|
||||
/* makepath.c */
|
||||
int make_path P_((char *argpath, int mode, int parent_mode,
|
||||
uid_t owner, gid_t group, char *verbose_fmt_string));
|
||||
int make_path (char *argpath, int mode, int parent_mode,
|
||||
uid_t owner, gid_t group, char *verbose_fmt_string);
|
||||
|
||||
/* tar.c */
|
||||
void write_out_tar_header P_((struct new_cpio_header *file_hdr, int out_des));
|
||||
int null_block P_((long *block, int size));
|
||||
void read_in_tar_header P_((struct new_cpio_header *file_hdr, int in_des));
|
||||
int otoa P_((char *s, unsigned long *n));
|
||||
int is_tar_header P_((char *buf));
|
||||
int is_tar_filename_too_long P_((char *name));
|
||||
void write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des);
|
||||
int null_block (long *block, int size);
|
||||
void read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des);
|
||||
int otoa (char *s, unsigned long *n);
|
||||
int is_tar_header (char *buf);
|
||||
int is_tar_filename_too_long (char *name);
|
||||
|
||||
/* userspec.c */
|
||||
#ifndef __MSDOS__
|
||||
char *parse_user_spec P_((char *name, uid_t *uid, gid_t *gid,
|
||||
char **username, char **groupname));
|
||||
char *parse_user_spec (char *name, uid_t *uid, gid_t *gid,
|
||||
char **username, char **groupname);
|
||||
#endif
|
||||
|
||||
/* util.c */
|
||||
void tape_empty_output_buffer P_((int out_des));
|
||||
void disk_empty_output_buffer P_((int out_des));
|
||||
void swahw_array P_((char *ptr, int count));
|
||||
void tape_buffered_write P_((char *in_buf, int out_des, long num_bytes));
|
||||
void tape_buffered_read P_((char *in_buf, int in_des, long num_bytes));
|
||||
int tape_buffered_peek P_((char *peek_buf, int in_des, int num_bytes));
|
||||
void tape_toss_input P_((int in_des, long num_bytes));
|
||||
void copy_files_tape_to_disk P_((int in_des, int out_des, long num_bytes));
|
||||
void copy_files_disk_to_tape P_((int in_des, int out_des, long num_bytes, char *filename));
|
||||
void copy_files_disk_to_disk P_((int in_des, int out_des, long num_bytes, char *filename));
|
||||
void warn_if_file_changed P_((char *file_name, unsigned long old_file_size,
|
||||
unsigned long old_file_mtime));
|
||||
void create_all_directories P_((char *name));
|
||||
void prepare_append P_((int out_file_des));
|
||||
char *find_inode_file P_((unsigned long node_num,
|
||||
unsigned long major_num, unsigned long minor_num));
|
||||
void add_inode P_((unsigned long node_num, char *file_name,
|
||||
unsigned long major_num, unsigned long minor_num));
|
||||
int open_archive P_((char *file));
|
||||
void tape_offline P_((int tape_des));
|
||||
void get_next_reel P_((int tape_des));
|
||||
void set_new_media_message P_((char *message));
|
||||
void tape_empty_output_buffer (int out_des);
|
||||
void disk_empty_output_buffer (int out_des);
|
||||
void swahw_array (char *ptr, int count);
|
||||
void tape_buffered_write (char *in_buf, int out_des, off_t num_bytes);
|
||||
void tape_buffered_read (char *in_buf, int in_des, off_t num_bytes);
|
||||
int tape_buffered_peek (char *peek_buf, int in_des, int num_bytes);
|
||||
void tape_toss_input (int in_des, off_t num_bytes);
|
||||
void copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes);
|
||||
void copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes, char *filename);
|
||||
void copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes, char *filename);
|
||||
void warn_if_file_changed (char *file_name, unsigned long old_file_size,
|
||||
off_t old_file_mtime);
|
||||
void create_all_directories (char *name);
|
||||
void prepare_append (int out_file_des);
|
||||
char *find_inode_file (unsigned long node_num,
|
||||
unsigned long major_num, unsigned long minor_num);
|
||||
void add_inode (unsigned long node_num, char *file_name,
|
||||
unsigned long major_num, unsigned long minor_num);
|
||||
int open_archive (char *file);
|
||||
void tape_offline (int tape_des);
|
||||
void get_next_reel (int tape_des);
|
||||
void set_new_media_message (char *message);
|
||||
#if defined(__MSDOS__) && !defined(__GNUC__)
|
||||
int chown P_((char *path, int owner, int group));
|
||||
int chown (char *path, int owner, int group);
|
||||
#endif
|
||||
#ifdef __TURBOC__
|
||||
int utime P_((char *filename, struct utimbuf *utb));
|
||||
int utime (char *filename, struct utimbuf *utb);
|
||||
#endif
|
||||
#ifdef HPUX_CDF
|
||||
char *add_cdf_double_slashes P_((char *filename));
|
||||
char *add_cdf_double_slashes (char *filename);
|
||||
#endif
|
||||
|
||||
#define DISK_IO_BLOCK_SIZE (512)
|
||||
void write_nuls_to_file (off_t num_bytes, int out_des,
|
||||
void (*writer) (char *in_buf,
|
||||
int out_des, off_t num_bytes));
|
||||
#define DISK_IO_BLOCK_SIZE 512
|
||||
|
||||
/* FIXME: Move to system.h? */
|
||||
#ifndef SYMLINK_USES_UMASK
|
||||
@ -198,3 +202,20 @@ char *add_cdf_double_slashes P_((char *filename));
|
||||
#else
|
||||
# define UMASKED_SYMLINK(name1,name2,mode) umasked_symlink(name1,name2,mode)
|
||||
#endif /* SYMLINK_USES_UMASK */
|
||||
|
||||
void set_perms (int fd, struct cpio_file_stat *header);
|
||||
void set_file_times (int fd, const char *name, unsigned long atime,
|
||||
unsigned long mtime);
|
||||
void stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st);
|
||||
void cpio_safer_name_suffix (char *name, bool link_target,
|
||||
bool absolute_names, bool strip_leading_dots);
|
||||
|
||||
/* FIXME: These two defines should be defined in paxutils */
|
||||
#define LG_8 3
|
||||
#define LG_16 4
|
||||
|
||||
uintmax_t from_ascii (char const *where, size_t digs, unsigned logbase);
|
||||
|
||||
#define FROM_OCTAL(f) from_ascii (f, sizeof f, LG_8)
|
||||
#define FROM_HEX(f) from_ascii (f, sizeof f, LG_16)
|
||||
|
||||
|
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
|
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
/* Include sys/types.h and sys/stat.h before this file. */
|
||||
|
||||
|
14
src/global.c
14
src/global.c
@ -1,5 +1,5 @@
|
||||
/* global.c - global variables and initial values for cpio.
|
||||
Copyright (C) 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
@ -139,7 +140,7 @@ char *archive_name = NULL;
|
||||
char *rsh_command_option = NULL;
|
||||
|
||||
/* CRC checksum. */
|
||||
unsigned long crc;
|
||||
unsigned int crc;
|
||||
|
||||
/* Input and output buffers. */
|
||||
char *input_buffer, *output_buffer;
|
||||
@ -165,9 +166,6 @@ long long input_bytes, output_bytes;
|
||||
long input_bytes, output_bytes;
|
||||
#endif
|
||||
|
||||
/* 512 bytes of 0; used for various padding operations. */
|
||||
char zeros_512[512];
|
||||
|
||||
/* Saving of argument values for later reference. */
|
||||
char *directory_name = NULL;
|
||||
char **save_patterns;
|
||||
|
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
|
377
src/main.c
377
src/main.c
@ -1,5 +1,6 @@
|
||||
/* main.c - main program and argument processing for cpio.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +12,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
/* Written by Phil Nelson <phil@cs.wwu.edu>,
|
||||
David MacKenzie <djm@gnu.ai.mit.edu>,
|
||||
@ -21,6 +23,7 @@
|
||||
and Sergey Poznyakoff <gray@mirddin.farlep.net> */
|
||||
|
||||
#include <system.h>
|
||||
#include <paxlib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
@ -29,7 +32,7 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
#include "filetypes.h"
|
||||
@ -37,10 +40,11 @@
|
||||
#include "dstring.h"
|
||||
#include "extern.h"
|
||||
#include <rmt.h>
|
||||
#include <localedir.h>
|
||||
#include <rmt-command.h>
|
||||
|
||||
enum cpio_options {
|
||||
NO_ABSOLUTE_FILENAMES_OPTION=256,
|
||||
NO_ABSOLUTE_FILENAMES_OPTION=256,
|
||||
ABSOLUTE_FILENAMES_OPTION,
|
||||
NO_PRESERVE_OWNER_OPTION,
|
||||
ONLY_VERIFY_CRC_OPTION,
|
||||
RENAME_BATCH_FILE_OPTION,
|
||||
@ -50,8 +54,9 @@ enum cpio_options {
|
||||
FORCE_LOCAL_OPTION,
|
||||
DEBUG_OPTION,
|
||||
BLOCK_SIZE_OPTION,
|
||||
TO_STDOUT_OPTION,
|
||||
|
||||
TO_STDOUT_OPTION,
|
||||
|
||||
HANG_OPTION,
|
||||
USAGE_OPTION,
|
||||
LICENSE_OPTION,
|
||||
VERSION_OPTION
|
||||
@ -71,129 +76,156 @@ Examples:\n\
|
||||
|
||||
/* Print usage error message and exit with error. */
|
||||
|
||||
#define USAGE_ERROR(args) do { error args; exit(2); } while (0)
|
||||
#define CHECK_USAGE(cond, opt, mode_opt) \
|
||||
if (cond) USAGE_ERROR((0, 0, _("%s is meaningless with %s"), opt, mode_opt));
|
||||
if (cond) \
|
||||
ERROR((PAXEXIT_FAILURE, 0, _("%s is meaningless with %s"), opt, mode_opt));
|
||||
|
||||
static struct argp_option options[] = {
|
||||
/* ********** */
|
||||
#define GRID 10
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Main operation mode:"), 10},
|
||||
N_("Main operation mode:"), GRID },
|
||||
{"create", 'o', 0, 0,
|
||||
N_("Create the archive (run in copy-out mode)"), 10},
|
||||
N_("Create the archive (run in copy-out mode)"), GRID },
|
||||
{"extract", 'i', 0, 0,
|
||||
N_("Extract files from an archive (run in copy-in mode)")},
|
||||
N_("Extract files from an archive (run in copy-in mode)"), GRID },
|
||||
{"pass-through", 'p', 0, 0,
|
||||
N_("Run in copy-pass mode"), 10},
|
||||
N_("Run in copy-pass mode"), GRID },
|
||||
{"list", 't', 0, 0,
|
||||
N_("Print a table of contents of the input"), 10},
|
||||
|
||||
{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},
|
||||
N_("Print a table of contents of the input"), GRID },
|
||||
#undef GRID
|
||||
|
||||
/* ********** */
|
||||
#define GRID 100
|
||||
{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,
|
||||
N_("Link files instead of copying them, when possible"), 410},
|
||||
N_("Link files instead of copying them, when possible"), GRID+1 },
|
||||
|
||||
#undef GRID
|
||||
|
||||
/* ********** */
|
||||
#define GRID 500
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Operation modifiers valid for copy-out and copy-pass modes:"), 500},
|
||||
N_("Operation modifiers valid in copy-in and copy-out modes:"), GRID },
|
||||
{"absolute-filenames", ABSOLUTE_FILENAMES_OPTION, 0, 0,
|
||||
N_("Do not strip file system prefix components from the file names"),
|
||||
GRID+1 },
|
||||
{"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
|
||||
N_("Create all files relative to the current directory"), GRID+1 },
|
||||
#undef GRID
|
||||
/* ********** */
|
||||
#define GRID 600
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Operation modifiers valid in copy-out and copy-pass modes:"), GRID },
|
||||
{"null", '0', 0, 0,
|
||||
N_("A list of filenames is terminated by a null character instead of a newline"), 510 },
|
||||
N_("A list of filenames is terminated by a null character instead of a newline"), GRID+1 },
|
||||
{NULL, 'I', N_("[[USER@]HOST:]FILE-NAME"), 0,
|
||||
N_("Archive filename to use instead of standard input. Optional USER and HOST specify the user and host names in case of a remote archive"), 510},
|
||||
N_("Archive filename to use instead of standard input. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
|
||||
{"dereference", 'L', 0, 0,
|
||||
N_("Dereference symbolic links (copy the files that they point to instead of copying the links)."), 510},
|
||||
N_("Dereference symbolic links (copy the files that they point to instead of copying the links)."), GRID+1 },
|
||||
{"owner", 'R', N_("[USER][:.][GROUP]"), 0,
|
||||
N_("Set the ownership of all files created to the specified USER and/or GROUP"), 510},
|
||||
{"sparse", SPARSE_OPTION, NULL, 0,
|
||||
N_("Write files with large blocks of zeros as sparse files"), 510},
|
||||
N_("Set the ownership of all files created to the specified USER and/or GROUP"), GRID+1 },
|
||||
{"reset-access-time", 'a', NULL, 0,
|
||||
N_("Reset the access times of files after reading them"), 510},
|
||||
N_("Reset the access times of files after reading them"), GRID+1 },
|
||||
|
||||
#undef GRID
|
||||
/* ********** */
|
||||
#define GRID 700
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Operation modifiers valid for copy-in and copy-pass modes:"), 600},
|
||||
N_("Operation modifiers valid in copy-in and copy-pass modes:"), GRID },
|
||||
{"preserve-modification-time", 'm', 0, 0,
|
||||
N_("Retain previous file modification times when creating files"), 610},
|
||||
N_("Retain previous file modification times when creating files"), GRID+1 },
|
||||
{"make-directories", 'd', 0, 0,
|
||||
N_("Create leading directories where needed"), 610},
|
||||
N_("Create leading directories where needed"), GRID+1 },
|
||||
{"no-preserve-owner", NO_PRESERVE_OWNER_OPTION, 0, 0,
|
||||
N_("Do not change the ownership of the files"), 610},
|
||||
N_("Do not change the ownership of the files"), GRID+1 },
|
||||
{"unconditional", 'u', NULL, 0,
|
||||
N_("Replace all files unconditionally"), 610},
|
||||
|
||||
N_("Replace all files unconditionally"), GRID+1 },
|
||||
{"sparse", SPARSE_OPTION, NULL, 0,
|
||||
N_("Write files with large blocks of zeros as sparse files"), GRID+1 },
|
||||
#undef GRID
|
||||
|
||||
/* ********** */
|
||||
#define GRID 800
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Informative options:"), 700 },
|
||||
N_("Informative options:"), GRID },
|
||||
|
||||
{"help", '?', 0, 0, N_("Give this help list"), -1},
|
||||
{"usage", USAGE_OPTION, 0, 0, N_("Give a short usage message"), -1},
|
||||
@ -201,7 +233,9 @@ static struct argp_option options[] = {
|
||||
{"version", VERSION_OPTION, 0, 0, N_("Print program version"), -1},
|
||||
/* FIXME -V (--dot) conflicts with the default short option for
|
||||
--version */
|
||||
|
||||
{"HANG", HANG_OPTION, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
|
||||
N_("hang for SECS seconds (default 3600)"), 0},
|
||||
#undef GRID
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@ -224,8 +258,8 @@ license ()
|
||||
" GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
" You should have received a copy of the GNU General Public License\n"
|
||||
" along with GNU cpio; if not, write to the Free Software\n"
|
||||
" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\n"));
|
||||
" along with GNU cpio; if not, write to the Free Software Foundation,\n"
|
||||
" Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n\n"));
|
||||
exit (0);
|
||||
}
|
||||
|
||||
@ -269,6 +303,7 @@ warn_control (char *arg)
|
||||
static error_t
|
||||
parse_opt (int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
static volatile int _argp_hang;
|
||||
switch (key)
|
||||
{
|
||||
case '0': /* Read null-terminated filenames. */
|
||||
@ -301,7 +336,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
|
||||
case 'c': /* Use the old portable ASCII format. */
|
||||
if (archive_format != arf_unknown)
|
||||
USAGE_ERROR ((0, 0, _("Archive format multiply defined")));
|
||||
error (0, EXIT_FAILURE, _("Archive format multiply defined"));
|
||||
#ifdef SVR4_COMPAT
|
||||
archive_format = arf_newascii; /* -H newc. */
|
||||
#else
|
||||
@ -333,7 +368,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
|
||||
case 'H': /* Header format name. */
|
||||
if (archive_format != arf_unknown)
|
||||
USAGE_ERROR ((0, 0, _("Archive format multiply defined")));
|
||||
error (PAXEXIT_FAILURE, 0, _("Archive format multiply defined"));
|
||||
if (!strcasecmp (arg, "crc"))
|
||||
archive_format = arf_crcascii;
|
||||
else if (!strcasecmp (arg, "newc"))
|
||||
@ -358,7 +393,7 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
|
||||
|
||||
case 'i': /* Copy-in mode. */
|
||||
if (copy_function != 0)
|
||||
USAGE_ERROR ((0, 0, _("Mode already defined")));
|
||||
error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
|
||||
copy_function = process_copy_in;
|
||||
break;
|
||||
|
||||
@ -394,17 +429,21 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
|
||||
case NO_ABSOLUTE_FILENAMES_OPTION: /* --no-absolute-filenames */
|
||||
no_abs_paths_flag = true;
|
||||
break;
|
||||
|
||||
|
||||
case ABSOLUTE_FILENAMES_OPTION: /* --absolute-filenames */
|
||||
no_abs_paths_flag = false;
|
||||
break;
|
||||
|
||||
case NO_PRESERVE_OWNER_OPTION: /* --no-preserve-owner */
|
||||
if (set_owner_flag || set_group_flag)
|
||||
USAGE_ERROR ((0, 0,
|
||||
_("--no-preserve-owner cannot be used with --owner")));
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("--no-preserve-owner cannot be used with --owner"));
|
||||
no_chown_flag = true;
|
||||
break;
|
||||
|
||||
case 'o': /* Copy-out mode. */
|
||||
if (copy_function != 0)
|
||||
USAGE_ERROR ((0, 0, _("Mode already defined")));
|
||||
error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
|
||||
copy_function = process_copy_out;
|
||||
break;
|
||||
|
||||
@ -418,7 +457,7 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
|
||||
|
||||
case 'p': /* Copy-pass mode. */
|
||||
if (copy_function != 0)
|
||||
USAGE_ERROR ((0, 0, _("Mode already defined")));
|
||||
error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
|
||||
copy_function = process_copy_pass;
|
||||
break;
|
||||
|
||||
@ -440,25 +479,26 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
|
||||
|
||||
case 'R': /* Set the owner. */
|
||||
if (no_chown_flag)
|
||||
USAGE_ERROR ((0, 0,
|
||||
_("--owner cannot be used with --no-preserve-owner")));
|
||||
{
|
||||
char *e, *u, *g;
|
||||
|
||||
e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
|
||||
if (e)
|
||||
error (2, 0, "%s: %s", arg, e);
|
||||
if (u)
|
||||
{
|
||||
free (u);
|
||||
set_owner_flag = true;
|
||||
}
|
||||
if (g)
|
||||
{
|
||||
free (g);
|
||||
set_group_flag = true;
|
||||
}
|
||||
}
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("--owner cannot be used with --no-preserve-owner"));
|
||||
else
|
||||
{
|
||||
char *e, *u, *g;
|
||||
|
||||
e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
|
||||
if (e)
|
||||
error (PAXEXIT_FAILURE, 0, "%s: %s", arg, e);
|
||||
if (u)
|
||||
{
|
||||
free (u);
|
||||
set_owner_flag = true;
|
||||
}
|
||||
if (g)
|
||||
{
|
||||
free (g);
|
||||
set_group_flag = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 's': /* Swap bytes. */
|
||||
@ -507,6 +547,12 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
|
||||
case TO_STDOUT_OPTION:
|
||||
to_stdout_option = true;
|
||||
break;
|
||||
|
||||
case HANG_OPTION:
|
||||
_argp_hang = atoi (arg ? arg : "3600");
|
||||
while (_argp_hang-- > 0)
|
||||
sleep (1);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
|
||||
@ -552,9 +598,9 @@ process_args (int argc, char *argv[])
|
||||
int index;
|
||||
|
||||
if (argc < 2)
|
||||
USAGE_ERROR ((0, 0,
|
||||
_("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
|
||||
program_name, program_name));
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
|
||||
program_name, program_name);
|
||||
|
||||
xstat = lstat;
|
||||
|
||||
@ -568,9 +614,9 @@ process_args (int argc, char *argv[])
|
||||
if (table_flag)
|
||||
copy_function = process_copy_in;
|
||||
else
|
||||
USAGE_ERROR ((0, 0,
|
||||
_("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
|
||||
program_name, program_name));
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
|
||||
program_name, program_name);
|
||||
}
|
||||
|
||||
/* Work around for pcc bug. */
|
||||
@ -584,7 +630,6 @@ process_args (int argc, char *argv[])
|
||||
CHECK_USAGE(reset_time_flag, "--reset", "--extract");
|
||||
CHECK_USAGE(xstat != lstat, "--dereference", "--extract");
|
||||
CHECK_USAGE(append_flag, "--append", "--extract");
|
||||
CHECK_USAGE(sparse_flag, "--sparse", "--extract");
|
||||
CHECK_USAGE(output_archive_name, "-O", "--extract");
|
||||
if (to_stdout_option)
|
||||
{
|
||||
@ -597,7 +642,8 @@ process_args (int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (archive_name && input_archive_name)
|
||||
USAGE_ERROR((0, 0, _("Both -I and -F are used in copy-in mode")));
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("Both -I and -F are used in copy-in mode"));
|
||||
|
||||
if (archive_format == arf_crcascii)
|
||||
crc_i_flag = true;
|
||||
@ -609,7 +655,7 @@ process_args (int argc, char *argv[])
|
||||
else if (copy_function == copy_out)
|
||||
{
|
||||
if (index != argc)
|
||||
USAGE_ERROR ((0, 0, _("Too many arguments")));
|
||||
error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
|
||||
|
||||
archive_des = 1;
|
||||
CHECK_USAGE(create_dir_flag, "--make-directories", "--create");
|
||||
@ -617,24 +663,24 @@ process_args (int argc, char *argv[])
|
||||
CHECK_USAGE(table_flag, "--list", "--create");
|
||||
CHECK_USAGE(unconditional_flag, "--unconditional", "--create");
|
||||
CHECK_USAGE(link_flag, "--link", "--create");
|
||||
CHECK_USAGE(sparse_flag, "--sparse", "--create");
|
||||
CHECK_USAGE(retain_time_flag, "--preserve-modification-time",
|
||||
"--create");
|
||||
CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--create");
|
||||
CHECK_USAGE(set_owner_flag||set_group_flag, "--owner", "--create");
|
||||
CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--create");
|
||||
CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
|
||||
"--create");
|
||||
CHECK_USAGE(to_stdout_option, "--to-stdout", "--create");
|
||||
|
||||
if (append_flag && !(archive_name || output_archive_name))
|
||||
USAGE_ERROR ((0, 0,
|
||||
_("--append is used but no archive file name is given (use -F or -O options")));
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("--append is used but no archive file name is given (use -F or -O options)"));
|
||||
|
||||
CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--create");
|
||||
CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames", "--create");
|
||||
CHECK_USAGE(input_archive_name, "-I", "--create");
|
||||
if (archive_name && output_archive_name)
|
||||
USAGE_ERROR ((0, 0, _("Both -O and -F are used in copy-out mode")));
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("Both -O and -F are used in copy-out mode"));
|
||||
|
||||
if (archive_format == arf_unknown)
|
||||
archive_format = arf_binary;
|
||||
@ -644,12 +690,14 @@ process_args (int argc, char *argv[])
|
||||
else
|
||||
{
|
||||
/* Copy pass. */
|
||||
if (index != argc - 1)
|
||||
USAGE_ERROR ((0, 0, _("Too many arguments")));
|
||||
if (index < argc - 1)
|
||||
error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
|
||||
else if (index > argc - 1)
|
||||
error (PAXEXIT_FAILURE, 0, _("Not enough arguments"));
|
||||
|
||||
if (archive_format != arf_unknown)
|
||||
USAGE_ERROR((0, 0,
|
||||
_("Archive format is not specified in copy-pass mode (use --format option)")));
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("Archive format is not specified in copy-pass mode (use --format option)"));
|
||||
|
||||
CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--pass-through");
|
||||
CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
|
||||
@ -660,6 +708,8 @@ process_args (int argc, char *argv[])
|
||||
CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--pass-through");
|
||||
CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames",
|
||||
"--pass-through");
|
||||
CHECK_USAGE(no_abs_paths_flag, "--absolute-pathnames",
|
||||
"--pass-through");
|
||||
CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through");
|
||||
|
||||
directory_name = argv[index];
|
||||
@ -668,11 +718,12 @@ process_args (int argc, char *argv[])
|
||||
if (archive_name)
|
||||
{
|
||||
if (copy_function != copy_in && copy_function != copy_out)
|
||||
USAGE_ERROR ((0, 0,
|
||||
_("-F can be used only with --create or --extract")));
|
||||
error (PAXEXIT_FAILURE, 0,
|
||||
_("-F can be used only with --create or --extract"));
|
||||
archive_des = open_archive (archive_name);
|
||||
if (archive_des < 0)
|
||||
error (1, errno, "%s", archive_name);
|
||||
error (PAXEXIT_FAILURE, errno, _("Cannot open %s"),
|
||||
quotearg_colon (archive_name));
|
||||
}
|
||||
|
||||
/* Prevent SysV non-root users from giving away files inadvertantly.
|
||||
@ -725,33 +776,19 @@ initialize_buffers ()
|
||||
out_buff = output_buffer;
|
||||
output_size = 0;
|
||||
output_bytes = 0;
|
||||
|
||||
/* Clear the block of zeros. */
|
||||
bzero (zeros_512, 512);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef HAVE_LOCALE_H
|
||||
setlocale (LC_ALL, "");
|
||||
#endif
|
||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
textdomain (PACKAGE);
|
||||
|
||||
program_name = argv[0];
|
||||
umask (0);
|
||||
|
||||
#ifdef __TURBOC__
|
||||
_fmode = O_BINARY; /* Put stdin and stdout in binary mode. */
|
||||
#endif
|
||||
#ifdef __EMX__ /* gcc on OS/2. */
|
||||
_response (&argc, &argv);
|
||||
_wildcard (&argc, &argv);
|
||||
#endif
|
||||
|
||||
process_args (argc, argv);
|
||||
|
||||
|
||||
initialize_buffers ();
|
||||
|
||||
(*copy_function) ();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* makepath.c -- Ensure that a directory path exists.
|
||||
Copyright (C) 1990 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu> and
|
||||
Jim Meyering <meyering@cs.utexas.edu>. */
|
||||
@ -23,46 +24,11 @@
|
||||
come together again in the future. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define alloca __builtin_alloca
|
||||
#else
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#ifdef _AIX
|
||||
#pragma alloca
|
||||
#else
|
||||
char *alloca ();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#include <paxlib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#ifdef STDC_HEADERS
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
|
||||
#include <string.h>
|
||||
#ifndef index
|
||||
#define index strchr
|
||||
#endif
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
/* Ensure that the directory ARGPATH exists.
|
||||
Remove any trailing slashes from ARGPATH before calling this function.
|
||||
@ -126,7 +92,7 @@ make_path (char *argpath,
|
||||
slash = dirpath;
|
||||
while (*slash == '/')
|
||||
slash++;
|
||||
while ((slash = index (slash, '/')))
|
||||
while ((slash = strchr (slash, '/')))
|
||||
{
|
||||
#ifdef HPUX_CDF
|
||||
int iscdf;
|
||||
@ -164,7 +130,7 @@ make_path (char *argpath,
|
||||
#endif
|
||||
)
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
chown_error_details (dirpath, owner, group);
|
||||
retval = 1;
|
||||
}
|
||||
if (re_protect)
|
||||
@ -231,23 +197,23 @@ make_path (char *argpath,
|
||||
#endif
|
||||
)
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
chown_error_details (dirpath, owner, group);
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
/* chown may have turned off some permission bits we wanted. */
|
||||
if ((mode & 07000) != 0 && chmod (dirpath, mode))
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
retval = 1;
|
||||
}
|
||||
/* chown may have turned off some permission bits we wanted. */
|
||||
if ((mode & 07000) != 0 && chmod (dirpath, mode))
|
||||
{
|
||||
chmod_error_details (dirpath, mode);
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
/* If the mode for leading directories didn't include owner "wx"
|
||||
privileges, we have to reset their protections to the correct
|
||||
value. */
|
||||
for (p = leading_dirs; p != NULL; p = p->next)
|
||||
{
|
||||
*(p->dirname_end) = '\0';
|
||||
*p->dirname_end = '\0';
|
||||
#if 0
|
||||
/* cpio always calls make_path with parent mode 0700, so
|
||||
we don't have to do this. If we ever do have to do this,
|
||||
@ -255,7 +221,7 @@ make_path (char *argpath,
|
||||
bit so we don't break HP CDF's. */
|
||||
if (chmod (dirpath, parent_mode))
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
chmod_error_details (dirpath, parent_mode);
|
||||
retval = 1;
|
||||
}
|
||||
#endif
|
||||
@ -286,12 +252,12 @@ make_path (char *argpath,
|
||||
#endif
|
||||
)
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
chown_error_details (dirpath, owner, group);
|
||||
retval = 1;
|
||||
}
|
||||
if (chmod (dirpath, mode))
|
||||
{
|
||||
error (0, errno, "%s", dirpath);
|
||||
chmod_error_details (dirpath, mode);
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
|
63
src/tar.c
63
src/tar.c
@ -1,5 +1,5 @@
|
||||
/* tar.c - read in write tar headers for cpio
|
||||
Copyright (C) 1992, 2001, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 2001, 2004, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
@ -112,10 +113,10 @@ to_oct (register long value, register int digits, register char *where)
|
||||
/* Compute and return a checksum for TAR_HDR,
|
||||
counting the checksum bytes as if they were spaces. */
|
||||
|
||||
unsigned long
|
||||
unsigned int
|
||||
tar_checksum (struct tar_header *tar_hdr)
|
||||
{
|
||||
unsigned long sum = 0;
|
||||
unsigned int sum = 0;
|
||||
char *p = (char *) tar_hdr;
|
||||
char *q = p + TARRECORDSIZE;
|
||||
int i;
|
||||
@ -136,13 +137,13 @@ tar_checksum (struct tar_header *tar_hdr)
|
||||
descriptor OUT_DES. */
|
||||
|
||||
void
|
||||
write_out_tar_header (struct new_cpio_header *file_hdr, int out_des)
|
||||
write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des)
|
||||
{
|
||||
int name_len;
|
||||
union tar_record tar_rec;
|
||||
struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
|
||||
|
||||
bzero ((char *) &tar_rec, TARRECORDSIZE);
|
||||
memset (&tar_rec, 0, sizeof tar_rec);
|
||||
|
||||
/* process_copy_out must ensure that file_hdr->c_name is short enough,
|
||||
or we will lose here. */
|
||||
@ -254,7 +255,7 @@ null_block (long *block, int size)
|
||||
into FILE_HDR. */
|
||||
|
||||
void
|
||||
read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des)
|
||||
{
|
||||
long bytes_skipped = 0;
|
||||
int warned = false;
|
||||
@ -280,7 +281,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
|
||||
#endif
|
||||
{
|
||||
file_hdr->c_name = "TRAILER!!!";
|
||||
file_hdr->c_name = CPIO_TRAILER_NAME;
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
@ -290,7 +291,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
|
||||
while (1)
|
||||
{
|
||||
otoa (tar_hdr->chksum, &file_hdr->c_chksum);
|
||||
file_hdr->c_chksum = FROM_OCTAL (tar_hdr->chksum);
|
||||
|
||||
if (file_hdr->c_chksum != tar_checksum (tar_hdr))
|
||||
{
|
||||
@ -307,8 +308,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
error (0, 0, _("invalid header: checksum error"));
|
||||
warned = true;
|
||||
}
|
||||
bcopy (((char *) &tar_rec) + 1, (char *) &tar_rec,
|
||||
TARRECORDSIZE - 1);
|
||||
memmove (&tar_rec, ((char *) &tar_rec) + 1, TARRECORDSIZE - 1);
|
||||
tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
|
||||
++bytes_skipped;
|
||||
continue;
|
||||
@ -319,7 +319,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
else
|
||||
file_hdr->c_name = stash_tar_filename (tar_hdr->prefix, tar_hdr->name);
|
||||
file_hdr->c_nlink = 1;
|
||||
otoa (tar_hdr->mode, &file_hdr->c_mode);
|
||||
file_hdr->c_mode = FROM_OCTAL (tar_hdr->mode);
|
||||
file_hdr->c_mode = file_hdr->c_mode & 07777;
|
||||
/* Debian hack: This version of cpio uses the -n flag also to extract
|
||||
tar archives using the numeric UID/GID instead of the user/group
|
||||
@ -328,17 +328,17 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
&& (uidp = getuidbyname (tar_hdr->uname)))
|
||||
file_hdr->c_uid = *uidp;
|
||||
else
|
||||
otoa (tar_hdr->uid, &file_hdr->c_uid);
|
||||
file_hdr->c_uid = FROM_OCTAL (tar_hdr->uid);
|
||||
|
||||
if (archive_format == arf_ustar && !numeric_uid
|
||||
&& (gidp = getgidbyname (tar_hdr->gname)))
|
||||
file_hdr->c_gid = *gidp;
|
||||
else
|
||||
otoa (tar_hdr->gid, &file_hdr->c_gid);
|
||||
otoa (tar_hdr->size, &file_hdr->c_filesize);
|
||||
otoa (tar_hdr->mtime, &file_hdr->c_mtime);
|
||||
otoa (tar_hdr->devmajor, (unsigned long *) &file_hdr->c_rdev_maj);
|
||||
otoa (tar_hdr->devminor, (unsigned long *) &file_hdr->c_rdev_min);
|
||||
file_hdr->c_gid = FROM_OCTAL (tar_hdr->gid);
|
||||
file_hdr->c_filesize = FROM_OCTAL (tar_hdr->size);
|
||||
file_hdr->c_mtime = FROM_OCTAL (tar_hdr->mtime);
|
||||
file_hdr->c_rdev_maj = FROM_OCTAL (tar_hdr->devmajor);
|
||||
file_hdr->c_rdev_min = FROM_OCTAL (tar_hdr->devminor);
|
||||
file_hdr->c_tar_linkname = NULL;
|
||||
|
||||
switch (tar_hdr->typeflag)
|
||||
@ -409,26 +409,6 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
|
||||
warn_junk_bytes (bytes_skipped);
|
||||
}
|
||||
|
||||
/* Convert the string of octal digits S into a number and store
|
||||
it in *N. Return nonzero if the whole string was converted,
|
||||
zero if there was something after the number.
|
||||
Skip leading and trailing spaces. */
|
||||
|
||||
int
|
||||
otoa (char *s, unsigned long *n)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
|
||||
while (*s == ' ')
|
||||
++s;
|
||||
while (*s >= '0' && *s <= '7')
|
||||
val = 8 * val + *s++ - '0';
|
||||
while (*s == ' ')
|
||||
++s;
|
||||
*n = val;
|
||||
return *s == '\0';
|
||||
}
|
||||
|
||||
/* Return
|
||||
2 if BUF is a valid POSIX tar header (the checksum is correct
|
||||
and it has the "ustar" magic string),
|
||||
@ -441,7 +421,7 @@ is_tar_header (char *buf)
|
||||
struct tar_header *tar_hdr = (struct tar_header *) buf;
|
||||
unsigned long chksum;
|
||||
|
||||
otoa (tar_hdr->chksum, &chksum);
|
||||
chksum = FROM_OCTAL (tar_hdr->chksum);
|
||||
|
||||
if (chksum != tar_checksum (tar_hdr))
|
||||
return 0;
|
||||
@ -473,7 +453,6 @@ is_tar_filename_too_long (char *name)
|
||||
{
|
||||
int whole_name_len;
|
||||
int prefix_name_len;
|
||||
char *p;
|
||||
|
||||
whole_name_len = strlen (name);
|
||||
if (whole_name_len <= TARNAMESIZE)
|
||||
|
@ -14,10 +14,10 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU Library General
|
||||
Public License along with this library; see the file COPYING.LIB.
|
||||
If not, write to the Free Software Foundation, Inc., 51 Franklin
|
||||
Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifndef _TAR_H
|
||||
|
||||
|
@ -11,9 +11,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifndef _TARHDR_H
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* userspec.c -- Parse a user and group string.
|
||||
Copyright (C) 1989, 1990, 1991, 1992, 2001, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1989, 1990, 1991, 1992, 2001,
|
||||
2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +12,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
@ -72,7 +74,7 @@ extern struct group *getgrgid (gid_t gid);
|
||||
otherwise return 0. */
|
||||
|
||||
static int
|
||||
isnumber (const char *str)
|
||||
isnumber_p (const char *str)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (!isdigit (*str))
|
||||
@ -111,9 +113,9 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
|
||||
V_STRDUP (spec, spec_arg);
|
||||
|
||||
/* Find the separator if there is one. */
|
||||
separator = index (spec, ':');
|
||||
separator = strchr (spec, ':');
|
||||
if (separator == NULL)
|
||||
separator = index (spec, '.');
|
||||
separator = strchr (spec, '.');
|
||||
|
||||
/* Replace separator with a NUL. */
|
||||
if (separator != NULL)
|
||||
@ -136,7 +138,7 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
|
||||
if (pwd == NULL)
|
||||
{
|
||||
|
||||
if (!isnumber (u))
|
||||
if (!isnumber_p (u))
|
||||
error_msg = _("invalid user");
|
||||
else
|
||||
{
|
||||
@ -182,7 +184,7 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
|
||||
grp = getgrnam (g);
|
||||
if (grp == NULL)
|
||||
{
|
||||
if (!isnumber (g))
|
||||
if (!isnumber_p (g))
|
||||
error_msg = _("invalid group");
|
||||
else
|
||||
*gid = atoi (g);
|
||||
|
439
src/util.c
439
src/util.c
@ -1,5 +1,6 @@
|
||||
/* util.c - Several utility routines for cpio.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 1991, 1992, 2001, 2004,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -11,9 +12,10 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
@ -23,15 +25,21 @@
|
||||
#include "cpiohdr.h"
|
||||
#include "dstring.h"
|
||||
#include "extern.h"
|
||||
#include <paxlib.h>
|
||||
#include "filetypes.h"
|
||||
#include <safe-read.h>
|
||||
#include <full-write.h>
|
||||
#include <rmt.h>
|
||||
#include <hash.h>
|
||||
#include <utimens.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef HAVE_SYS_MTIO_H
|
||||
#ifdef HAVE_SYS_IO_TRIOCTL_H
|
||||
#include <sys/io/trioctl.h>
|
||||
#endif
|
||||
#include <sys/mtio.h>
|
||||
# ifdef HAVE_SYS_IO_TRIOCTL_H
|
||||
# include <sys/io/trioctl.h>
|
||||
# endif
|
||||
# include <sys/mtio.h>
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_ERRNO
|
||||
@ -90,6 +98,8 @@ tape_empty_output_buffer (int out_des)
|
||||
output_size = 0;
|
||||
}
|
||||
|
||||
static int sparse_write (int fildes, char *buf, unsigned int nbyte);
|
||||
|
||||
/* Write `output_size' bytes of `output_buffer' to file
|
||||
descriptor OUT_DES and reset `output_size' and `out_buff'.
|
||||
If `swapping_halfwords' or `swapping_bytes' is set,
|
||||
@ -207,7 +217,7 @@ tape_fill_input_buffer (int in_des, int num_bytes)
|
||||
Exit with an error if end of file is reached. */
|
||||
|
||||
static int
|
||||
disk_fill_input_buffer (int in_des, int num_bytes)
|
||||
disk_fill_input_buffer (int in_des, off_t num_bytes)
|
||||
{
|
||||
in_buff = input_buffer;
|
||||
num_bytes = (num_bytes < DISK_IO_BLOCK_SIZE) ? num_bytes : DISK_IO_BLOCK_SIZE;
|
||||
@ -227,10 +237,10 @@ disk_fill_input_buffer (int in_des, int num_bytes)
|
||||
When `out_buff' fills up, flush it to file descriptor OUT_DES. */
|
||||
|
||||
void
|
||||
tape_buffered_write (char *in_buf, int out_des, long num_bytes)
|
||||
tape_buffered_write (char *in_buf, int out_des, off_t num_bytes)
|
||||
{
|
||||
register long bytes_left = num_bytes; /* Bytes needing to be copied. */
|
||||
register long space_left; /* Room left in output buffer. */
|
||||
off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
|
||||
off_t space_left; /* Room left in output buffer. */
|
||||
|
||||
while (bytes_left > 0)
|
||||
{
|
||||
@ -241,7 +251,7 @@ tape_buffered_write (char *in_buf, int out_des, long num_bytes)
|
||||
{
|
||||
if (bytes_left < space_left)
|
||||
space_left = bytes_left;
|
||||
bcopy (in_buf, out_buff, (unsigned) space_left);
|
||||
memcpy (out_buff, in_buf, (unsigned) space_left);
|
||||
out_buff += space_left;
|
||||
output_size += space_left;
|
||||
in_buf += space_left;
|
||||
@ -254,10 +264,10 @@ tape_buffered_write (char *in_buf, int out_des, long num_bytes)
|
||||
When `out_buff' fills up, flush it to file descriptor OUT_DES. */
|
||||
|
||||
void
|
||||
disk_buffered_write (char *in_buf, int out_des, long num_bytes)
|
||||
disk_buffered_write (char *in_buf, int out_des, off_t num_bytes)
|
||||
{
|
||||
register long bytes_left = num_bytes; /* Bytes needing to be copied. */
|
||||
register long space_left; /* Room left in output buffer. */
|
||||
off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
|
||||
off_t space_left; /* Room left in output buffer. */
|
||||
|
||||
while (bytes_left > 0)
|
||||
{
|
||||
@ -268,7 +278,7 @@ disk_buffered_write (char *in_buf, int out_des, long num_bytes)
|
||||
{
|
||||
if (bytes_left < space_left)
|
||||
space_left = bytes_left;
|
||||
bcopy (in_buf, out_buff, (unsigned) space_left);
|
||||
memcpy (out_buff, in_buf, (unsigned) space_left);
|
||||
out_buff += space_left;
|
||||
output_size += space_left;
|
||||
in_buf += space_left;
|
||||
@ -282,10 +292,10 @@ disk_buffered_write (char *in_buf, int out_des, long num_bytes)
|
||||
When `in_buff' is exhausted, refill it from file descriptor IN_DES. */
|
||||
|
||||
void
|
||||
tape_buffered_read (char *in_buf, int in_des, long num_bytes)
|
||||
tape_buffered_read (char *in_buf, int in_des, off_t num_bytes)
|
||||
{
|
||||
register long bytes_left = num_bytes; /* Bytes needing to be copied. */
|
||||
register long space_left; /* Bytes to copy from input buffer. */
|
||||
off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
|
||||
off_t space_left; /* Bytes to copy from input buffer. */
|
||||
|
||||
while (bytes_left > 0)
|
||||
{
|
||||
@ -295,7 +305,7 @@ tape_buffered_read (char *in_buf, int in_des, long num_bytes)
|
||||
space_left = bytes_left;
|
||||
else
|
||||
space_left = input_size;
|
||||
bcopy (in_buff, in_buf, (unsigned) space_left);
|
||||
memcpy (in_buf, in_buff, (unsigned) space_left);
|
||||
in_buff += space_left;
|
||||
in_buf += space_left;
|
||||
input_size -= space_left;
|
||||
@ -345,7 +355,7 @@ tape_buffered_peek (char *peek_buf, int in_des, int num_bytes)
|
||||
first block to make room. */
|
||||
int half;
|
||||
half = input_buffer_size / 2;
|
||||
bcopy (input_buffer + half, input_buffer, half);
|
||||
memmove (input_buffer, input_buffer + half, half);
|
||||
in_buff = in_buff - half;
|
||||
append_buf = append_buf - half;
|
||||
}
|
||||
@ -369,17 +379,17 @@ tape_buffered_peek (char *peek_buf, int in_des, int num_bytes)
|
||||
got_bytes = num_bytes;
|
||||
else
|
||||
got_bytes = input_size;
|
||||
bcopy (in_buff, peek_buf, (unsigned) got_bytes);
|
||||
memcpy (peek_buf, in_buff, (unsigned) got_bytes);
|
||||
return got_bytes;
|
||||
}
|
||||
|
||||
/* Skip the next NUM_BYTES bytes of file descriptor IN_DES. */
|
||||
|
||||
void
|
||||
tape_toss_input (int in_des, long num_bytes)
|
||||
tape_toss_input (int in_des, off_t num_bytes)
|
||||
{
|
||||
register long bytes_left = num_bytes; /* Bytes needing to be copied. */
|
||||
register long space_left; /* Bytes to copy from input buffer. */
|
||||
off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
|
||||
off_t space_left; /* Bytes to copy from input buffer. */
|
||||
|
||||
while (bytes_left > 0)
|
||||
{
|
||||
@ -403,18 +413,19 @@ tape_toss_input (int in_des, long num_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_nuls_to_file (long num_bytes, int out_des,
|
||||
void (*writer) (char *in_buf, int out_des, long num_bytes))
|
||||
void
|
||||
write_nuls_to_file (off_t num_bytes, int out_des,
|
||||
void (*writer) (char *in_buf, int out_des, off_t num_bytes))
|
||||
{
|
||||
long blocks;
|
||||
long extra_bytes;
|
||||
long i;
|
||||
|
||||
blocks = num_bytes / 512;
|
||||
extra_bytes = num_bytes % 512;
|
||||
off_t blocks;
|
||||
off_t extra_bytes;
|
||||
off_t i;
|
||||
static char zeros_512[512];
|
||||
|
||||
blocks = num_bytes / sizeof zeros_512;
|
||||
extra_bytes = num_bytes % sizeof zeros_512;
|
||||
for (i = 0; i < blocks; ++i)
|
||||
writer (zeros_512, out_des, 512);
|
||||
writer (zeros_512, out_des, sizeof zeros_512);
|
||||
if (extra_bytes)
|
||||
writer (zeros_512, out_des, extra_bytes);
|
||||
}
|
||||
@ -428,7 +439,7 @@ write_nuls_to_file (long num_bytes, int out_des,
|
||||
NUM_BYTES is the number of bytes to copy. */
|
||||
|
||||
void
|
||||
copy_files_tape_to_disk (int in_des, int out_des, long num_bytes)
|
||||
copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes)
|
||||
{
|
||||
long size;
|
||||
long k;
|
||||
@ -458,13 +469,13 @@ copy_files_tape_to_disk (int in_des, int out_des, long num_bytes)
|
||||
NUM_BYTES is the number of bytes to copy. */
|
||||
|
||||
void
|
||||
copy_files_disk_to_tape (int in_des, int out_des, long num_bytes,
|
||||
copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes,
|
||||
char *filename)
|
||||
{
|
||||
long size;
|
||||
long k;
|
||||
int rc;
|
||||
long original_num_bytes;
|
||||
off_t original_num_bytes;
|
||||
|
||||
original_num_bytes = num_bytes;
|
||||
|
||||
@ -472,14 +483,20 @@ copy_files_disk_to_tape (int in_des, int out_des, long num_bytes,
|
||||
{
|
||||
if (input_size == 0)
|
||||
if (rc = disk_fill_input_buffer (in_des,
|
||||
num_bytes < DISK_IO_BLOCK_SIZE ?
|
||||
num_bytes : DISK_IO_BLOCK_SIZE))
|
||||
num_bytes < DISK_IO_BLOCK_SIZE ?
|
||||
num_bytes : DISK_IO_BLOCK_SIZE))
|
||||
{
|
||||
if (rc > 0)
|
||||
error (0, 0, _("File %s shrunk by %ld bytes, padding with zeros"),
|
||||
filename, num_bytes);
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
error (0, 0,
|
||||
ngettext ("File %s shrunk by %s byte, padding with zeros",
|
||||
"File %s shrunk by %s bytes, padding with zeros",
|
||||
num_bytes),
|
||||
filename, STRINGIFY_BIGINT (num_bytes, buf));
|
||||
}
|
||||
else
|
||||
error (0, 0, _("Read error at byte %ld in file %s, padding with zeros"),
|
||||
error (0, 0, _("Read error at byte %lld in file %s, padding with zeros"),
|
||||
original_num_bytes - num_bytes, filename);
|
||||
write_nuls_to_file (num_bytes, out_des, tape_buffered_write);
|
||||
break;
|
||||
@ -505,12 +522,12 @@ copy_files_disk_to_tape (int in_des, int out_des, long num_bytes,
|
||||
NUM_BYTES is the number of bytes to copy. */
|
||||
|
||||
void
|
||||
copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
|
||||
copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes,
|
||||
char *filename)
|
||||
{
|
||||
long size;
|
||||
long k;
|
||||
long original_num_bytes;
|
||||
off_t original_num_bytes;
|
||||
int rc;
|
||||
|
||||
original_num_bytes = num_bytes;
|
||||
@ -520,10 +537,16 @@ copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
|
||||
if (rc = disk_fill_input_buffer (in_des, num_bytes))
|
||||
{
|
||||
if (rc > 0)
|
||||
error (0, 0, _("File %s shrunk by %ld bytes, padding with zeros"),
|
||||
filename, num_bytes);
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
error (0, 0,
|
||||
ngettext ("File %s shrunk by %s byte, padding with zeros",
|
||||
"File %s shrunk by %s bytes, padding with zeros",
|
||||
num_bytes),
|
||||
filename, STRINGIFY_BIGINT (num_bytes, buf));
|
||||
}
|
||||
else
|
||||
error (0, 0, _("Read error at byte %ld in file %s, padding with zeros"),
|
||||
error (0, 0, _("Read error at byte %lld in file %s, padding with zeros"),
|
||||
original_num_bytes - num_bytes, filename);
|
||||
write_nuls_to_file (num_bytes, out_des, disk_buffered_write);
|
||||
break;
|
||||
@ -545,20 +568,23 @@ copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
|
||||
|
||||
void
|
||||
warn_if_file_changed (char *file_name, unsigned long old_file_size,
|
||||
unsigned long old_file_mtime)
|
||||
off_t old_file_mtime)
|
||||
{
|
||||
struct stat new_file_stat;
|
||||
if ((*xstat) (file_name, &new_file_stat) < 0)
|
||||
{
|
||||
error (0, errno, "%s", file_name);
|
||||
stat_error (file_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only check growth, shrinkage detected in copy_files_disk_to_{disk,tape}()
|
||||
*/
|
||||
if (new_file_stat.st_size > old_file_size)
|
||||
error (0, 0, _("File %s grew, %ld new bytes not copied"),
|
||||
file_name, (long)(new_file_stat.st_size - old_file_size));
|
||||
error (0, 0,
|
||||
ngettext ("File %s grew, %"PRIuMAX" new byte not copied",
|
||||
"File %s grew, %"PRIuMAX" new bytes not copied",
|
||||
(long)(new_file_stat.st_size - old_file_size)),
|
||||
file_name, (uintmax_t) (new_file_stat.st_size - old_file_size));
|
||||
|
||||
else if (new_file_stat.st_mtime != old_file_mtime)
|
||||
error (0, 0, _("File %s was modified while being copied"), file_name);
|
||||
@ -658,82 +684,40 @@ struct inode_val
|
||||
};
|
||||
|
||||
/* Inode hash table. Allocated by first call to add_inode. */
|
||||
static struct inode_val **hash_table = NULL;
|
||||
static Hash_table *hash_table = NULL;
|
||||
|
||||
/* Size of current hash table. Initial size is 47. (47 = 2*22 + 3) */
|
||||
static int hash_size = 22;
|
||||
static size_t
|
||||
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 int hash_num;
|
||||
|
||||
/* Find the file name associated with NODE_NUM. If there is no file
|
||||
associated with NODE_NUM, return NULL. */
|
||||
static bool
|
||||
inode_val_compare (const void *val1, const void *val2)
|
||||
{
|
||||
const struct inode_val *ival1 = val1;
|
||||
const struct inode_val *ival2 = val2;
|
||||
return ival1->inode == ival2->inode
|
||||
&& ival1->major_num == ival2->major_num
|
||||
&& ival1->minor_num == ival2->minor_num;
|
||||
}
|
||||
|
||||
char *
|
||||
find_inode_file (unsigned long node_num, unsigned long major_num,
|
||||
unsigned long minor_num)
|
||||
{
|
||||
int start; /* Initial hash location. */
|
||||
int temp; /* Rehash search variable. */
|
||||
|
||||
if (hash_table != NULL)
|
||||
{
|
||||
/* Hash function is node number modulo the table size. */
|
||||
start = node_num % hash_size;
|
||||
|
||||
/* Initial look into the table. */
|
||||
if (hash_table[start] == NULL)
|
||||
return NULL;
|
||||
if (hash_table[start]->inode == node_num
|
||||
&& hash_table[start]->major_num == major_num
|
||||
&& hash_table[start]->minor_num == minor_num)
|
||||
return hash_table[start]->file_name;
|
||||
|
||||
/* The home position is full with a different inode record.
|
||||
Do a linear search terminated by a NULL pointer. */
|
||||
for (temp = (start + 1) % hash_size;
|
||||
hash_table[temp] != NULL && temp != start;
|
||||
temp = (temp + 1) % hash_size)
|
||||
{
|
||||
if (hash_table[temp]->inode == node_num
|
||||
&& hash_table[start]->major_num == major_num
|
||||
&& hash_table[start]->minor_num == minor_num)
|
||||
return hash_table[temp]->file_name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Do the hash insert. Used in normal inserts and resizing the hash
|
||||
table. It is guaranteed that there is room to insert the item.
|
||||
NEW_VALUE is the pointer to the previously allocated inode, file
|
||||
name association record. */
|
||||
|
||||
static void
|
||||
hash_insert (struct inode_val *new_value)
|
||||
{
|
||||
int start; /* Home position for the value. */
|
||||
int temp; /* Used for rehashing. */
|
||||
|
||||
/* Hash function is node number modulo the table size. */
|
||||
start = new_value->inode % hash_size;
|
||||
|
||||
/* Do the initial look into the table. */
|
||||
if (hash_table[start] == NULL)
|
||||
{
|
||||
hash_table[start] = new_value;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we get to here, the home position is full with a different inode
|
||||
record. Do a linear search for the first NULL pointer and insert
|
||||
the new item there. */
|
||||
temp = (start + 1) % hash_size;
|
||||
while (hash_table[temp] != NULL)
|
||||
temp = (temp + 1) % hash_size;
|
||||
|
||||
/* Insert at the NULL. */
|
||||
hash_table[temp] = new_value;
|
||||
struct inode_val sample;
|
||||
struct inode_val *ival;
|
||||
|
||||
if (!hash_table)
|
||||
return NULL;
|
||||
|
||||
sample.inode = node_num;
|
||||
sample.major_num = major_num;
|
||||
sample.minor_num = minor_num;
|
||||
ival = hash_lookup (hash_table, &sample);
|
||||
return ival ? ival->file_name : NULL;
|
||||
}
|
||||
|
||||
/* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */
|
||||
@ -743,7 +727,8 @@ add_inode (unsigned long node_num, char *file_name, unsigned long major_num,
|
||||
unsigned long minor_num)
|
||||
{
|
||||
struct inode_val *temp;
|
||||
|
||||
struct inode_val *e;
|
||||
|
||||
/* Create new inode record. */
|
||||
temp = (struct inode_val *) xmalloc (sizeof (struct inode_val));
|
||||
temp->inode = node_num;
|
||||
@ -751,39 +736,12 @@ add_inode (unsigned long node_num, char *file_name, unsigned long major_num,
|
||||
temp->minor_num = minor_num;
|
||||
temp->file_name = xstrdup (file_name);
|
||||
|
||||
/* Do we have to increase the size of (or initially allocate)
|
||||
the hash table? */
|
||||
if (hash_num == hash_size || hash_table == NULL)
|
||||
{
|
||||
struct inode_val **old_table; /* Pointer to old table. */
|
||||
int i; /* Index for re-insert loop. */
|
||||
|
||||
/* Save old table. */
|
||||
old_table = hash_table;
|
||||
if (old_table == NULL)
|
||||
hash_num = 0;
|
||||
|
||||
/* Calculate new size of table and allocate it.
|
||||
Sequence of table sizes is 47, 97, 197, 397, 797, 1597, 3197, 6397 ...
|
||||
where 3197 and most of the sizes after 6397 are not prime. The other
|
||||
numbers listed are prime. */
|
||||
hash_size = 2 * hash_size + 3;
|
||||
hash_table = (struct inode_val **)
|
||||
xmalloc (hash_size * sizeof (struct inode_val *));
|
||||
bzero (hash_table, hash_size * sizeof (struct inode_val *));
|
||||
|
||||
/* Insert the values from the old table into the new table. */
|
||||
for (i = 0; i < hash_num; i++)
|
||||
hash_insert (old_table[i]);
|
||||
|
||||
if (old_table != NULL)
|
||||
free (old_table);
|
||||
}
|
||||
|
||||
/* Insert the new record and increment the count of elements in the
|
||||
hash table. */
|
||||
hash_insert (temp);
|
||||
hash_num++;
|
||||
if (!((hash_table
|
||||
|| (hash_table = hash_initialize (0, 0, inode_val_hasher,
|
||||
inode_val_compare, 0)))
|
||||
&& (e = hash_insert (hash_table, temp))))
|
||||
xalloc_die ();
|
||||
/* FIXME: e is not used */
|
||||
}
|
||||
|
||||
|
||||
@ -800,14 +758,14 @@ open_archive (char *file)
|
||||
copy_in = process_copy_in;
|
||||
|
||||
if (copy_function == copy_in)
|
||||
fd = rmtopen (file, O_RDONLY | O_BINARY, 0666, rsh_command_option);
|
||||
fd = rmtopen (file, O_RDONLY | O_BINARY, MODE_RW, rsh_command_option);
|
||||
else
|
||||
{
|
||||
if (!append_flag)
|
||||
fd = rmtopen (file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666,
|
||||
fd = rmtopen (file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, MODE_RW,
|
||||
rsh_command_option);
|
||||
else
|
||||
fd = rmtopen (file, O_RDWR | O_BINARY, 0666, rsh_command_option);
|
||||
fd = rmtopen (file, O_RDWR | O_BINARY, MODE_RW, rsh_command_option);
|
||||
}
|
||||
|
||||
return fd;
|
||||
@ -887,7 +845,7 @@ get_next_reel (int tape_des)
|
||||
|
||||
tape_des = open_archive (archive_name);
|
||||
if (tape_des == -1)
|
||||
error (1, errno, "%s", archive_name);
|
||||
open_error (archive_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -907,7 +865,7 @@ get_next_reel (int tape_des)
|
||||
|
||||
tape_des = open_archive (next_archive_name);
|
||||
if (tape_des == -1)
|
||||
error (0, errno, "%s", next_archive_name);
|
||||
open_error (next_archive_name);
|
||||
}
|
||||
while (tape_des < 0);
|
||||
}
|
||||
@ -1003,9 +961,10 @@ umasked_symlink (char *name1, char *name2, int mode)
|
||||
|
||||
/* Take an input pathname and check it for CDF's. Insert an extra
|
||||
`/' in the pathname after each "hidden" directory. If we add
|
||||
any `/'s, return a malloced string (which it will reuse for
|
||||
later calls so our caller doesn't have to worry about freeing
|
||||
the string) instead of the original input string. */
|
||||
any `/'s, return a malloced string instead of the original input
|
||||
string.
|
||||
FIXME: This creates a memory leak.
|
||||
*/
|
||||
|
||||
char *
|
||||
add_cdf_double_slashes (char *input_name)
|
||||
@ -1055,7 +1014,7 @@ add_cdf_double_slashes (char *input_name)
|
||||
*p = '\0';
|
||||
if ((*xstat) (input_name, &dir_stat) < 0)
|
||||
{
|
||||
error (0, errno, "%s", input_name);
|
||||
stat_error (input_name);
|
||||
return input_name;
|
||||
}
|
||||
|
||||
@ -1081,7 +1040,7 @@ add_cdf_double_slashes (char *input_name)
|
||||
*p = '\0';
|
||||
if ((*xstat) (input_name, &dir_stat) < 0)
|
||||
{
|
||||
error (0, errno, "%s", input_name);
|
||||
stat_error (input_name);
|
||||
return input_name;
|
||||
}
|
||||
*p = '/';
|
||||
@ -1109,7 +1068,7 @@ islastparentcdf (char *path)
|
||||
int slash_count;
|
||||
int length; /* Length of result, not including NUL. */
|
||||
|
||||
slash = rindex (path, '/');
|
||||
slash = strrchr (path, '/');
|
||||
if (slash == 0)
|
||||
return 0;
|
||||
else
|
||||
@ -1131,9 +1090,6 @@ islastparentcdf (char *path)
|
||||
|
||||
#define DISKBLOCKSIZE (512)
|
||||
|
||||
enum sparse_write_states { begin, in_zeros, not_in_zeros };
|
||||
|
||||
|
||||
static int
|
||||
buf_all_zeros (char *buf, int bufsize)
|
||||
{
|
||||
@ -1151,7 +1107,7 @@ int delayed_seek_count = 0;
|
||||
/* Write NBYTE bytes from BUF to remote tape connection FILDES.
|
||||
Return the number of bytes written on success, -1 on error. */
|
||||
|
||||
int
|
||||
static int
|
||||
sparse_write (int fildes, char *buf, unsigned int nbyte)
|
||||
{
|
||||
int complete_block_count;
|
||||
@ -1162,7 +1118,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
|
||||
int lseek_rc;
|
||||
int write_rc;
|
||||
int i;
|
||||
enum sparse_write_states state;
|
||||
enum { begin, in_zeros, not_in_zeros } state;
|
||||
|
||||
complete_block_count = nbyte / DISKBLOCKSIZE;
|
||||
leftover_bytes_count = nbyte % DISKBLOCKSIZE;
|
||||
@ -1192,6 +1148,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
|
||||
}
|
||||
buf += DISKBLOCKSIZE;
|
||||
break;
|
||||
|
||||
case in_zeros :
|
||||
if (buf_all_zeros (buf, DISKBLOCKSIZE))
|
||||
{
|
||||
@ -1206,6 +1163,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
|
||||
}
|
||||
buf += DISKBLOCKSIZE;
|
||||
break;
|
||||
|
||||
case not_in_zeros :
|
||||
if (buf_all_zeros (buf, DISKBLOCKSIZE))
|
||||
{
|
||||
@ -1228,6 +1186,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
|
||||
case in_zeros :
|
||||
delayed_seek_count = seek_count;
|
||||
break;
|
||||
|
||||
case not_in_zeros :
|
||||
write_rc = write (fildes, cur_write_start, write_count);
|
||||
delayed_seek_count = 0;
|
||||
@ -1245,3 +1204,139 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
|
||||
}
|
||||
return nbyte;
|
||||
}
|
||||
|
||||
#define CPIO_UID(uid) (set_owner_flag ? set_owner : (uid))
|
||||
#define CPIO_GID(gid) (set_group_flag ? set_group : (gid))
|
||||
|
||||
void
|
||||
stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st)
|
||||
{
|
||||
hdr->c_dev_maj = major (st->st_dev);
|
||||
hdr->c_dev_min = minor (st->st_dev);
|
||||
hdr->c_ino = st->st_ino;
|
||||
/* For POSIX systems that don't define the S_IF macros,
|
||||
we can't assume that S_ISfoo means the standard Unix
|
||||
S_IFfoo bit(s) are set. So do it manually, with a
|
||||
different name. Bleah. */
|
||||
hdr->c_mode = (st->st_mode & 07777);
|
||||
if (S_ISREG (st->st_mode))
|
||||
hdr->c_mode |= CP_IFREG;
|
||||
else if (S_ISDIR (st->st_mode))
|
||||
hdr->c_mode |= CP_IFDIR;
|
||||
#ifdef S_ISBLK
|
||||
else if (S_ISBLK (st->st_mode))
|
||||
hdr->c_mode |= CP_IFBLK;
|
||||
#endif
|
||||
#ifdef S_ISCHR
|
||||
else if (S_ISCHR (st->st_mode))
|
||||
hdr->c_mode |= CP_IFCHR;
|
||||
#endif
|
||||
#ifdef S_ISFIFO
|
||||
else if (S_ISFIFO (st->st_mode))
|
||||
hdr->c_mode |= CP_IFIFO;
|
||||
#endif
|
||||
#ifdef S_ISLNK
|
||||
else if (S_ISLNK (st->st_mode))
|
||||
hdr->c_mode |= CP_IFLNK;
|
||||
#endif
|
||||
#ifdef S_ISSOCK
|
||||
else if (S_ISSOCK (st->st_mode))
|
||||
hdr->c_mode |= CP_IFSOCK;
|
||||
#endif
|
||||
#ifdef S_ISNWK
|
||||
else if (S_ISNWK (st->st_mode))
|
||||
hdr->c_mode |= CP_IFNWK;
|
||||
#endif
|
||||
hdr->c_uid = CPIO_UID (st->st_uid);
|
||||
hdr->c_gid = CPIO_GID (st->st_gid);
|
||||
hdr->c_nlink = st->st_nlink;
|
||||
hdr->c_rdev_maj = major (st->st_rdev);
|
||||
hdr->c_rdev_min = minor (st->st_rdev);
|
||||
hdr->c_mtime = st->st_mtime;
|
||||
hdr->c_filesize = st->st_size;
|
||||
hdr->c_chksum = 0;
|
||||
hdr->c_tar_linkname = NULL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_FCHOWN
|
||||
# define fchown(fd, uid, gid) (-1)
|
||||
#endif
|
||||
|
||||
int
|
||||
fchown_or_chown (int fd, const char *name, uid_t uid, uid_t gid)
|
||||
{
|
||||
if (HAVE_FCHOWN && fd != -1)
|
||||
return fchown (fd, uid, gid);
|
||||
else
|
||||
return chown (name, uid, gid);
|
||||
}
|
||||
|
||||
int
|
||||
fchmod_or_chmod (int fd, const char *name, mode_t mode)
|
||||
{
|
||||
if (HAVE_FCHMOD && fd != -1)
|
||||
return fchmod (fd, mode);
|
||||
else
|
||||
return chmod(name, mode);
|
||||
}
|
||||
|
||||
void
|
||||
set_perms (int fd, struct cpio_file_stat *header)
|
||||
{
|
||||
if (!no_chown_flag)
|
||||
{
|
||||
uid_t uid = CPIO_UID (header->c_uid);
|
||||
gid_t gid = CPIO_GID (header->c_gid);
|
||||
if ((fchown_or_chown (fd, header->c_name, uid, gid) < 0)
|
||||
&& errno != EPERM)
|
||||
chown_error_details (header->c_name, uid, gid);
|
||||
}
|
||||
/* chown may have turned off some permissions we wanted. */
|
||||
if (fchmod_or_chmod (fd, header->c_name, header->c_mode) < 0)
|
||||
chmod_error_details (header->c_name, header->c_mode);
|
||||
#ifdef HPUX_CDF
|
||||
if ((header->c_mode & CP_IFMT) && cdf_flag)
|
||||
/* Once we "hide" the directory with the chmod(),
|
||||
we have to refer to it using name+ instead of name. */
|
||||
file_hdr->c_name [cdf_char] = '+';
|
||||
#endif
|
||||
if (retain_time_flag)
|
||||
set_file_times (fd, header->c_name, header->c_mtime, header->c_mtime);
|
||||
}
|
||||
|
||||
void
|
||||
set_file_times (int fd,
|
||||
const char *name, unsigned long atime, unsigned long mtime)
|
||||
{
|
||||
struct timespec ts[2];
|
||||
|
||||
memset (&ts, 0, sizeof ts);
|
||||
|
||||
ts[0].tv_sec = atime;
|
||||
ts[1].tv_sec = mtime;
|
||||
|
||||
/* Silently ignore EROFS because reading the file won't have upset its
|
||||
timestamp if it's on a read-only filesystem. */
|
||||
if (gl_futimens (fd, name, ts) < 0 && errno != EROFS)
|
||||
utime_error (name);
|
||||
}
|
||||
|
||||
/* Do we have to ignore absolute paths, and if so, does the filename
|
||||
have an absolute path? */
|
||||
void
|
||||
cpio_safer_name_suffix (char *name, bool link_target, bool absolute_names,
|
||||
bool strip_leading_dots)
|
||||
{
|
||||
char *p = safer_name_suffix (name, link_target, absolute_names);
|
||||
if (strip_leading_dots && strcmp (p, "./"))
|
||||
/* strip leading `./' from the filename. */
|
||||
while (*p == '.' && *(p + 1) == '/')
|
||||
{
|
||||
++p;
|
||||
while (*p == '/')
|
||||
++p;
|
||||
}
|
||||
if (p != name)
|
||||
memmove (name, p, (size_t)(strlen (p) + 1));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user