Compare commits
74 Commits
release_1_
...
release_1_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8e0b6cb7a | ||
|
|
338add8d10 | ||
|
|
46b07a52f9 | ||
|
|
a06b3a29fb | ||
|
|
6f02669c7b | ||
|
|
e1e1f87eb4 | ||
|
|
bffe1074aa | ||
|
|
9a3e8a6f43 | ||
|
|
a0fd0d95e2 | ||
|
|
3925776b41 | ||
|
|
762be4f2bd | ||
|
|
b7899bb121 | ||
|
|
6e196273a4 | ||
|
|
bdb9de4b1e | ||
|
|
c4acbdaa97 | ||
|
|
c3fa22fc80 | ||
|
|
706bd01915 | ||
|
|
0057cd6803 | ||
|
|
45cf3a7426 | ||
|
|
28f2669b15 | ||
|
|
166b7c7d02 | ||
|
|
cd91cd3c62 | ||
|
|
cac45fffc5 | ||
|
|
0c6c288b53 | ||
|
|
87240ee7c4 | ||
|
|
84a55f12e5 | ||
|
|
a7e9b6a17b | ||
|
|
f0ceef8596 | ||
|
|
63e092548a | ||
|
|
7cb84c25ee | ||
|
|
4dfcd6c054 | ||
|
|
2947023d27 | ||
|
|
92773d860f | ||
|
|
dccb3806a6 | ||
|
|
0d8e324912 | ||
|
|
cef4d5e838 | ||
|
|
ba954ea1e1 | ||
|
|
006c1efbe8 | ||
|
|
aeffa4f266 | ||
|
|
829b3feb26 | ||
|
|
88347995b2 | ||
|
|
acd833fb98 | ||
|
|
51aee274e8 | ||
|
|
2b1bffbad6 | ||
|
|
df59690240 | ||
|
|
1bcbbcf1ff | ||
|
|
ac5288c1ac | ||
|
|
67a1a0eac5 | ||
|
|
471c0f76cd | ||
|
|
755c246588 | ||
|
|
5944f452b0 | ||
|
|
f74cab3a93 | ||
|
|
01c4475b17 | ||
|
|
b7d206cb1e | ||
|
|
c30c4ffb9f | ||
|
|
b216fed634 | ||
|
|
0d6720288b | ||
|
|
da760e3faa | ||
|
|
af30244849 | ||
|
|
be34933b63 | ||
|
|
8f390db92f | ||
|
|
705fab49eb | ||
|
|
f14558de94 | ||
|
|
67cad0792b | ||
|
|
9077de9fa9 | ||
|
|
ac6caa71bc | ||
|
|
1ffb4377a4 | ||
|
|
a00f276fe9 | ||
|
|
5fa60b8d43 | ||
|
|
29887e47d3 | ||
|
|
a6318ea0ef | ||
|
|
c10830a35b | ||
|
|
7a968d67c8 | ||
|
|
7b68ef3d91 |
18
.cvsignore
18
.cvsignore
@@ -1,18 +0,0 @@
|
||||
*.bz2
|
||||
*.gz
|
||||
*.tar
|
||||
.bootstrap
|
||||
ABOUT-NLS
|
||||
INSTALL
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
build-aux
|
||||
config.*
|
||||
configure
|
||||
gnulib
|
||||
m4
|
||||
rmt
|
||||
stamp-h1
|
||||
tar-[0-9]*
|
||||
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
*.o
|
||||
*.so
|
||||
*~
|
||||
.bootstrap
|
||||
.deps
|
||||
.emacs*
|
||||
.libs
|
||||
ABOUT-NLS
|
||||
ChangeLog
|
||||
INSTALL
|
||||
Make.rules
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
build-aux
|
||||
build-aux/
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
gnu
|
||||
gnulib
|
||||
libtool
|
||||
m4
|
||||
paxutils
|
||||
stamp-h1
|
||||
@@ -1,3 +1,31 @@
|
||||
2009-03-05 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/incremen.c: --no-recursive works with --incremental.
|
||||
|
||||
2009-03-04 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
Add xz support.
|
||||
|
||||
* src/buffer.c, src/suffix.c: Add support for xz compression.
|
||||
* src/tar.c: New option --xz, for compression/decompression using xz.
|
||||
Re-assign -J as a short equivalent of --xz.
|
||||
|
||||
2009-01-19 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* doc/tar.texi: Fix typo.
|
||||
|
||||
2008-12-29 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* bootstrap.conf: Include size_max.
|
||||
* gnulib.modules: Remove memset, rmdir. Replace strdup with
|
||||
strdup-posix. Patch by Eric Blake.
|
||||
* src/tar.c: Implement -I as a shorthand for --use-compress-program.
|
||||
* doc/tar.texi: Document -I.
|
||||
* tests/pipe.at, tests/shortrec.at: Account for eventual 'Record
|
||||
size' output.
|
||||
* tests/testsuite.at (AT_TAR_CHECK_HOOK): New define
|
||||
(AT_TAR_WITH_HOOK, TAR_IGNREC_HOOK): New macros.
|
||||
|
||||
2008-11-30 Sergey Poznyakoff <gray@gnu.org.ua>
|
||||
|
||||
* src/xheader.c: Remove duplicate inclusion of fnmatch.h. Reported
|
||||
17
Makefile.am
17
Makefile.am
@@ -1,7 +1,7 @@
|
||||
# Main Makefile for GNU tar.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2007 Free
|
||||
# Software Foundation, Inc.
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2007,
|
||||
# 2009 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
|
||||
@@ -19,13 +19,22 @@
|
||||
## 02110-1301, USA.
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
EXTRA_DIST = ChangeLog.1 PORTS
|
||||
SUBDIRS = doc lib rmt src scripts po tests
|
||||
EXTRA_DIST = ChangeLog.1 Make.rules
|
||||
SUBDIRS = doc gnu lib rmt src scripts po tests
|
||||
|
||||
dist-hook:
|
||||
$(MAKE) changelog_dir=$(distdir) ChangeLog
|
||||
-rm -f $(distdir).cpio
|
||||
find $(distdir) | cpio -Hcrc -o | \
|
||||
GZIP=$(GZIP_ENV) gzip -c > $(distdir).cpio.gz
|
||||
|
||||
distclean-local:
|
||||
-rm -f $(distdir).cpio.gz
|
||||
|
||||
include Make.rules
|
||||
|
||||
gen_start_date = 2009-03-06
|
||||
prev_change_log = ChangeLog.CVS
|
||||
changelog_dir = .
|
||||
|
||||
|
||||
|
||||
378
Makefile.in
378
Makefile.in
@@ -1,378 +0,0 @@
|
||||
# Makefile.in generated automatically by automake 1.1n from Makefile.am
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy, distribute and modify it.
|
||||
|
||||
# Main Makefile for GNU tar.
|
||||
# Copyright (C) 1994, 1995, 1996, 1997 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.
|
||||
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = .
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = true
|
||||
PRE_INSTALL = true
|
||||
POST_INSTALL = true
|
||||
NORMAL_UNINSTALL = true
|
||||
PRE_UNINSTALL = true
|
||||
POST_UNINSTALL = true
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
CATALOGS = @CATALOGS@
|
||||
CATOBJEXT = @CATOBJEXT@
|
||||
CC = @CC@
|
||||
DATADIRNAME = @DATADIRNAME@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
GENCAT = @GENCAT@
|
||||
GMOFILES = @GMOFILES@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
GT_NO = @GT_NO@
|
||||
GT_YES = @GT_YES@
|
||||
INSTOBJEXT = @INSTOBJEXT@
|
||||
INTLDEPS = @INTLDEPS@
|
||||
INTLLIBS = @INTLLIBS@
|
||||
INTLOBJS = @INTLOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKINSTALLDIRS = @MKINSTALLDIRS@
|
||||
MSGFMT = @MSGFMT@
|
||||
PACKAGE = @PACKAGE@
|
||||
POFILES = @POFILES@
|
||||
POSUB = @POSUB@
|
||||
RANLIB = @RANLIB@
|
||||
RMT = @RMT@
|
||||
U = @U@
|
||||
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
|
||||
USE_NLS = @USE_NLS@
|
||||
VERSION = @VERSION@
|
||||
YACC = @YACC@
|
||||
|
||||
AUTOMAKE_OPTIONS = gnits dist-shar
|
||||
|
||||
BABYL = rmail/* admin/*/RMAIL
|
||||
EXTRA_DIST = AC-PATCHES AM-PATCHES BI-PATCHES PORTS rebox.el
|
||||
SUBDIRS = doc lib intl src scripts po tests
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
CONFIG_HEADER_IN = config.h.in
|
||||
CONFIG_HEADER_FULL = config.h
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
DIST_COMMON = README ABOUT-NLS AUTHORS BACKLOG COPYING ChangeLog \
|
||||
INSTALL Makefile.am Makefile.in NEWS THANKS TODO acconfig.h \
|
||||
acinclude.m4 aclocal.m4 config.h.in configure configure.in install-sh \
|
||||
missing mkinstalldirs stamp-h.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = tar
|
||||
GZIP = --best
|
||||
default: all
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --gnits Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
$(srcdir)/aclocal.m4: configure.in acinclude.m4
|
||||
cd $(srcdir) && $(ACLOCAL)
|
||||
|
||||
config.status: configure
|
||||
$(SHELL) ./config.status --recheck
|
||||
$(srcdir)/configure: configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
|
||||
cd $(srcdir) && $(AUTOCONF)
|
||||
|
||||
$(CONFIG_HEADER): stamp-h
|
||||
stamp-h: $(CONFIG_HEADER_IN) $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES= CONFIG_HEADERS=$(CONFIG_HEADER_FULL) \
|
||||
$(SHELL) ./config.status
|
||||
@echo timestamp > stamp-h
|
||||
$(srcdir)/$(CONFIG_HEADER_IN): stamp-h.in
|
||||
$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
|
||||
cd $(top_srcdir) && $(AUTOHEADER)
|
||||
echo timestamp > $(srcdir)/stamp-h.in
|
||||
|
||||
mostlyclean-hdr:
|
||||
|
||||
clean-hdr:
|
||||
|
||||
distclean-hdr:
|
||||
rm -f $(CONFIG_HEADER)
|
||||
|
||||
maintainer-clean-hdr:
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
all-recursive install-data-recursive install-exec-recursive \
|
||||
installdirs-recursive install-recursive uninstall-recursive \
|
||||
check-recursive installcheck-recursive info-recursive dvi-recursive \
|
||||
mostlyclean-recursive clean-recursive distclean-recursive \
|
||||
maintainer-clean-recursive:
|
||||
@for subdir in $(SUBDIRS); do \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
(cd $$subdir && $(MAKE) $$target) \
|
||||
|| case "$(MFLAGS)" in *k*) fail=yes;; *) exit 1;; esac; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
(cd $$subdir && $(MAKE) tags); \
|
||||
done
|
||||
|
||||
tags: TAGS
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
|
||||
done; \
|
||||
test -z "$(ETAGS_ARGS)config.h.in$(SOURCES)$(HEADERS)$$tags" \
|
||||
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $(SOURCES) $(HEADERS) -o $$here/TAGS)
|
||||
|
||||
mostlyclean-tags:
|
||||
|
||||
clean-tags:
|
||||
|
||||
distclean-tags:
|
||||
rm -f TAGS ID
|
||||
|
||||
maintainer-clean-tags:
|
||||
|
||||
distdir = $(PACKAGE)-$(VERSION)
|
||||
# This target untars the dist file and tries a VPATH configuration. Then
|
||||
# it guarantees that the distribution is self-contained by making another
|
||||
# tarfile.
|
||||
distcheck: dist
|
||||
rm -rf $(distdir)
|
||||
GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz --mode=a+r
|
||||
mkdir $(distdir)/=build
|
||||
mkdir $(distdir)/=inst
|
||||
dc_install_base=`cd $(distdir)/=inst && pwd`; \
|
||||
cd $(distdir)/=build \
|
||||
&& ../configure --with-included-gettext --srcdir=.. --prefix=$$dc_install_base \
|
||||
&& $(MAKE) \
|
||||
&& $(MAKE) dvi \
|
||||
&& $(MAKE) check \
|
||||
&& $(MAKE) install \
|
||||
&& $(MAKE) installcheck \
|
||||
&& $(MAKE) dist
|
||||
rm -rf $(distdir)
|
||||
@echo "========================"; \
|
||||
echo "$(distdir).tar.gz is ready for distribution"; \
|
||||
echo "========================"
|
||||
dist: distdir
|
||||
-chmod -R a+r $(distdir)
|
||||
GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz --mode=a+r $(distdir)
|
||||
rm -rf $(distdir)
|
||||
dist-shar: distdir
|
||||
-chmod -R a+r $(distdir)
|
||||
rm -rf $(distdir)
|
||||
dist-all: distdir
|
||||
-chmod -R a+r $(distdir)
|
||||
GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz --mode=a+r $(distdir)
|
||||
rm -rf $(distdir)
|
||||
distdir: $(DISTFILES)
|
||||
@if sed 15q $(srcdir)/NEWS | fgrep -e "$(VERSION)" > /dev/null; then :; else \
|
||||
echo "NEWS not updated; not releasing" 1>&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
rm -rf $(distdir)
|
||||
mkdir $(distdir)
|
||||
-chmod 755 $(distdir)
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file; \
|
||||
done
|
||||
for subdir in $(SUBDIRS); do \
|
||||
test -d $(distdir)/$$subdir \
|
||||
|| mkdir $(distdir)/$$subdir \
|
||||
|| exit 1; \
|
||||
chmod 755 $(distdir)/$$subdir; \
|
||||
(cd $$subdir && $(MAKE) distdir=../$(distdir)/$$subdir distdir) \
|
||||
|| exit 1; \
|
||||
done
|
||||
info: info-recursive
|
||||
dvi: dvi-recursive
|
||||
check: all-am
|
||||
$(MAKE) check-recursive
|
||||
installcheck: installcheck-recursive
|
||||
all-recursive-am: $(CONFIG_HEADER)
|
||||
$(MAKE) all-recursive
|
||||
|
||||
all-am: Makefile config.h all-local
|
||||
|
||||
install-exec: install-exec-recursive
|
||||
@$(NORMAL_INSTALL)
|
||||
|
||||
install-data: install-data-recursive
|
||||
@$(NORMAL_INSTALL)
|
||||
|
||||
install: install-recursive
|
||||
@:
|
||||
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
all: all-recursive-am all-am
|
||||
|
||||
install-strip:
|
||||
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
|
||||
installdirs: installdirs-recursive
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
|
||||
|
||||
clean-generic:
|
||||
test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
rm -f Makefile $(DISTCLEANFILES)
|
||||
rm -f config.cache config.log stamp-h
|
||||
test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||
mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic
|
||||
|
||||
clean-am: clean-hdr clean-tags clean-generic mostlyclean-am
|
||||
|
||||
distclean-am: distclean-hdr distclean-tags distclean-generic clean-am
|
||||
|
||||
maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \
|
||||
maintainer-clean-generic distclean-am
|
||||
|
||||
mostlyclean: mostlyclean-recursive mostlyclean-am
|
||||
|
||||
clean: clean-recursive clean-am
|
||||
|
||||
distclean: distclean-recursive distclean-am
|
||||
rm -f config.status
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive maintainer-clean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
rm -f config.status
|
||||
|
||||
.PHONY: default mostlyclean-hdr distclean-hdr clean-hdr \
|
||||
maintainer-clean-hdr install-data-recursive uninstall-data-recursive \
|
||||
install-exec-recursive uninstall-exec-recursive installdirs-recursive \
|
||||
uninstalldirs-recursive all-recursive check-recursive \
|
||||
installcheck-recursive info-recursive dvi-recursive \
|
||||
mostlyclean-recursive distclean-recursive clean-recursive \
|
||||
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
|
||||
distclean-tags clean-tags maintainer-clean-tags distdir info dvi \
|
||||
installcheck all-recursive-am all-am install-exec install-data install \
|
||||
uninstall all installdirs mostlyclean-generic distclean-generic \
|
||||
clean-generic maintainer-clean-generic clean mostlyclean distclean \
|
||||
maintainer-clean
|
||||
|
||||
|
||||
all-local: $(CONFIG_HEADER)
|
||||
|
||||
id: ID
|
||||
|
||||
ID:
|
||||
cd lib && $(MAKE) $@
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
dist-zoo: $(DISTFILES)
|
||||
rm -rf $(distdir)
|
||||
mkdir $(distdir)
|
||||
distdir=`cd $(distdir) && pwd` \
|
||||
&& cd $(srcdir) \
|
||||
&& automake --include-deps --output-dir=$$distdir
|
||||
@for file in $(DISTFILES); do \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $(srcdir)/$$file $(distdir)/$$file; \
|
||||
done
|
||||
for subdir in $(SUBDIRS); do \
|
||||
test -d $(distdir)/$$subdir \
|
||||
|| mkdir $(distdir)/$$subdir \
|
||||
|| exit 1; \
|
||||
chmod 777 $(distdir)/$$subdir; \
|
||||
(cd $$subdir && $(MAKE) dist) || exit 1; \
|
||||
done
|
||||
@sublist="$(DIST_SUBDIRS)"; \
|
||||
for dir in $$sublist; do \
|
||||
echo copying directory $$dir; \
|
||||
tar -chf - $$dir | (cd $(distdir) && tar -xBpf -); \
|
||||
done
|
||||
chmod -R a+r $(distdir)
|
||||
find $(distdir) -type f | xargs dosfn
|
||||
# find $(distdir) -type f | xargs recode :ibmpc
|
||||
mv $(distdir) $(PACKAGE)
|
||||
find $(PACKAGE) -type f | zoo ahIq $(PACKAGE).zoo
|
||||
rm -rf $(PACKAGE)
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
139
NEWS
139
NEWS
@@ -1,6 +1,141 @@
|
||||
GNU tar NEWS - User visible changes. 2008-12-27
|
||||
GNU tar NEWS - User visible changes. 2010-03-10
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
|
||||
version 1.23 - Sergey Poznyakoff, 2010-03-10
|
||||
|
||||
* Record size autodetection
|
||||
|
||||
When listing or extracting archives, the actual record size is
|
||||
reported only if the archive is read from a device (as opposed
|
||||
to regular files and pipes).
|
||||
|
||||
* Seekable archives
|
||||
|
||||
When a read-only operation (e.g. --list or --extract) is requested
|
||||
on a regular file, tar attemtps to speed up accesses by using lseek.
|
||||
|
||||
* New command line option `--warning'
|
||||
|
||||
The `--warning' command line option allows to suppress or enable
|
||||
particular warning messages during `tar' run. It takes a single
|
||||
argument (a `keyword'), identifying the class of warning messages
|
||||
to affect. If the argument is prefixed with `no-', such warning
|
||||
messages are suppressed. For example,
|
||||
|
||||
tar --warning=no-alone-zero-block -x -f archive
|
||||
|
||||
suppresses the output of `A lone zero block' diagnostics, which is
|
||||
normally issued if `archive' ends with a single block of zeros.
|
||||
|
||||
See Tar Manual, section 3.9 "Controlling Warning Messages", for a
|
||||
detailed discussion.
|
||||
|
||||
* New command line option `--level'
|
||||
|
||||
The `--level=N' option sets the incremental dump level N. It
|
||||
is valid when used in conjunction with the -c and --listed-incremental
|
||||
options. So far the only meaningful value for N is 0. The
|
||||
`--level=0' option forces creating the level 0 dump, by truncating
|
||||
the snapshot file if it exists.
|
||||
|
||||
* Files removed during incremental dumps
|
||||
|
||||
If a file or directory is removed while incremental dump is
|
||||
in progress, tar exact actions depend on whether this file
|
||||
was explicitly listed in the command line, or was found
|
||||
during file system scan.
|
||||
|
||||
If the file was explicitly listed in the command line, tar
|
||||
issues error message and exits with the code 2, meaning
|
||||
fatal error.
|
||||
|
||||
Otherwise, if the file was found during the file system scan,
|
||||
tar issues a warning, saying "File removed before we read it",
|
||||
and sets exit code to 1, which means "some files differ".
|
||||
If the --warning=no-file-removed option is given, no warning
|
||||
is issued and exit code remains 0.
|
||||
|
||||
* Modification times of PAX extended headers.
|
||||
|
||||
Modification times in ustar header blocks of extended headers
|
||||
are set to mtimes of the corresponding archive members. This
|
||||
can be overridden by the
|
||||
|
||||
--pax-opion='exthdr.mtime=STRING'
|
||||
|
||||
command line option. The STRING is either number of seconds since
|
||||
the Epoch or a `Time reference' (see below).
|
||||
|
||||
Modification times in ustar header blocks of global extended
|
||||
headers are set to the time when tar was invoked.
|
||||
|
||||
This can be overridden by the
|
||||
|
||||
--pax-opion='globexthdr.mtime=STRING'
|
||||
|
||||
command line option. The STRING is either number of seconds since
|
||||
the Epoch or a `Time reference' (see below).
|
||||
|
||||
* Time references in --pax-option argument.
|
||||
|
||||
Any value from the --pax-option argument that is enclosed in a pair
|
||||
of curly braces represents a time reference. The string between the
|
||||
braces is understood either as a textual time representation, as described in
|
||||
chapter 7, "Date input formats", of the Tar manual, or as a name of
|
||||
an existing file, starting with `/' or `.'. In the latter
|
||||
case, it is replaced with the modification time of that file.
|
||||
|
||||
* Environment of --to-command script.
|
||||
|
||||
The environment passed to the --to-command script is extended with
|
||||
the following variables:
|
||||
|
||||
TAR_VERSION GNU tar version number
|
||||
TAR_ARCHIVE The name of the archive
|
||||
TAR_VOLUME Ordinal number of the volume
|
||||
TAR_FORMAT Format of the archive
|
||||
TAR_BLOCKING_FACTOR Current blocking factor
|
||||
|
||||
* Bugfixes
|
||||
** Fix handling of hard link targets by -c --transform.
|
||||
** Fix hard links recognition with -c --remove-files.
|
||||
** Fix restoring files from backup (debian bug #508199).
|
||||
** Correctly restore modes and permissions on existing directories.
|
||||
** The --remove-files option removes files only if they were
|
||||
succesfully stored in the archive.
|
||||
** Fix storing and listing of the volume labels in POSIX format.
|
||||
** Improve algorithm for splitting long file names (ustar
|
||||
format).
|
||||
** Fix possible memory overflow in the rmt client code (CVE-2010-0624).
|
||||
|
||||
|
||||
version 1.22 - Sergey Poznyakoff, 2009-03-05
|
||||
|
||||
* Support for xz compression
|
||||
|
||||
Tar uses xz for compression if one of the following conditions is met:
|
||||
|
||||
1. The option --xz or -J (see below) is used.
|
||||
2. The xz binary is set as compressor using --use-compress-program option.
|
||||
3. The file name of the archive being created ends in `.xz' and
|
||||
auto-compress option (-a) is used.
|
||||
|
||||
Xz is used for decompression if one of the following conditions is met:
|
||||
|
||||
1. The option --xz or -J is used.
|
||||
2. The xz binary is set as compressor using --use-compress-program option.
|
||||
3. The file is recognized as xz compressed stream data.
|
||||
|
||||
* Short option -J reassigned as a short equivalent of --xz
|
||||
|
||||
* New option -I
|
||||
|
||||
The -I option is assigned as a short equivalent for
|
||||
--use-compress-program.
|
||||
|
||||
* The --no-recursive option works in incremental mode.
|
||||
|
||||
|
||||
version 1.21 - Sergey Poznyakoff, 2008-12-27
|
||||
|
||||
@@ -1064,7 +1199,7 @@ Versions 1.07 back to 1.00 by Jay Fenlason.
|
||||
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
|
||||
2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
|
||||
173
PORTS
173
PORTS
@@ -1,173 +0,0 @@
|
||||
Ports of GNU tar and other tars
|
||||
See the end of file for copying conditions.
|
||||
|
||||
* Introduction
|
||||
|
||||
Most entries in this file are out of date, unfortunately. Such
|
||||
entries are marked with an `X'. Run grep '^\*\*[^X]' PORTS to
|
||||
extract valid entries.
|
||||
|
||||
Please write bug-tar@gnu.org if you are aware of various ports of GNU tar
|
||||
to non-GNU and non-Unix systems not listed here, or for corrections.
|
||||
Please provide the goal system, a complete and stable URL, the maintainer
|
||||
name and address, the tar version used as a base, and your comments.
|
||||
|
||||
* GNU/Linux and Unix
|
||||
|
||||
** Star is a tape archiver similar to tar.
|
||||
<http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/star.html>
|
||||
|
||||
* Amiga
|
||||
|
||||
**X ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/GNUtar-1.11.8.lha
|
||||
maintained by Enrico Forestieri <enrico@com.unipr.it>
|
||||
Based on tar 1.11.8.
|
||||
|
||||
**X ftp://ftp.ninemoons.com/pub/ade/current/amiga-bin/tar-1.11.8-bin.lha
|
||||
maintained by the ADE group <fnf@fishpond.ninemoons.com>
|
||||
Based on tar 1.11.8, needs ixemul.library.
|
||||
|
||||
**X ftp://ftp.wustl.edu/systems/amiga/aminet/util/arc/gnutar.lha
|
||||
maintained by <mscheler@wuarchive.wustl.edu>
|
||||
|
||||
* DEC alpha (NT)
|
||||
|
||||
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
|
||||
* DEC VAX (VMS)
|
||||
|
||||
**X http://www.lp.se/free/vmstar/
|
||||
maintained by Richard Levitte <levitte@lp.se>
|
||||
This is not GNU tar, but a separate implementation.
|
||||
|
||||
** maintained by William Bader <william@nscs.fast.net>
|
||||
For V4.7. Based on an old PDtar. Requires compatible shared libraries
|
||||
to run V5 or V6 executables.
|
||||
|
||||
* IBM/PC (DV/X)
|
||||
|
||||
**X ftp://qdeck.com/ (?)
|
||||
maintained by David Ronis <ronis@gibbs.chem.mcgill.ca>
|
||||
For Desqview/X. Everything works besides compression. Copy of hacked
|
||||
sources available, some of DV/X's programmer's library also needed.
|
||||
|
||||
* IBM/PC (MSDOS)
|
||||
|
||||
**X http://www.simtel.net/simtel.net/
|
||||
http://www.leo.org/pub/comp/platforms/pc/gnuish (Germany)
|
||||
ftp://ftp.simtel.net/simtelnet/gnu
|
||||
ftp://ftp.leo.org/pub/comp/platforms/pc/gnuish
|
||||
maintained by Darrel Hankerson <hankedr@mail.auburn.edu>
|
||||
You get many GNU tools, not only `tar'. The GNUish project is described
|
||||
in `gnuish_t.htm'.
|
||||
|
||||
** The DJGPP development tools also include some `tar' utilities.
|
||||
|
||||
**X ftp://ftp.mcs.com/mcsnet.users/les/dos-gnutar/
|
||||
maintained by Leslie Mikesell <les@mcs.net>
|
||||
Based on tar 1.11.2. Support for SCSI (via ASPI) and network (rsh over
|
||||
packet driver). No support for win95 long file names.
|
||||
|
||||
**X ftp://ftp.wu-wien.ac.at/pub/src/PCmisc/aspi-tar/*
|
||||
maintained by Christoph Splittgerber <chris@orion.sdata.de>
|
||||
Based on tar 1.10. Support for SCSI (via ASPI).
|
||||
|
||||
**X ftp://wuarchive (?)
|
||||
Several DOS version based on PDtar. John Gilmore <gnu@toad.com> says
|
||||
he has copies of several vintages saved.
|
||||
|
||||
**X ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.exe
|
||||
ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.taz
|
||||
ftp://ftp.cdrom.com/.14/languages/ada/toolkit/msdos/gtar/gtar.zip
|
||||
|
||||
**X ftp://ftp.cdrom.com/.4/os2/archiver/tar.zip
|
||||
Based on PDtar.
|
||||
|
||||
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
GNU tar for NT (intel and Alpha platforms).
|
||||
|
||||
** ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
|
||||
|
||||
**X http://people.darmstadt.netsurf.de/tst/tar.htm
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
This is not a `tar' port, but an index of them.
|
||||
|
||||
* IBM/PC (OS/2)
|
||||
|
||||
**X http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtar254.zip
|
||||
http://www.leo.org/pub/comp/os/os2/leo/gnu/archiver/gtak254.zip
|
||||
maintained by Andreas Kaiser <Andreas.Kaiser@stuttgart.netsurf.de>
|
||||
Version 2.54. Based on tar 1.10. The second archive contains SCSI
|
||||
drivers (DAT streamers notably) and rmt-type programs.
|
||||
|
||||
* IBM/PC (Win32: Windows 95, NT 3.5 or NT 4.0)
|
||||
|
||||
**X ftp://ftp.cygnus.com:~ftp/pub/sac/win32/usersrc/*
|
||||
maintained by Cygnus
|
||||
GNU-Win32 B17.1 distribution. Download all files, `cat' them together,
|
||||
and `untar' the result. You get many GNU tools, not only `tar'.
|
||||
Based on tar 1.11.2.
|
||||
|
||||
**X ftp://ftp.cdrom.com/.20/windows/archiver/tar.zip
|
||||
maintained by Drew Bliss & Geoff Voelker
|
||||
GNU tar for NT (intel and Alpha platforms).
|
||||
|
||||
** ftp://garbo.uwasa.fi/pc/unix/untgz095.zip
|
||||
maintained by Tillmann Steinbrecher <tst@darmstadt.netsurf.de>
|
||||
The `untgz' program is a fast .tar or .tar.gz (.tgz) extractor.
|
||||
|
||||
* IBM/PC (Windows 3.1)
|
||||
|
||||
**X ftp://ftp.mcs.com/mcsnet.users/les/win-gnutar/
|
||||
maintained by Leslie Mikesell <les@mcs.net>
|
||||
Support for network (rsh over winsock). No support for win95 long
|
||||
file names.
|
||||
|
||||
**X ftp://ftp.gamesdomain.ru/.1/os/windows/programr/tar.zip
|
||||
Based on GNU tar 1.11.2.
|
||||
|
||||
* Macintosh
|
||||
|
||||
** Paulo Abreu (paulotex at yahoo dot com) did a
|
||||
limited port of GNU tar to Darwin, with support for resource forks
|
||||
and finder info, but this no longer seems to be available.
|
||||
|
||||
** There is a tar in Stuffit Expander which is available many places and
|
||||
comes with MacOS. It creates some spurious files but works on average.
|
||||
|
||||
** There is an excellent GNU tar bundled in Tenon MachTen, but it does not
|
||||
seem to be available separately.
|
||||
|
||||
|
||||
* Copyright notice
|
||||
|
||||
Copyright (C) 1999, 2001, 2003, 2004, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU tar.
|
||||
|
||||
GNU tar 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 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU tar 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 GNU tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ]*$"
|
||||
version-control: never
|
||||
End:
|
||||
|
||||
70
README-cvs
70
README-cvs
@@ -1,70 +0,0 @@
|
||||
-*- outline -*-
|
||||
|
||||
These notes intend to help people working on the CVS version of
|
||||
this package.
|
||||
|
||||
* Requirements
|
||||
|
||||
Only the sources are installed in the CVS repository (to ease the
|
||||
maintenance, merges etc.), therefore you will have to get the latest
|
||||
stable versions of the maintainer tools we depend upon, including:
|
||||
|
||||
- Automake <http://www.gnu.org/software/automake/>
|
||||
- Autoconf <http://www.gnu.org/software/autoconf/>
|
||||
- Bison <http://www.gnu.org/software/bison/>
|
||||
- Gettext <http://www.gnu.org/software/gettext/>
|
||||
- Gzip <http://www.gnu.org/software/gzip/>
|
||||
- Tar <http://www.gnu.org/software/tar/>
|
||||
- Wget <http://www.gnu.org/software/wget/>
|
||||
|
||||
As of this writing, the latest stable version of Gzip is 1.2.4 but we
|
||||
suggest using test version 1.3.5 (or later, if one becomes available).
|
||||
|
||||
Valgrind <http://valgrind.org/> is also highly recommended, if
|
||||
Valgrind supports your architecture.
|
||||
|
||||
Only building the initial full source tree will be a bit painful,
|
||||
later, a plain `cvs update -P && make' should be sufficient.
|
||||
|
||||
* First CVS checkout
|
||||
|
||||
Obviously, if you are reading these notes, you did manage to check out
|
||||
this package from CVS. The next step is to get other files needed to
|
||||
build, which are extracted from other source packages:
|
||||
|
||||
$ ./bootstrap
|
||||
|
||||
And there you are! Just
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make check
|
||||
|
||||
At this point, there should be no difference between your local copy,
|
||||
and the CVS master copy:
|
||||
|
||||
$ cvs diff
|
||||
|
||||
should output no difference.
|
||||
|
||||
Enjoy!
|
||||
|
||||
-----
|
||||
|
||||
Copyright (C) 2002, 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 3, 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.
|
||||
71
README-hacking
Normal file
71
README-hacking
Normal file
@@ -0,0 +1,71 @@
|
||||
These notes intend to help people working on the Git version of
|
||||
this package.
|
||||
|
||||
* Requirements
|
||||
|
||||
You need the following packages to build the Git version of GNU
|
||||
tar. We do not make any efforts to accommodate older versions of
|
||||
these packages, so please make sure that you have the latest stable
|
||||
version.
|
||||
|
||||
- Automake <http://www.gnu.org/software/automake/>
|
||||
- Autoconf <http://www.gnu.org/software/autoconf/>
|
||||
- M4 <http://www.gnu.org/software/m4/>
|
||||
- Texinfo <http://www.gnu.org/software/texinfo>
|
||||
- Gnulib <http://www.gnu.org/software/gnulib>
|
||||
- Git <http://git.or.cz>
|
||||
|
||||
* Bootstrapping
|
||||
|
||||
Obviously, if you are reading these notes, you did manage to clone
|
||||
tar from Git. The next step is to get other files needed to build,
|
||||
which are extracted from other source packages:
|
||||
|
||||
1. Change to the source tree directory
|
||||
|
||||
cd tar
|
||||
|
||||
2. Run
|
||||
|
||||
./bootstrap
|
||||
|
||||
Once done, proceed as described in the file README (section
|
||||
INSTALLATION).
|
||||
|
||||
Normally you will have to run bootstrap only once. However, if you
|
||||
intend to hack on GNU tar, you might need to run it again later. In
|
||||
this case, you will probably want to save some time and bandwidth by
|
||||
avoiding downloading the same files again. If so, create in GNU tar
|
||||
root directory the file named `.bootstrap' with the following
|
||||
contents:
|
||||
|
||||
--gnulib-srcdir=$HOME/gnulib
|
||||
|
||||
Replace `$HOME/gnulib' with the actual directory where the Gnulib
|
||||
sources reside.
|
||||
|
||||
For more information about `bootstrap', run `bootstrap --help'.
|
||||
|
||||
|
||||
* Copyright information
|
||||
|
||||
Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to anyone to make or distribute verbatim copies
|
||||
of this document as received, in any medium, provided that the
|
||||
copyright notice and this permission notice are preserved,
|
||||
thus giving the recipient permission to redistribute in turn.
|
||||
|
||||
Permission is granted to distribute modified versions
|
||||
of this document, or of portions of it,
|
||||
under the above conditions, provided also that they
|
||||
carry prominent notices stating who last changed them.
|
||||
|
||||
^L
|
||||
Local Variables:
|
||||
mode: outline
|
||||
paragraph-separate: "[ ^L]*$"
|
||||
version-control: never
|
||||
End:
|
||||
|
||||
|
||||
4
THANKS
4
THANKS
@@ -70,6 +70,7 @@ Burkhard Plache plache@krusty.optimax.ns.ca
|
||||
Calvin Cliff cliff@trifid.astro.ucla.edu
|
||||
Cameron Elliott cam@mvbms.mvbms.com
|
||||
Carl Streeter streeter@cae.wisc.edu
|
||||
Carl Worth cworth@cworth.org
|
||||
Carsten Heyl heyl@nads.de
|
||||
Catrin Urbanneck cur@gppc.de
|
||||
Cesar Romani romani@ifm.uni-hamburg.de
|
||||
@@ -132,6 +133,7 @@ David Steiner dsteiner@ispa.uni-osnabrueck.de
|
||||
David Taylor taylor@think.com
|
||||
Dean Gaudet dgaudet@watdragon.uwaterloo.ca
|
||||
Demizu Noritoshi nori-d@is.aist-nara.ac.jp
|
||||
Denis Excoffier denis.excoffier@airbus.com
|
||||
Denis Fortin fortin@acm.org
|
||||
Dennis Pixton dennis@math.binghamton.edu
|
||||
Dick Streefland dicks@tasking.nl
|
||||
@@ -367,6 +369,7 @@ Olaf Schlueter olaf@toppoint.de
|
||||
Olaf Wucknitz owucknitz@hs.uni-hamburg.de
|
||||
Oliver Trepte oliver@fysik4.kth.se
|
||||
Olivier Roussel roussel@lifl.fr
|
||||
Ondřej Vašík ovasik@redhat.com
|
||||
Oswald P. Backus IV backus@lks.csi.com
|
||||
Pascal Meheut pascal@cnam.cnam.fr
|
||||
Patrick Fulconis fulco@sig.uvsq.fr
|
||||
@@ -388,6 +391,7 @@ Peter Fox fox@gec-mi-at.co.uk
|
||||
Peter Kutschera peter@zditr1.arcs.ac.at
|
||||
Peter Seebach seebs@taniemarie.solon.com
|
||||
Phil Hands phil@hands.com
|
||||
Phil Proudman phil@proudman51.freeserve.co.uk
|
||||
Philippe Defert defert@cern.ch
|
||||
Piercarlo Grandi piercarl@sabi.demon.co.uk
|
||||
Pierce Cantrell cantrell@ee.tamu.edu
|
||||
|
||||
88
acconfig.h
88
acconfig.h
@@ -1,88 +0,0 @@
|
||||
/* Special definitions for GNU tar, processed by autoheader.
|
||||
Copyright <20> 1994, 1997 Free Software Foundation, Inc.
|
||||
Fran<61>ois Pinard <pinard@iro.umontreal.ca>, 1993.
|
||||
*/
|
||||
|
||||
/* This is unconditionally defined for setting a GNU environment. */
|
||||
#undef _GNU_SOURCE
|
||||
|
||||
/* Define to a string giving the full name of the default archive file. */
|
||||
#undef DEFAULT_ARCHIVE
|
||||
|
||||
/* Define to a number giving the default blocking size for archives. */
|
||||
#undef DEFAULT_BLOCKING
|
||||
|
||||
/* Define to 1 if density may be indicated by [lmh] at end of device. */
|
||||
#undef DENSITY_LETTER
|
||||
|
||||
/* Define to a string giving the prefix of the default device, without the
|
||||
part specifying the unit and density. */
|
||||
#undef DEVICE_PREFIX
|
||||
|
||||
/* Define to 1 if you lack a 3-argument version of open, and want to
|
||||
emulate it with system calls you do have. */
|
||||
#undef EMUL_OPEN3
|
||||
|
||||
/* Define to 1 if NLS is requested. */
|
||||
#undef ENABLE_NLS
|
||||
|
||||
/* Define as 1 if you have catgets and don't want to use GNU gettext. */
|
||||
#undef HAVE_CATGETS
|
||||
|
||||
/* Define to 1 if you have getgrgid(3). */
|
||||
#undef HAVE_GETGRGID
|
||||
|
||||
/* Define to 1 if you have getpwuid(3). */
|
||||
#undef HAVE_GETPWUID
|
||||
|
||||
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
|
||||
#undef HAVE_GETTEXT
|
||||
|
||||
/* Define if your locale.h file contains LC_MESSAGES. */
|
||||
#undef HAVE_LC_MESSAGES
|
||||
|
||||
/* Define to 1 if you have the valloc function. */
|
||||
#undef HAVE_VALLOC
|
||||
|
||||
/* Define to 1 if some rsh exists, or if you have <netdb.h>. */
|
||||
#undef HAVE_RTAPELIB
|
||||
|
||||
/* Define to 1 if mknod function is available. */
|
||||
#undef HAVE_MKNOD
|
||||
|
||||
/* Define to 1 if stpcpy function is available. */
|
||||
#undef HAVE_STPCPY
|
||||
|
||||
/* Define if `union wait' is the type of the first arg to wait functions. */
|
||||
#undef HAVE_UNION_WAIT
|
||||
|
||||
/* Define to 1 if utime.h exists and declares struct utimbuf. */
|
||||
#undef HAVE_UTIME_H
|
||||
|
||||
/* Define to mt_model (v.g., for DG/UX), else to mt_type. */
|
||||
#undef MTIO_CHECK_FIELD
|
||||
|
||||
/* Define to the name of the distribution. */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to 1 if ANSI function prototypes are usable. */
|
||||
#undef PROTOTYPES
|
||||
|
||||
/* Define to the full path of your rsh, if any. */
|
||||
#undef REMOTE_SHELL
|
||||
|
||||
/* Path to directory containing system wide message catalog sources. */
|
||||
#undef STD_INC_PATH
|
||||
|
||||
/* Define to the version of the distribution. */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to 1 if using the `glocale' package for message catalogs. */
|
||||
#undef WITH_CATALOGS
|
||||
|
||||
/* Define to 1 for better use of the debugging malloc library. See
|
||||
site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz. */
|
||||
#undef WITH_DMALLOC
|
||||
|
||||
/* Define to 1 if GNU regex should be used instead of GNU rx. */
|
||||
#undef WITH_REGEX
|
||||
449
acinclude.m4
449
acinclude.m4
@@ -1,425 +1,26 @@
|
||||
## ----------------------------------------- ##
|
||||
## Find how to suppress newlines with echo. ##
|
||||
## ----------------------------------------- ##
|
||||
dnl Special Autoconf macros for GNU Tar -*- autoconf -*-
|
||||
dnl Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
dnl
|
||||
dnl GNU tar is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU General Public License as published by
|
||||
dnl the Free Software Foundation; either version 3, or (at your option)
|
||||
dnl any later version.
|
||||
dnl
|
||||
dnl GNU tar is distributed in the hope that it will be useful,
|
||||
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
dnl GNU General Public License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU General Public License along
|
||||
dnl with GNU tar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Once this macro is called, you may output with no echo in a Makefile or
|
||||
# script using: echo @ECHO_N@ "STRING_TO_OUTPUT@ECHO_C@".
|
||||
|
||||
AC_DEFUN(fp_PROG_ECHO,
|
||||
[AC_MSG_CHECKING(how to suppress newlines using echo)
|
||||
AC_CACHE_VAL(fp_cv_prog_echo_nonl,
|
||||
[if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
|
||||
if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
|
||||
fp_cv_prog_echo_nonl=no
|
||||
else
|
||||
fp_cv_prog_echo_nonl=option
|
||||
fi
|
||||
else
|
||||
fp_cv_prog_echo_nonl=escape
|
||||
fi
|
||||
])
|
||||
AC_MSG_RESULT($fp_cv_prog_echo_nonl)
|
||||
case $fp_cv_prog_echo_nonl in
|
||||
no) ECHO_N= ECHO_C= ;;
|
||||
option) ECHO_N=-n ECHO_C= ;;
|
||||
escape) ECHO_N= ECHO_C='\c' ;;
|
||||
esac
|
||||
AC_SUBST(ECHO_N)dnl
|
||||
AC_SUBST(ECHO_C)dnl
|
||||
])
|
||||
|
||||
## ------------------------------------------- ##
|
||||
## Check if --with-included-malloc was given. ##
|
||||
## From Franc,ois Pinard ##
|
||||
## ------------------------------------------- ##
|
||||
|
||||
# In 1992, Michael Bushnell (now Thomas Bushnell <thomas@gnu.ai.mit.edu>)
|
||||
# devised a test for avoiding HP/UX malloc and using GNU malloc instead.
|
||||
# Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhe.de> recycled this
|
||||
# test for CLISP Common LISP and extended it to cover broken mallocs from
|
||||
# Sun and SGI. I (<pinard@iro.umontreal.ca>) reworked it a little so
|
||||
# it is independent of config.guess, and overridable by the installer.
|
||||
|
||||
# On IRIX 5.2, libc malloc is broken, but the -lmalloc one was usable.
|
||||
# So in my packages, I once unconditionally used -lmalloc if it existed.
|
||||
# This does not do anymore, because the -lmalloc malloc is broken on
|
||||
# Solaris 2.4 to 2.5.1 (alignment is 4 bytes instead of 8 bytes, as
|
||||
# reported by John Wells <john@bitsmart.com>).
|
||||
|
||||
# Bruno also notes: "HP-UX has two different malloc() implementations.
|
||||
# Both are broken. When used with CLISP, the one in the default libc.a
|
||||
# leads to a SIGSEGV, the one in libmalloc.a leads to a SIGBUS. The SunOS
|
||||
# 4.1.1 malloc() breaks when used by CLISP's generational GC. The IRIX
|
||||
# 5.2 malloc() breaks when used by CLISP's generational GC."
|
||||
|
||||
# If the installer does not give a preference, we use the included GNU
|
||||
# malloc if we have the slightest doubt that malloc could be broken, this
|
||||
# includes cross compilation, and *all* HP/UX, SunOS or IRIX systems.
|
||||
# It is crude indeed, but I just do not have enough information for truly
|
||||
# benchmarking malloc in all cases, but want safe packages nevertheless.
|
||||
|
||||
AC_DEFUN(fp_WITH_INCLUDED_MALLOC,
|
||||
[AC_MSG_CHECKING(if included GNU malloc is wanted)
|
||||
AC_ARG_WITH(included-malloc,
|
||||
[ --with-included-malloc use the GNU malloc which is included here], ,
|
||||
[if test $cross_compiling = yes; then
|
||||
withval=yes
|
||||
else
|
||||
case `uname -s 2> /dev/null` in
|
||||
HP-UX | SunOS | IRIX* ) withval=yes ;;
|
||||
*) withval=no ;;
|
||||
esac
|
||||
fi])
|
||||
test "$withval" = yes && LIBOBJS="$LIBOBJS gmalloc.o"
|
||||
AC_MSG_RESULT($withval)
|
||||
])
|
||||
|
||||
## -------------------- ##
|
||||
## Macros from Ulrich. ##
|
||||
## -------------------- ##
|
||||
|
||||
# Search path for a program which passes the given test.
|
||||
# Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||
|
||||
# serial 1
|
||||
|
||||
dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
|
||||
dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
|
||||
AC_DEFUN(AM_PATH_PROG_WITH_TEST,
|
||||
[# Extract the first word of "$2", so it can be a program name with args.
|
||||
set dummy $2; ac_word=[$]2
|
||||
AC_MSG_CHECKING([for $ac_word])
|
||||
AC_CACHE_VAL(ac_cv_path_$1,
|
||||
[case "[$]$1" in
|
||||
/*)
|
||||
ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
|
||||
for ac_dir in ifelse([$5], , $PATH, [$5]); do
|
||||
test -z "$ac_dir" && ac_dir=.
|
||||
if test -f $ac_dir/$ac_word; then
|
||||
if [$3]; then
|
||||
ac_cv_path_$1="$ac_dir/$ac_word"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
IFS="$ac_save_ifs"
|
||||
dnl If no 4th arg is given, leave the cache variable unset,
|
||||
dnl so AC_PATH_PROGS will keep looking.
|
||||
ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
|
||||
])dnl
|
||||
;;
|
||||
esac])dnl
|
||||
$1="$ac_cv_path_$1"
|
||||
if test -n "[$]$1"; then
|
||||
AC_MSG_RESULT([$]$1)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_SUBST($1)dnl
|
||||
])
|
||||
|
||||
# Check whether LC_MESSAGES is available in <locale.h>.
|
||||
# Ulrich Drepper <drepper@cygnus.com>, 1995.
|
||||
|
||||
# serial 1
|
||||
|
||||
AC_DEFUN(AM_LC_MESSAGES,
|
||||
[if test $ac_cv_header_locale_h = yes; then
|
||||
AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
|
||||
[AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
|
||||
am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
|
||||
if test $am_cv_val_LC_MESSAGES = yes; then
|
||||
AC_DEFINE(HAVE_LC_MESSAGES)
|
||||
fi
|
||||
fi])
|
||||
|
||||
# Macro to add for using GNU gettext.
|
||||
# Ulrich Drepper <drepper@cygnus.com>, 1995.
|
||||
|
||||
# serial 1
|
||||
|
||||
AC_DEFUN(AM_WITH_NLS,
|
||||
[AC_MSG_CHECKING([whether NLS is requested])
|
||||
dnl Default is enabled NLS
|
||||
AC_ARG_ENABLE(nls,
|
||||
[ --disable-nls do not use Native Language Support],
|
||||
USE_NLS=$enableval, USE_NLS=yes)
|
||||
AC_MSG_RESULT($USE_NLS)
|
||||
AC_SUBST(USE_NLS)
|
||||
|
||||
USE_INCLUDED_LIBINTL=no
|
||||
|
||||
dnl If we use NLS figure out what method
|
||||
if test "$USE_NLS" = "yes"; then
|
||||
AC_DEFINE(ENABLE_NLS)
|
||||
AC_MSG_CHECKING([whether included gettext is requested])
|
||||
AC_ARG_WITH(included-gettext,
|
||||
[ --with-included-gettext use the GNU gettext library included here],
|
||||
nls_cv_force_use_gnu_gettext=$withval,
|
||||
nls_cv_force_use_gnu_gettext=no)
|
||||
AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
|
||||
|
||||
nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
|
||||
if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
|
||||
dnl User does not insist on using GNU NLS library. Figure out what
|
||||
dnl to use. If gettext or catgets are available (in this order) we
|
||||
dnl use this. Else we have to fall back to GNU NLS library.
|
||||
dnl catgets is only used if permitted by option --with-catgets.
|
||||
nls_cv_header_intl=
|
||||
nls_cv_header_libgt=
|
||||
CATOBJEXT=NONE
|
||||
|
||||
AC_CHECK_HEADER(libintl.h,
|
||||
[AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc,
|
||||
[AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")],
|
||||
gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)])
|
||||
|
||||
if test "$gt_cv_func_gettext_libc" != "yes"; then
|
||||
AC_CHECK_LIB(intl, bindtextdomain,
|
||||
[AC_CACHE_CHECK([for gettext in libintl],
|
||||
gt_cv_func_gettext_libintl,
|
||||
[AC_TRY_LINK([], [return (int) gettext ("")],
|
||||
gt_cv_func_gettext_libintl=yes,
|
||||
gt_cv_func_gettext_libintl=no)])])
|
||||
fi
|
||||
|
||||
if test "$gt_cv_func_gettext_libc" = "yes" \
|
||||
|| test "$gt_cv_func_gettext_libintl" = "yes"; then
|
||||
AC_DEFINE(HAVE_GETTEXT)
|
||||
AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
|
||||
if test "$MSGFMT" != "no"; then
|
||||
AC_CHECK_FUNCS(dcgettext)
|
||||
AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
|
||||
AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
|
||||
AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
|
||||
return _nl_msg_cat_cntr],
|
||||
[CATOBJEXT=.gmo
|
||||
DATADIRNAME=share],
|
||||
[CATOBJEXT=.mo
|
||||
DATADIRNAME=lib])
|
||||
INSTOBJEXT=.mo
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
if test "$CATOBJEXT" = "NONE"; then
|
||||
AC_MSG_CHECKING([whether catgets can be used])
|
||||
AC_ARG_WITH(catgets,
|
||||
[ --with-catgets use catgets functions if available],
|
||||
nls_cv_use_catgets=$withval, nls_cv_use_catgets=no)
|
||||
AC_MSG_RESULT($nls_cv_use_catgets)
|
||||
|
||||
if test "$nls_cv_use_catgets" = "yes"; then
|
||||
dnl No gettext in C library. Try catgets next.
|
||||
AC_CHECK_LIB(i, main)
|
||||
AC_CHECK_FUNC(catgets,
|
||||
[AC_DEFINE(HAVE_CATGETS)
|
||||
INTLOBJS="\$(CATOBJS)"
|
||||
AC_PATH_PROG(GENCAT, gencat, no)dnl
|
||||
if test "$GENCAT" != "no"; then
|
||||
AC_PATH_PROG(GMSGFMT, gmsgfmt, no)
|
||||
if test "$GMSGFMT" = "no"; then
|
||||
AM_PATH_PROG_WITH_TEST(GMSGFMT, msgfmt,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)
|
||||
fi
|
||||
AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
|
||||
USE_INCLUDED_LIBINTL=yes
|
||||
CATOBJEXT=.cat
|
||||
INSTOBJEXT=.cat
|
||||
DATADIRNAME=lib
|
||||
INTLDEPS="../intl/libintl.a"
|
||||
INTLLIBS=$INTLDEPS
|
||||
LIBS=`echo $LIBS | sed -e 's/-lintl//'`
|
||||
nls_cv_header_intl=intl/libintl.h
|
||||
nls_cv_header_libgt=intl/libgettext.h
|
||||
fi])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$CATOBJEXT" = "NONE"; then
|
||||
dnl Neither gettext nor catgets in included in the C library.
|
||||
dnl Fall back on GNU gettext library.
|
||||
nls_cv_use_gnu_gettext=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||
dnl Mark actions used to generate GNU NLS library.
|
||||
INTLOBJS="\$(GETTOBJS)"
|
||||
AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt)
|
||||
AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
|
||||
AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
|
||||
AC_SUBST(MSGFMT)
|
||||
USE_INCLUDED_LIBINTL=yes
|
||||
CATOBJEXT=.gmo
|
||||
INSTOBJEXT=.mo
|
||||
DATADIRNAME=share
|
||||
INTLDEPS="../intl/libintl.a"
|
||||
INTLLIBS=$INTLDEPS
|
||||
LIBS=`echo $LIBS | sed -e 's/-lintl//'`
|
||||
nls_cv_header_intl=intl/libintl.h
|
||||
nls_cv_header_libgt=intl/libgettext.h
|
||||
fi
|
||||
|
||||
dnl Test whether we really found GNU xgettext.
|
||||
if test "$XGETTEXT" != ":"; then
|
||||
dnl If it is no GNU xgettext we define it as : so that the
|
||||
dnl Makefiles still can work.
|
||||
if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
|
||||
: ;
|
||||
else
|
||||
AC_MSG_RESULT(
|
||||
[found xgettext programs is not GNU xgettext; ignore it])
|
||||
XGETTEXT=":"
|
||||
fi
|
||||
fi
|
||||
|
||||
# We need to process the po/ directory.
|
||||
POSUB=po
|
||||
else
|
||||
DATADIRNAME=share
|
||||
nls_cv_header_intl=intl/libintl.h
|
||||
nls_cv_header_libgt=intl/libgettext.h
|
||||
fi
|
||||
|
||||
# If this is used in GNU gettext we have to set USE_NLS to `yes'
|
||||
# because some of the sources are only built for this goal.
|
||||
if test "$PACKAGE" = gettext; then
|
||||
USE_NLS=yes
|
||||
USE_INCLUDED_LIBINTL=yes
|
||||
fi
|
||||
|
||||
dnl These rules are solely for the distribution goal. While doing this
|
||||
dnl we only have to keep exactly one list of the available catalogs
|
||||
dnl in configure.in.
|
||||
for lang in $ALL_LINGUAS; do
|
||||
GMOFILES="$GMOFILES $lang.gmo"
|
||||
POFILES="$POFILES $lang.po"
|
||||
done
|
||||
|
||||
dnl Make all variables we use known to autoconf.
|
||||
AC_SUBST(USE_INCLUDED_LIBINTL)
|
||||
AC_SUBST(CATALOGS)
|
||||
AC_SUBST(CATOBJEXT)
|
||||
AC_SUBST(DATADIRNAME)
|
||||
AC_SUBST(GMOFILES)
|
||||
AC_SUBST(INSTOBJEXT)
|
||||
AC_SUBST(INTLDEPS)
|
||||
AC_SUBST(INTLLIBS)
|
||||
AC_SUBST(INTLOBJS)
|
||||
AC_SUBST(POFILES)
|
||||
AC_SUBST(POSUB)
|
||||
])
|
||||
|
||||
AC_DEFUN(AM_GNU_GETTEXT,
|
||||
[AC_REQUIRE([AC_PROG_MAKE_SET])dnl
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_ISC_POSIX])dnl
|
||||
AC_REQUIRE([AC_PROG_RANLIB])dnl
|
||||
AC_REQUIRE([AC_HEADER_STDC])dnl
|
||||
AC_REQUIRE([AC_C_CONST])dnl
|
||||
AC_REQUIRE([AC_C_INLINE])dnl
|
||||
AC_REQUIRE([AC_TYPE_OFF_T])dnl
|
||||
AC_REQUIRE([AC_TYPE_SIZE_T])dnl
|
||||
AC_REQUIRE([AC_FUNC_ALLOCA])dnl
|
||||
AC_REQUIRE([AC_FUNC_MMAP])dnl
|
||||
|
||||
AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \
|
||||
unistd.h values.h])
|
||||
AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \
|
||||
__argz_count __argz_stringify __argz_next])
|
||||
|
||||
if test "${ac_cv_func_stpcpy+set}" != "set"; then
|
||||
AC_CHECK_FUNCS(stpcpy)
|
||||
fi
|
||||
if test "${ac_cv_func_stpcpy}" = "yes"; then
|
||||
AC_DEFINE(HAVE_STPCPY)
|
||||
fi
|
||||
|
||||
AM_LC_MESSAGES
|
||||
AM_WITH_NLS
|
||||
|
||||
if test "x$CATOBJEXT" != "x"; then
|
||||
if test "x$ALL_LINGUAS" = "x"; then
|
||||
LINGUAS=
|
||||
else
|
||||
AC_MSG_CHECKING(for catalogs to be installed)
|
||||
NEW_LINGUAS=
|
||||
for lang in ${LINGUAS=$ALL_LINGUAS}; do
|
||||
case "$ALL_LINGUAS" in
|
||||
*$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
|
||||
esac
|
||||
done
|
||||
LINGUAS=$NEW_LINGUAS
|
||||
AC_MSG_RESULT($LINGUAS)
|
||||
fi
|
||||
|
||||
dnl Construct list of names of catalog files to be constructed.
|
||||
if test -n "$LINGUAS"; then
|
||||
for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Determine which catalog format we have (if any is needed)
|
||||
dnl For now we know about two different formats:
|
||||
dnl Linux libc-5 and the normal X/Open format
|
||||
test -d intl || mkdir intl
|
||||
if test "$CATOBJEXT" = ".cat"; then
|
||||
AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen)
|
||||
|
||||
dnl Transform the SED scripts while copying because some dumb SEDs
|
||||
dnl cannot handle comments.
|
||||
sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed
|
||||
fi
|
||||
dnl po2tbl.sed is always needed.
|
||||
sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
|
||||
$srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed
|
||||
|
||||
dnl In the intl/Makefile.in we have a special dependency which makes
|
||||
dnl only sense for gettext. We comment this out for non-gettext
|
||||
dnl packages.
|
||||
if test "$PACKAGE" = "gettext"; then
|
||||
GT_NO="#NO#"
|
||||
GT_YES=
|
||||
else
|
||||
GT_NO=
|
||||
GT_YES="#YES#"
|
||||
fi
|
||||
AC_SUBST(GT_NO)
|
||||
AC_SUBST(GT_YES)
|
||||
|
||||
dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly
|
||||
dnl find the mkinstalldirs script in another subdir but ($top_srcdir).
|
||||
dnl Try to locate is.
|
||||
MKINSTALLDIRS=
|
||||
if test $ac_aux_dir; then
|
||||
MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs"
|
||||
fi
|
||||
if test -z $MKINSTALLDIRS; then
|
||||
MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
|
||||
fi
|
||||
AC_SUBST(MKINSTALLDIRS)
|
||||
|
||||
dnl Generate list of files to be processed by xgettext which will
|
||||
dnl be included in po/Makefile.
|
||||
test -d po || mkdir po
|
||||
if test "x$srcdir" != "x."; then
|
||||
if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
|
||||
posrcprefix="$srcdir/"
|
||||
else
|
||||
posrcprefix="../$srcdir/"
|
||||
fi
|
||||
else
|
||||
posrcprefix="../"
|
||||
fi
|
||||
sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
|
||||
< $srcdir/po/POTFILES.in > po/POTFILES
|
||||
])
|
||||
AC_DEFUN([TAR_COMPR_PROGRAM],[
|
||||
m4_pushdef([tar_compr_define],translit($1,[a-z+-],[A-ZX_])[_PROGRAM])
|
||||
m4_pushdef([tar_compr_var],[tar_cv_compressor_]translit($1,[+-],[x_]))
|
||||
AC_ARG_WITH($1,
|
||||
AC_HELP_STRING([--with-]$1[=PROG],
|
||||
[use PROG as ]$1[ compressor program]),
|
||||
[tar_compr_var=${withval}],
|
||||
[tar_compr_var=m4_if($2,,$1,$2)])
|
||||
AC_DEFINE_UNQUOTED(tar_compr_define, "$tar_compr_var",
|
||||
[Define to the program name of ]$1[ compressor program])])
|
||||
|
||||
629
bootstrap
629
bootstrap
@@ -1,13 +1,13 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Bootstrap this package from CVS.
|
||||
# Bootstrap this package from checked-out sources.
|
||||
|
||||
# Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2003-2008, 2009 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -15,9 +15,7 @@
|
||||
# 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.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Written by Paul Eggert and Sergey Poznyakoff.
|
||||
|
||||
@@ -25,10 +23,16 @@ nl='
|
||||
'
|
||||
|
||||
# Ensure file names are sorted consistently across platforms.
|
||||
# Also, ensure diagnostics are in English, e.g., "wget --help" below.
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
local_gl_dir=gl
|
||||
|
||||
# Temporary directory names.
|
||||
bt='._bootmp'
|
||||
bt_regex=`echo "$bt"| sed 's/\./[.]/g'`
|
||||
bt2=${bt}2
|
||||
|
||||
usage() {
|
||||
echo >&2 "\
|
||||
Usage: $0 [OPTION]...
|
||||
@@ -43,73 +47,25 @@ Options:
|
||||
--gnulib-srcdir=DIRNAME Specify the local directory where gnulib
|
||||
sources reside. Use this if you already
|
||||
have gnulib sources on your machine, and
|
||||
do not want to waste your bandwidth dowloading
|
||||
do not want to waste your bandwidth downloading
|
||||
them again.
|
||||
--copy Copy files instead of creating symbolic links.
|
||||
--force Attempt to bootstrap even if the sources seem
|
||||
not to have been checked out.
|
||||
--skip-po Do not download po files.
|
||||
--update-po Update po files and exit.
|
||||
--cvs-user=USERNAME Set the CVS username to be used when accessing
|
||||
the paxutils repository.
|
||||
|
||||
If the file bootstrap.conf exists in the current working directory, its
|
||||
If the file $0.conf exists in the same directory as this script, its
|
||||
contents are read as shell variables to configure the bootstrap.
|
||||
|
||||
Local defaults can be provided by placing the file \`.bootstrap' in the
|
||||
current working directory. The file is read after bootstrap.conf, comments
|
||||
and empty lines are removed, shell variables expanded and the result is
|
||||
prepended to the command line options.
|
||||
|
||||
Running without arguments will suffice in most cases.
|
||||
"
|
||||
}
|
||||
|
||||
checkout() {
|
||||
if [ ! -d $1 ]; then
|
||||
echo "$0: getting $1 files..."
|
||||
|
||||
case $1 in
|
||||
paxutils)
|
||||
case ${CVS_AUTH-pserver} in
|
||||
pserver)
|
||||
CVS_PREFIX=':pserver:anonymous@';;
|
||||
ssh)
|
||||
CVS_PREFIX="$CVS_USER${CVS_USER+@}";;
|
||||
*)
|
||||
echo "$0: $CVS_AUTH: Unknown CVS access method" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
case $CVS_RSH in
|
||||
'') CVS_RSH=ssh; export CVS_RSH;;
|
||||
esac
|
||||
|
||||
CVSURL=${CVS_PREFIX}cvs.savannah.gnu.org:/cvsroot/"$1"
|
||||
;;
|
||||
|
||||
gnulib)
|
||||
CVSURL=:pserver:anonymous@pserver.git.sv.gnu.org:/gnulib.git
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
trap "cleanup $1" 1 2 13 15
|
||||
|
||||
cvs -z3 -q -d $CVSURL co $1 || cleanup $1
|
||||
|
||||
trap - 1 2 13 15
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
status=$?
|
||||
rm -fr $1
|
||||
exit $status
|
||||
}
|
||||
|
||||
# Configuration.
|
||||
|
||||
# Name of the Makefile.am
|
||||
gnulib_mk=gnulib.mk
|
||||
|
||||
# List of gnulib modules needed.
|
||||
gnulib_modules=
|
||||
|
||||
@@ -126,9 +82,10 @@ po_download_command_format=\
|
||||
|
||||
extract_package_name='
|
||||
/^AC_INIT(/{
|
||||
/.*,.*,.*,/{
|
||||
/.*,.*,.*, */{
|
||||
s///
|
||||
s/[][]//g
|
||||
s/)$//
|
||||
p
|
||||
q
|
||||
}
|
||||
@@ -141,19 +98,28 @@ extract_package_name='
|
||||
}
|
||||
'
|
||||
package=`sed -n "$extract_package_name" configure.ac` || exit
|
||||
gnulib_name=lib$package
|
||||
|
||||
build_aux=build-aux
|
||||
source_base=lib
|
||||
m4_base=m4
|
||||
doc_base=doc
|
||||
tests_base=tests
|
||||
|
||||
# Extra files from gnulib, which override files from other sources.
|
||||
gnulib_extra_files='
|
||||
build-aux/announce-gen
|
||||
build-aux/install-sh
|
||||
build-aux/missing
|
||||
build-aux/mdate-sh
|
||||
build-aux/texinfo.tex
|
||||
build-aux/depcomp
|
||||
build-aux/config.guess
|
||||
build-aux/config.sub
|
||||
gnulib_extra_files="
|
||||
$build_aux/install-sh
|
||||
$build_aux/missing
|
||||
$build_aux/mdate-sh
|
||||
$build_aux/texinfo.tex
|
||||
$build_aux/depcomp
|
||||
$build_aux/config.guess
|
||||
$build_aux/config.sub
|
||||
doc/INSTALL
|
||||
'
|
||||
"
|
||||
|
||||
# Additional gnulib-tool options to use. Use "\newline" to break lines.
|
||||
gnulib_tool_option_extras=
|
||||
|
||||
# Other locale categories that need message catalogs.
|
||||
EXTRA_LOCALE_CATEGORIES=
|
||||
@@ -165,23 +131,38 @@ XGETTEXT_OPTIONS='\\\
|
||||
--flag=error:3:c-format --flag=error_at_line:5:c-format\\\
|
||||
'
|
||||
|
||||
# Package bug report address for gettext files
|
||||
MSGID_BUGS_ADDRESS=bug-$package@gnu.org
|
||||
|
||||
# Files we don't want to import.
|
||||
excluded_files=
|
||||
|
||||
# File that should exist in the top directory of a checked out hierarchy,
|
||||
# but not in a distribution tarball.
|
||||
CVS_only_file=README-cvs
|
||||
checkout_only_file=README-hacking
|
||||
|
||||
# Whether to use copies instead of symlinks.
|
||||
copy=false
|
||||
|
||||
# Override the default configuration, if necessary.
|
||||
test -r bootstrap.conf && . ./bootstrap.conf
|
||||
# Set this to '.cvsignore .gitignore' in bootstrap.conf if you want
|
||||
# those files to be generated in directories like lib/, m4/, and po/.
|
||||
# Or set it to 'auto' to make this script select which to use based
|
||||
# on which version control system (if any) is used in the source directory.
|
||||
vc_ignore=auto
|
||||
|
||||
# Read local configuration file
|
||||
if [ -r .bootstrap ]; then
|
||||
echo "$0: Reading configuration file .bootstrap"
|
||||
eval set -- "`sed 's/#.*$//;/^$/d' .bootstrap | tr '\n' ' '` $*"
|
||||
# Override the default configuration, if necessary.
|
||||
# Make sure that bootstrap.conf is sourced from the current directory
|
||||
# if we were invoked as "sh bootstrap".
|
||||
case "$0" in
|
||||
*/*) test -r "$0.conf" && . "$0.conf" ;;
|
||||
*) test -r "$0.conf" && . ./"$0.conf" ;;
|
||||
esac
|
||||
|
||||
|
||||
if test "$vc_ignore" = auto; then
|
||||
vc_ignore=
|
||||
test -d .git && vc_ignore=.gitignore
|
||||
test -d CVS && vc_ignore="$vc_ignore .cvsignore"
|
||||
fi
|
||||
|
||||
# Translate configuration into internal form.
|
||||
@@ -194,20 +175,14 @@ do
|
||||
--help)
|
||||
usage
|
||||
exit;;
|
||||
--gnulib-srcdir=*)
|
||||
GNULIB_SRCDIR=`expr "X$option" : 'X--gnulib-srcdir=\(.*\)'`;;
|
||||
--paxutils-srcdir=*)
|
||||
PAXUTILS_SRCDIR=`expr "$option" : '--paxutils-srcdir=\(.*\)'`;;
|
||||
--gnulib-srcdir=*)
|
||||
GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
|
||||
--cvs-user=*)
|
||||
CVS_USER=`expr "$option" : '--cvs-user=\(.*\)'`;;
|
||||
--skip-po | --no-po) # --no-po is for compatibility with 'tar' tradition.
|
||||
DOWNLOAD_PO=skip;;
|
||||
--update-po=*)
|
||||
DOWNLOAD_PO=`expr "$option" : '--update-po=\(.*\)'`;;
|
||||
--update-po)
|
||||
DOWNLOAD_PO=only;;
|
||||
--skip-po)
|
||||
SKIP_PO=t;;
|
||||
--force)
|
||||
CVS_only_file=;;
|
||||
checkout_only_file=;;
|
||||
--copy)
|
||||
copy=true;;
|
||||
*)
|
||||
@@ -216,12 +191,130 @@ do
|
||||
esac
|
||||
done
|
||||
|
||||
if test -n "$CVS_only_file" && test ! -r "$CVS_only_file"; then
|
||||
if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
|
||||
echo "$0: Bootstrapping from a non-checked-out distribution is risky." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$0: Bootstrapping CVS $package..."
|
||||
# If $STR is not already on a line by itself in $FILE, insert it,
|
||||
# sorting the new contents of the file and replacing $FILE with the result.
|
||||
insert_sorted_if_absent() {
|
||||
file=$1
|
||||
str=$2
|
||||
test -f $file || touch $file
|
||||
echo "$str" | sort -u - $file | cmp -s - $file \
|
||||
|| echo "$str" | sort -u - $file -o $file \
|
||||
|| exit 1
|
||||
}
|
||||
|
||||
# Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
|
||||
found_aux_dir=no
|
||||
grep '^[ ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \
|
||||
>/dev/null && found_aux_dir=yes
|
||||
grep '^[ ]*AC_CONFIG_AUX_DIR('"$build_aux"')' configure.ac \
|
||||
>/dev/null && found_aux_dir=yes
|
||||
if test $found_aux_dir = no; then
|
||||
echo "$0: expected line not found in configure.ac. Add the following:" >&2
|
||||
echo " AC_CONFIG_AUX_DIR([$build_aux])" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If $build_aux doesn't exist, create it now, otherwise some bits
|
||||
# below will malfunction. If creating it, also mark it as ignored.
|
||||
if test ! -d $build_aux; then
|
||||
mkdir $build_aux
|
||||
for dot_ig in x $vc_ignore; do
|
||||
test $dot_ig = x && continue
|
||||
insert_sorted_if_absent $dot_ig $build_aux
|
||||
done
|
||||
fi
|
||||
|
||||
echo "$0: Bootstrapping from checked-out $package sources..."
|
||||
|
||||
# See if we can use gnulib's git-merge-changelog merge driver.
|
||||
if test -d .git && (git --version) >/dev/null 2>/dev/null ; then
|
||||
if git config merge.merge-changelog.driver >/dev/null ; then
|
||||
:
|
||||
elif (git-merge-changelog --version) >/dev/null 2>/dev/null ; then
|
||||
echo "initializing git-merge-changelog driver"
|
||||
git config merge.merge-changelog.name 'GNU-style ChangeLog merge driver'
|
||||
git config merge.merge-changelog.driver 'git-merge-changelog %O %A %B'
|
||||
else
|
||||
echo "consider installing git-merge-changelog from gnulib"
|
||||
fi
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
status=$?
|
||||
rm -fr $1
|
||||
exit $status
|
||||
}
|
||||
|
||||
git_modules_config () {
|
||||
GIT_CONFIG_LOCAL=.gitmodules git config "$@"
|
||||
}
|
||||
|
||||
# Get paxutils files.
|
||||
case ${PAXUTILS_SRCDIR--} in
|
||||
-) if [ ! -d paxutils ]; then
|
||||
echo "$0: getting paxutils files..."
|
||||
|
||||
trap "cleanup paxutils" 1 2 13 15
|
||||
|
||||
git clone --depth 1 git://git.sv.gnu.org/paxutils || cleanup paxutils
|
||||
|
||||
trap - 1 2 13 15
|
||||
fi
|
||||
PAXUTILS_SRCDIR=paxutils
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -r $PAXUTILS_SRCDIR/gnulib.modules ]; then
|
||||
gnulib_modules=`
|
||||
(echo "$gnulib_modules"; grep '^[^#]' $PAXUTILS_SRCDIR/gnulib.modules) |
|
||||
sort -u
|
||||
`
|
||||
fi
|
||||
|
||||
# Get gnulib files.
|
||||
|
||||
case ${GNULIB_SRCDIR--} in
|
||||
-)
|
||||
if git_modules_config submodule.gnulib.url >/dev/null; then
|
||||
echo "$0: getting gnulib files..."
|
||||
git submodule init || exit $?
|
||||
git submodule update || exit $?
|
||||
|
||||
elif [ ! -d gnulib ]; then
|
||||
echo "$0: getting gnulib files..."
|
||||
|
||||
trap cleanup_gnulib 1 2 13 15
|
||||
|
||||
git clone --help|grep depth > /dev/null && shallow='--depth 2' || shallow=
|
||||
git clone $shallow git://git.sv.gnu.org/gnulib ||
|
||||
"cleanup $1"
|
||||
|
||||
trap - 1 2 13 15
|
||||
fi
|
||||
GNULIB_SRCDIR=gnulib
|
||||
;;
|
||||
*)
|
||||
# Redirect the gnulib submodule to the directory on the command line
|
||||
# if possible.
|
||||
if test -d "$GNULIB_SRCDIR"/.git && \
|
||||
git_modules_config submodule.gnulib.url >/dev/null; then
|
||||
git submodule init
|
||||
GNULIB_SRCDIR=`cd $GNULIB_SRCDIR && pwd`
|
||||
git config --replace-all submodule.gnulib.url $GNULIB_SRCDIR
|
||||
echo "$0: getting gnulib files..."
|
||||
git submodule update || exit $?
|
||||
GNULIB_SRCDIR=gnulib
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
|
||||
<$gnulib_tool || exit
|
||||
|
||||
# Get translations.
|
||||
|
||||
@@ -252,7 +345,7 @@ update_po_files() {
|
||||
|
||||
langs=`cd $ref_po_dir && echo *.po|sed 's/\.po//g'`
|
||||
test "$langs" = '*' && langs=x
|
||||
for po in `cd $ref_po_dir && echo *.po|sed 's/\.po//g'`; do
|
||||
for po in $langs; do
|
||||
case $po in x) continue;; esac
|
||||
new_po="$ref_po_dir/$po.po"
|
||||
cksum_file="$ref_po_dir/$po.s1"
|
||||
@@ -265,97 +358,41 @@ update_po_files() {
|
||||
done
|
||||
}
|
||||
|
||||
case $DOWNLOAD_PO in
|
||||
'skip')
|
||||
;;
|
||||
case $SKIP_PO in
|
||||
'')
|
||||
if test -d po; then
|
||||
update_po_files po $package || exit
|
||||
fi
|
||||
;;
|
||||
'only')
|
||||
if test -d po; then
|
||||
update_po_files po $package || exit
|
||||
fi
|
||||
exit
|
||||
;;
|
||||
|
||||
if test -d runtime-po; then
|
||||
update_po_files runtime-po $package-runtime || exit
|
||||
fi;;
|
||||
esac
|
||||
|
||||
# Get paxutils files.
|
||||
|
||||
case ${PAXUTILS_SRCDIR--} in
|
||||
-) checkout paxutils
|
||||
PAXUTILS_SRCDIR=paxutils
|
||||
esac
|
||||
|
||||
if [ -r $PAXUTILS_SRCDIR/gnulib.modules ]; then
|
||||
gnulib_modules=`
|
||||
(echo "$gnulib_modules"; grep '^[^#]' $PAXUTILS_SRCDIR/gnulib.modules) |
|
||||
sort -u
|
||||
`
|
||||
fi
|
||||
|
||||
ignore_file_list=
|
||||
cleanup_ifl() {
|
||||
test -n "$ignore_file_list" && rm -f $ignore_file_list
|
||||
}
|
||||
|
||||
trap 'cleanup_ifl' 1 2 3 15
|
||||
|
||||
# ignorefile DIR FILE
|
||||
# add FILE to the temporary ignorelist in the directory DIR
|
||||
ignorefile() {
|
||||
file=$1/.ignore.$$
|
||||
echo "$2" >> $file
|
||||
if `echo $ignore_list | grep -qv $file`; then
|
||||
ignore_file_list="$ignore_file_list
|
||||
$file"
|
||||
fi
|
||||
}
|
||||
|
||||
# copy_files srcdir dstdir
|
||||
copy_files() {
|
||||
for file in `cat $1/DISTFILES`
|
||||
do
|
||||
case $file in
|
||||
"#*") continue;;
|
||||
esac
|
||||
dst=`echo $file | sed 's^.*/^^'`
|
||||
if [ $# -eq 3 ]; then
|
||||
case $dst in
|
||||
${3}*) ;;
|
||||
*) dst=${3}$dst;;
|
||||
esac
|
||||
fi
|
||||
echo "$0: Copying file $1/$file to $2/$dst"
|
||||
cp -p $1/$file $2/$dst
|
||||
ignorefile $2 $dst
|
||||
done
|
||||
}
|
||||
|
||||
# Get gnulib files.
|
||||
|
||||
case ${GNULIB_SRCDIR--} in
|
||||
-)
|
||||
checkout gnulib
|
||||
GNULIB_SRCDIR=gnulib
|
||||
esac
|
||||
|
||||
gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
|
||||
<$gnulib_tool || exit
|
||||
|
||||
ensure_dir_exists()
|
||||
symlink_to_dir()
|
||||
{
|
||||
d=`dirname $dst`
|
||||
test -d "$d" || mkdir -p -- "$d"
|
||||
}
|
||||
|
||||
symlink_to_gnulib()
|
||||
{
|
||||
src=$GNULIB_SRCDIR/$1
|
||||
dst=${2-$1}
|
||||
src=$1/$2
|
||||
dst=${3-$2}
|
||||
|
||||
test -f "$src" && {
|
||||
|
||||
# If the destination directory doesn't exist, create it.
|
||||
# This is required at least for "lib/uniwidth/cjk.h".
|
||||
dst_dir=`dirname "$dst"`
|
||||
if ! test -d "$dst_dir"; then
|
||||
mkdir -p "$dst_dir"
|
||||
|
||||
# If we've just created a directory like lib/uniwidth,
|
||||
# tell version control system(s) it's ignorable.
|
||||
# FIXME: for now, this does only one level
|
||||
parent=`dirname "$dst_dir"`
|
||||
for dot_ig in x $vc_ignore; do
|
||||
test $dot_ig = x && continue
|
||||
ig=$parent/$dot_ig
|
||||
insert_sorted_if_absent $ig `echo "$dst_dir"|sed 's,.*/,,'`
|
||||
done
|
||||
fi
|
||||
|
||||
if $copy; then
|
||||
{
|
||||
test ! -h "$dst" || {
|
||||
@@ -366,7 +403,6 @@ symlink_to_gnulib()
|
||||
test -f "$dst" &&
|
||||
cmp -s "$src" "$dst" || {
|
||||
echo "$0: cp -fp $src $dst" &&
|
||||
ensure_dir_exists $dst &&
|
||||
cp -fp "$src" "$dst"
|
||||
}
|
||||
else
|
||||
@@ -379,6 +415,7 @@ symlink_to_gnulib()
|
||||
/*) ;;
|
||||
*)
|
||||
case /$dst/ in
|
||||
/./*) ;;
|
||||
*//* | */../* | */./* | /*/*/*/*/*/)
|
||||
echo >&2 "$0: invalid symlink calculation: $src -> $dst"
|
||||
exit 1;;
|
||||
@@ -389,7 +426,6 @@ symlink_to_gnulib()
|
||||
esac
|
||||
|
||||
echo "$0: ln -fs $dot_dots$src $dst" &&
|
||||
ensure_dir_exists $dst &&
|
||||
ln -fs "$dot_dots$src" "$dst"
|
||||
}
|
||||
fi
|
||||
@@ -402,7 +438,9 @@ cp_mark_as_generated()
|
||||
cp_dst=$2
|
||||
|
||||
if cmp -s "$cp_src" "$GNULIB_SRCDIR/$cp_dst"; then
|
||||
symlink_to_gnulib "$cp_dst"
|
||||
symlink_to_dir "$GNULIB_SRCDIR" "$cp_dst"
|
||||
elif cmp -s "$cp_src" "$local_gl_dir/$cp_dst"; then
|
||||
symlink_to_dir $local_gl_dir "$cp_dst"
|
||||
else
|
||||
case $cp_dst in
|
||||
*.[ch]) c1='/* '; c2=' */';;
|
||||
@@ -411,10 +449,20 @@ cp_mark_as_generated()
|
||||
*) c1= ; c2= ;;
|
||||
esac
|
||||
|
||||
# If the destination directory doesn't exist, create it.
|
||||
# This is required at least for "lib/uniwidth/cjk.h".
|
||||
dst_dir=`dirname "$cp_dst"`
|
||||
test -d "$dst_dir" || mkdir -p "$dst_dir"
|
||||
|
||||
if test -z "$c1"; then
|
||||
cmp -s "$cp_src" "$cp_dst" || {
|
||||
# Copy the file first to get proper permissions if it
|
||||
# doesn't already exist. Then overwrite the copy.
|
||||
echo "$0: cp -f $cp_src $cp_dst" &&
|
||||
cp -f "$cp_src" "$cp_dst"
|
||||
rm -f "$cp_dst" &&
|
||||
cp "$cp_src" "$cp_dst-t" &&
|
||||
sed "s!$bt_regex/!!g" "$cp_src" > "$cp_dst-t" &&
|
||||
mv -f "$cp_dst-t" "$cp_dst"
|
||||
}
|
||||
else
|
||||
# Copy the file first to get proper permissions if it
|
||||
@@ -423,7 +471,7 @@ cp_mark_as_generated()
|
||||
(
|
||||
echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" &&
|
||||
echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" &&
|
||||
cat "$cp_src"
|
||||
sed "s!$bt_regex/!!g" "$cp_src"
|
||||
) > $cp_dst-t &&
|
||||
if cmp -s "$cp_dst-t" "$cp_dst"; then
|
||||
rm -f "$cp_dst-t"
|
||||
@@ -443,7 +491,9 @@ version_controlled_file() {
|
||||
grep -F "/$file/" $dir/CVS/Entries 2>/dev/null |
|
||||
grep '^/[^/]*/[0-9]' > /dev/null && found=yes
|
||||
elif test -d .git; then
|
||||
git-rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
|
||||
git rm -n "$dir/$file" > /dev/null 2>&1 && found=yes
|
||||
elif test -d .svn; then
|
||||
svn log -r HEAD "$dir/$file" > /dev/null 2>&1 && found=yes
|
||||
else
|
||||
echo "$0: no version control for $dir/$file?" >&2
|
||||
fi
|
||||
@@ -454,18 +504,22 @@ slurp() {
|
||||
for dir in . `(cd $1 && find * -type d -print)`; do
|
||||
copied=
|
||||
sep=
|
||||
for file in `ls $1/$dir`; do
|
||||
for file in `ls -a $1/$dir`; do
|
||||
case $file in
|
||||
.|..) continue;;
|
||||
.*) continue;; # FIXME: should all file names starting with "." be ignored?
|
||||
esac
|
||||
test -d $1/$dir/$file && continue
|
||||
for excluded_file in $excluded_files; do
|
||||
test "$dir/$file" = "$excluded_file" && continue 2
|
||||
done
|
||||
if test $file = Makefile.am; then
|
||||
copied=$copied${sep}gnulib.mk; sep=$nl
|
||||
remove_intl='/^[^#].*\/intl/s/^/#/;'"s,/$bt,,g"
|
||||
sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/gnulib.mk || {
|
||||
echo "$0: Copying $1/$dir/$file to $dir/gnulib.mk ..." &&
|
||||
rm -f $dir/gnulib.mk &&
|
||||
sed "$remove_intl" $1/$dir/$file >$dir/gnulib.mk
|
||||
copied=$copied${sep}$gnulib_mk; sep=$nl
|
||||
remove_intl='/^[^#].*\/intl/s/^/#/;'"s!$bt_regex/!!g"
|
||||
sed "$remove_intl" $1/$dir/$file | cmp -s - $dir/$gnulib_mk || {
|
||||
echo "$0: Copying $1/$dir/$file to $dir/$gnulib_mk ..." &&
|
||||
rm -f $dir/$gnulib_mk &&
|
||||
sed "$remove_intl" $1/$dir/$file >$dir/$gnulib_mk
|
||||
}
|
||||
elif { test "${2+set}" = set && test -r $2/$dir/$file; } ||
|
||||
version_controlled_file $dir $file; then
|
||||
@@ -489,98 +543,109 @@ slurp() {
|
||||
fi || exit
|
||||
done
|
||||
|
||||
if test -n "$copied"; then
|
||||
copied="Makefile
|
||||
Makefile.in
|
||||
$copied"
|
||||
if test -d CVS; then
|
||||
dot_ig=.cvsignore
|
||||
else
|
||||
dor_ig=.gitignore
|
||||
fi
|
||||
|
||||
for dot_ig in x $vc_ignore; do
|
||||
test $dot_ig = x && continue
|
||||
ig=$dir/$dot_ig
|
||||
if [ -f $dir/.ignore.$$ ]; then
|
||||
tfile=$dir/.ignore.$$
|
||||
else
|
||||
tfile=
|
||||
if test -n "$copied"; then
|
||||
insert_sorted_if_absent $ig "$copied"
|
||||
# If an ignored file name ends with .in.h, then also add
|
||||
# the name with just ".h". Many gnulib headers are generated,
|
||||
# e.g., stdint.in.h -> stdint.h, dirent.in.h ->..., etc.
|
||||
# Likewise for .gperf -> .h, .y -> .c, and .sin -> .sed
|
||||
f=`echo "$copied"|sed 's/\.in\.h$/.h/;s/\.sin$/.sed/;s/\.y$/.c/;s/\.gperf$/.h/'`
|
||||
insert_sorted_if_absent $ig "$f"
|
||||
|
||||
# For files like sys_stat.in.h and sys_time.in.h, record as
|
||||
# ignorable the directory we might eventually create: sys/.
|
||||
f=`echo "$copied"|sed 's/sys_.*\.in\.h$/sys/'`
|
||||
insert_sorted_if_absent $ig "$f"
|
||||
fi
|
||||
if test -f $ig; then
|
||||
echo "$copied" | sort -u - $ig | cmp -s - $ig ||
|
||||
echo "$copied" | sort -u - $ig $tfile -o $ig
|
||||
else
|
||||
copied="$dot_ig
|
||||
$copied"
|
||||
if [ "$dir" = "po" ]; then
|
||||
copied="LINGUAS
|
||||
Makevars
|
||||
POTFILES
|
||||
*.mo
|
||||
*.gmo
|
||||
*.po
|
||||
remove-potcdate.sed
|
||||
stamp-po
|
||||
$package.pot
|
||||
$copied"
|
||||
fi
|
||||
echo "$copied" | sort -u - $tfile -o $ig
|
||||
fi || exit
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# Create boot temporary directories to import from gnulib and gettext.
|
||||
|
||||
bt='.#bootmp'
|
||||
bt2=${bt}2
|
||||
rm -fr $bt $bt2 &&
|
||||
mkdir $bt $bt2 || exit
|
||||
|
||||
# Import from gnulib.
|
||||
|
||||
test -d build-aux || {
|
||||
echo "$0: mkdir build-aux ..." &&
|
||||
mkdir build-aux
|
||||
} || exit
|
||||
gnulib_tool_options="\
|
||||
--import\
|
||||
--no-changelog\
|
||||
--aux-dir $bt/build-aux\
|
||||
--doc-base $bt/doc\
|
||||
--lib lib$package\
|
||||
--m4-base $bt/m4/\
|
||||
--source-base $bt/lib/\
|
||||
--tests-base $bt/tests\
|
||||
--local-dir gl\
|
||||
--aux-dir $bt/$build_aux\
|
||||
--doc-base $bt/$doc_base\
|
||||
--lib $gnulib_name\
|
||||
--m4-base $bt/$m4_base/\
|
||||
--source-base $bt/$source_base/\
|
||||
--tests-base $bt/$tests_base\
|
||||
--local-dir $local_gl_dir\
|
||||
$gnulib_tool_option_extras\
|
||||
"
|
||||
echo "$0: $gnulib_tool $gnulib_tool_options --import ..."
|
||||
$gnulib_tool $gnulib_tool_options --import $gnulib_modules &&
|
||||
slurp $bt || exit
|
||||
|
||||
for file in $gnulib_files; do
|
||||
symlink_to_gnulib $file || exit
|
||||
symlink_to_dir "$GNULIB_SRCDIR" $file || exit
|
||||
done
|
||||
|
||||
|
||||
# Import from gettext.
|
||||
with_gettext=yes
|
||||
grep '^[ ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \
|
||||
with_gettext=no
|
||||
|
||||
echo "$0: (cd $bt2; autopoint) ..."
|
||||
cp configure.ac $bt2 &&
|
||||
(cd $bt2 && autopoint && rm configure.ac) &&
|
||||
slurp $bt2 $bt || exit
|
||||
|
||||
if test $with_gettext = yes; then
|
||||
echo "$0: (cd $bt2; autopoint) ..."
|
||||
cp configure.ac $bt2 &&
|
||||
(cd $bt2 && autopoint && rm configure.ac) &&
|
||||
slurp $bt2 $bt || exit
|
||||
fi
|
||||
rm -fr $bt $bt2 || exit
|
||||
|
||||
# Remove any dangling symlink matching "*.m4" or "*.[ch]" in some
|
||||
# gnulib-populated directories. Such .m4 files would cause aclocal to fail.
|
||||
# The following requires GNU find 4.2.3 or newer. Considering the usual
|
||||
# portability constraints of this script, that may seem a very demanding
|
||||
# requirement, but it should be ok. Ignore any failure, which is fine,
|
||||
# since this is only a convenience to help developers avoid the relatively
|
||||
# unusual case in which a symlinked-to .m4 file is git-removed from gnulib
|
||||
# between successive runs of this script.
|
||||
find "$m4_base" "$source_base" \
|
||||
-depth \( -name '*.m4' -o -name '*.[ch]' \) \
|
||||
-type l -xtype l -delete > /dev/null 2>&1
|
||||
|
||||
# copy_files srcdir dstdir
|
||||
copy_files() {
|
||||
for file in `cat $1/DISTFILES`
|
||||
do
|
||||
case $file in
|
||||
"#*") continue;;
|
||||
esac
|
||||
dst=`echo $file | sed 's^.*/^^'`
|
||||
if [ $# -eq 3 ]; then
|
||||
case $dst in
|
||||
${3}*) ;;
|
||||
*) dst=${3}$dst;;
|
||||
esac
|
||||
fi
|
||||
symlink_to_dir "$1" "$file" "$2/$dst" || exit
|
||||
# FIXME ignorefile $2 $dst
|
||||
done
|
||||
}
|
||||
|
||||
# Import from paxutils
|
||||
copy_files ${PAXUTILS_SRCDIR}/m4 m4
|
||||
copy_files ${PAXUTILS_SRCDIR} .
|
||||
copy_files ${PAXUTILS_SRCDIR}/am m4
|
||||
echo "$0: Creating m4/paxutils.m4"
|
||||
(echo "# This file is generated automatically. Please, do not edit."
|
||||
echo "#"
|
||||
echo "AC_DEFUN([${package}_PAXUTILS],["
|
||||
cat ${PAXUTILS_SRCDIR}/m4/DISTFILES | sed '/^#/d;s/\(.*\)\.m4/pu_\1/' | tr a-z A-Z
|
||||
cat ${PAXUTILS_SRCDIR}/am/DISTFILES | sed '/^#/d;s/\(.*\)\.m4/pu_\1/' | tr a-z A-Z
|
||||
echo "])") > ./m4/paxutils.m4
|
||||
ignorefile m4 paxutils.m4
|
||||
#FIXME ignorefile m4 paxutils.m4
|
||||
|
||||
if [ -d rmt ]; then
|
||||
:
|
||||
@@ -595,59 +660,75 @@ done
|
||||
|
||||
copy_files ${PAXUTILS_SRCDIR}/paxlib lib pax
|
||||
|
||||
|
||||
# Reconfigure, getting other files.
|
||||
|
||||
for command in \
|
||||
libtool \
|
||||
'aclocal --force -I m4' \
|
||||
'autoconf --force' \
|
||||
'autoheader --force' \
|
||||
'automake --add-missing --copy --force-missing';
|
||||
do
|
||||
if test "$command" = libtool; then
|
||||
use_libtool=0
|
||||
# We'd like to use grep -E, to see if any of LT_INIT,
|
||||
# AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,
|
||||
# but that's not portable enough (e.g., for Solaris).
|
||||
grep '^[ ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \
|
||||
&& use_libtool=1
|
||||
grep '^[ ]*LT_INIT' configure.ac >/dev/null \
|
||||
&& use_libtool=1
|
||||
test $use_libtool = 0 \
|
||||
&& continue
|
||||
command='libtoolize -c -f'
|
||||
fi
|
||||
echo "$0: $command ..."
|
||||
$command || exit
|
||||
done
|
||||
|
||||
|
||||
# Get some extra files from gnulib, overriding existing files.
|
||||
|
||||
for file in $gnulib_extra_files; do
|
||||
case $file in
|
||||
*/INSTALL) dst=INSTALL;;
|
||||
build-aux/*) dst=$build_aux/`expr "$file" : 'build-aux/\(.*\)'`;;
|
||||
*) dst=$file;;
|
||||
esac
|
||||
symlink_to_gnulib $file $dst || exit
|
||||
symlink_to_dir "$GNULIB_SRCDIR" $file $dst || exit
|
||||
done
|
||||
|
||||
|
||||
# Create gettext configuration.
|
||||
echo "$0: Creating po/Makevars from po/Makevars.template ..."
|
||||
rm -f po/Makevars
|
||||
sed '
|
||||
/^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
|
||||
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
|
||||
/^XGETTEXT_OPTIONS *=/{
|
||||
s/$/ \\/
|
||||
a\
|
||||
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
|
||||
}
|
||||
' po/Makevars.template >po/Makevars
|
||||
|
||||
if test -d runtime-po; then
|
||||
# Similarly for runtime-po/Makevars, but not quite the same.
|
||||
rm -f runtime-po/Makevars
|
||||
if test $with_gettext = yes; then
|
||||
# Create gettext configuration.
|
||||
echo "$0: Creating po/Makevars from po/Makevars.template ..."
|
||||
rm -f po/Makevars
|
||||
sed '
|
||||
/^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
|
||||
/^subdir *=.*/s/=.*/= runtime-po/
|
||||
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
|
||||
/^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/
|
||||
/^MSGID_BUGS_ADDRESS *=/s/=.*/= '"$MSGID_BUGS_ADDRESS"'/
|
||||
/^XGETTEXT_OPTIONS *=/{
|
||||
s/$/ \\/
|
||||
a\
|
||||
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
|
||||
'"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+}
|
||||
}
|
||||
' <po/Makevars.template >runtime-po/Makevars
|
||||
' po/Makevars.template >po/Makevars
|
||||
|
||||
# Copy identical files from po to runtime-po.
|
||||
(cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
|
||||
if test -d runtime-po; then
|
||||
# Similarly for runtime-po/Makevars, but not quite the same.
|
||||
rm -f runtime-po/Makevars
|
||||
sed '
|
||||
/^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/
|
||||
/^subdir *=.*/s/=.*/= runtime-po/
|
||||
/^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/
|
||||
/^XGETTEXT_OPTIONS *=/{
|
||||
s/$/ \\/
|
||||
a\
|
||||
'"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+}
|
||||
}
|
||||
' <po/Makevars.template >runtime-po/Makevars
|
||||
|
||||
# Copy identical files from po to runtime-po.
|
||||
(cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)
|
||||
fi
|
||||
fi
|
||||
cleanup_ifl
|
||||
|
||||
echo "$0: done. Now you can run './configure'."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Bootstrap configuration.
|
||||
# Bootstrap configuration for GNU tar.
|
||||
|
||||
# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006, 2007, 2008, 2009 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
|
||||
@@ -17,12 +17,14 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
source_base=gnu
|
||||
gnulib_name=libgnu
|
||||
gnulib_mk=Makefile.am
|
||||
|
||||
# We don't need these modules, even though gnulib-tool mistakenly
|
||||
# includes them because of gettext dependencies.
|
||||
avoided_gnulib_modules='
|
||||
--avoid=lock
|
||||
--avoid=size_max
|
||||
'
|
||||
|
||||
# gnulib modules used by this package.
|
||||
@@ -52,8 +54,21 @@ excluded_files='
|
||||
m4/lcmessage.m4
|
||||
m4/lock.m4
|
||||
m4/printf-posix.m4
|
||||
m4/size_max.m4
|
||||
m4/uintmax_t.m4
|
||||
m4/ulonglong.m4
|
||||
m4/visibility.m4
|
||||
'
|
||||
|
||||
# Read local configuration file
|
||||
if [ -r .bootstrap ]; then
|
||||
echo "$0: Reading configuration file .bootstrap"
|
||||
eval set -- "`sed 's/#.*$//;/^$/d' .bootstrap | tr '\n' ' '` $*"
|
||||
fi
|
||||
|
||||
test -d m4 || mkdir m4
|
||||
test -d $source_base || mkdir $source_base
|
||||
|
||||
cat > ChangeLog <<EOT
|
||||
This file is a placeholder. It will be replaced with the actual ChangeLog
|
||||
by make dist. Run make ChangeLog if you wish to create it earlier.
|
||||
EOT
|
||||
|
||||
24
configure.ac
24
configure.ac
@@ -1,7 +1,8 @@
|
||||
# Configure template for GNU tar. -*- autoconf -*-
|
||||
|
||||
# Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
|
||||
@@ -18,12 +19,15 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
|
||||
AC_INIT([GNU tar], [1.21], [bug-tar@gnu.org])
|
||||
AC_INIT([GNU tar], [1.23], [bug-tar@gnu.org])
|
||||
AC_CONFIG_SRCDIR([src/tar.c])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h:config.hin])
|
||||
AC_PREREQ([2.60])
|
||||
AM_INIT_AUTOMAKE([1.9 gnits tar-ustar dist-bzip2 dist-shar std-options])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_PREREQ([2.63])
|
||||
AM_INIT_AUTOMAKE([1.11 gnits tar-ustar dist-bzip2 dist-shar std-options silent-rules])
|
||||
|
||||
# Enable silent rules by default:
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_EXEEXT
|
||||
@@ -48,7 +52,6 @@ AC_CHECK_HEADERS([sys/buf.h], [], [],
|
||||
#endif])
|
||||
|
||||
AC_HEADER_SYS_WAIT
|
||||
AM_STDBOOL_H
|
||||
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_MAJOR
|
||||
@@ -122,6 +125,14 @@ else
|
||||
[Define to the full path of your rsh, if any.])
|
||||
fi
|
||||
|
||||
TAR_COMPR_PROGRAM(compress)
|
||||
TAR_COMPR_PROGRAM(gzip)
|
||||
TAR_COMPR_PROGRAM(bzip2)
|
||||
TAR_COMPR_PROGRAM(lzip)
|
||||
TAR_COMPR_PROGRAM(lzma)
|
||||
TAR_COMPR_PROGRAM(lzop)
|
||||
TAR_COMPR_PROGRAM(xz)
|
||||
|
||||
AC_MSG_CHECKING(for default archive format)
|
||||
|
||||
AC_ARG_VAR([DEFAULT_ARCHIVE_FORMAT],
|
||||
@@ -241,6 +252,7 @@ fi
|
||||
|
||||
AC_OUTPUT([Makefile\
|
||||
doc/Makefile\
|
||||
gnu/Makefile\
|
||||
lib/Makefile\
|
||||
po/Makefile.in\
|
||||
scripts/Makefile\
|
||||
|
||||
25
doc/.cvsignore → doc/.gitignore
vendored
25
doc/.cvsignore → doc/.gitignore
vendored
@@ -1,37 +1,26 @@
|
||||
*.stamp
|
||||
Makefile
|
||||
Makefile.in
|
||||
genfile.texi
|
||||
getdate.texi
|
||||
header.texi
|
||||
html_chapter
|
||||
html_mono
|
||||
html_node
|
||||
manual
|
||||
stamp-vti
|
||||
tar.at
|
||||
tar.ats
|
||||
tar.aux
|
||||
tar.cp
|
||||
tar.cps
|
||||
tar.dvi
|
||||
tar.ex
|
||||
tar.exs
|
||||
tar.fl
|
||||
tar.fn
|
||||
tar.fns
|
||||
tar.html
|
||||
tar.info
|
||||
tar.info*
|
||||
tar.info-*
|
||||
tar.kw
|
||||
tar.kws
|
||||
tar.ky
|
||||
tar.log
|
||||
tar.mt
|
||||
tar.op
|
||||
tar.ops
|
||||
tar.pdf
|
||||
tar.pg
|
||||
tar.pgs
|
||||
tar.ps
|
||||
tar.pr
|
||||
tar.t2d
|
||||
tar.toc
|
||||
tar.tp
|
||||
tar.vr
|
||||
tar.vrs
|
||||
version.texi
|
||||
@@ -59,25 +59,28 @@ check-format:
|
||||
fi
|
||||
|
||||
check-options:
|
||||
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,\
|
||||
doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
|
||||
@ARGP_HELP_FMT='usage-indent=0,short-opt-col=0,long-opt-col=0,doc-opt-col=0,opt-doc-col=0,header-col=0,rmargin=1' \
|
||||
$(top_builddir)/src/tar --usage | \
|
||||
sed -n 's/^\[--\([^]\=\[]*\).*/\1/p' | sort | uniq > opts.$$$$;\
|
||||
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \
|
||||
$(info_TEXINFOS) | \
|
||||
sed -n '/^@macro/,/^@end macro/d;s/@opindex *\([^@,]*\).*/\1/p' \
|
||||
| sort | uniq > docs.$$$$;\
|
||||
(echo 'Not documented options:';\
|
||||
join -v1 opts.$$$$ docs.$$$$;\
|
||||
echo 'Non-existing options:';\
|
||||
join -v2 opts.$$$$ docs.$$$$) > report.$$$$;\
|
||||
rm opts.$$$$ docs.$$$$;\
|
||||
if [ -n "`sed '1,2d' report.$$$$`" ]; then \
|
||||
cat report.$$$$;\
|
||||
rm report.$$$$;\
|
||||
exit 1;\
|
||||
fi;\
|
||||
rm report.$$$$
|
||||
status=0;\
|
||||
join -v1 opts.$$$$ docs.$$$$ > report.$$$$;\
|
||||
if test -s report.$$$$; then \
|
||||
echo 'Not documented options:'; \
|
||||
cat report.$$$$; \
|
||||
status=1; \
|
||||
fi; \
|
||||
join -v2 opts.$$$$ docs.$$$$ > report.$$$$;\
|
||||
if test -s report.$$$$; then \
|
||||
echo 'Non-existing options:';\
|
||||
cat report.$$$$; \
|
||||
status=1; \
|
||||
fi; \
|
||||
rm opts.$$$$ docs.$$$$ report.$$$$;\
|
||||
test $$status -ne 0 && exit $$status
|
||||
|
||||
check-refs:
|
||||
@for file in $(info_TEXINFOS) $(tar_TEXINFOS); \
|
||||
|
||||
@@ -23,14 +23,14 @@ snapshots only in format 2.
|
||||
This appendix describes all three formats in detail.
|
||||
|
||||
@enumerate 0
|
||||
@cindex format 0, snapshot file
|
||||
@cindex format 0, snapshot file
|
||||
@cindex snapshot file, format 0
|
||||
@item
|
||||
@item
|
||||
@samp{Format 0} snapshot file begins with a line containing a
|
||||
decimal number that represents a @acronym{UNIX} timestamp of the
|
||||
beginning of the last archivation. This line is followed by directory
|
||||
metadata descriptions, one per line. Each description has the
|
||||
following format:
|
||||
following format:
|
||||
|
||||
@smallexample
|
||||
@var{nfs}@var{dev} @var{inode} @var{name}
|
||||
@@ -55,9 +55,9 @@ Name of the directory. Any special characters (white-space,
|
||||
backslashes, etc.) are quoted.
|
||||
@end table
|
||||
|
||||
@cindex format 1, snapshot file
|
||||
@cindex format 1, snapshot file
|
||||
@cindex snapshot file, format 1
|
||||
@item
|
||||
@item
|
||||
@samp{Format 1} snapshot file begins with a line specifying the
|
||||
format of the file. This line has the following structure:
|
||||
|
||||
@@ -69,7 +69,7 @@ format of the file. This line has the following structure:
|
||||
where @var{tar-version} is the version number of @GNUTAR{}
|
||||
implementation that created this snapshot, and
|
||||
@var{incr-format-version} is the version number of the snapshot format
|
||||
(in this case @samp{1}).
|
||||
(in this case @samp{1}).
|
||||
|
||||
Next line contains two decimal numbers, representing the
|
||||
time of the last backup. First number is the number of seconds, the
|
||||
@@ -89,11 +89,11 @@ modification time of this directory with nanosecond precision;
|
||||
@var{nfs}, @var{dev}, @var{inode} and @var{name} have the same meaning
|
||||
as with @samp{format 0}.
|
||||
|
||||
@cindex format 2, snapshot file
|
||||
@cindex format 2, snapshot file
|
||||
@cindex snapshot file, format 2
|
||||
@item
|
||||
@FIXME{}
|
||||
A snapshot file begins with a format identifier, as described for
|
||||
@item
|
||||
@samp{Format 2} snapshot file begins with a format identifier, as described for
|
||||
version 1, e.g.:
|
||||
|
||||
@smallexample
|
||||
@@ -109,7 +109,7 @@ snapshot is a binary file.
|
||||
time of the last backup. First number is the number of seconds, the
|
||||
second one is the number of nanoseconds, since the beginning of the
|
||||
epoch. These are followed by arbitrary number of directory records.
|
||||
|
||||
|
||||
Each @dfn{directory record} contains a set of metadata describing a
|
||||
particular directory. Parts of a directory record are delimited with
|
||||
@acronym{ASCII} 0 characters. The following table describes each
|
||||
@@ -124,11 +124,11 @@ an @acronym{NFS}-mounted partition, or @samp{0} otherwise;
|
||||
@item mtime-nano @tab Number @tab Modification time, nanoseconds;
|
||||
@item dev-no @tab Number @tab Device number;
|
||||
@item i-no @tab Number @tab I-node number;
|
||||
@item name @tab String @tab Directory name; In contrast to the
|
||||
previous versions it is not quoted.
|
||||
@item name @tab String @tab Directory name; in contrast to the
|
||||
previous versions it is not quoted;
|
||||
@item contents @tab Dumpdir @tab Contents of the directory;
|
||||
@xref{Dumpdir}, for a description of its format.
|
||||
@item
|
||||
@item
|
||||
@end multitable
|
||||
|
||||
Dumpdirs stored in snapshot files contain only records of types
|
||||
@@ -138,4 +138,3 @@ previous versions it is not quoted.
|
||||
|
||||
@c End of snapshot.texi
|
||||
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@ The support for sparse files in @GNUTAR{} has a long history. The
|
||||
earliest version featuring this support that I was able to find was 1.09,
|
||||
released in November, 1990. The format introduced back then is called
|
||||
@dfn{old GNU} sparse format and in spite of the fact that its design
|
||||
contained many flaws, it was the only format @GNUTAR{} supported
|
||||
contained many flaws, it was the only format @GNUTAR{} supported
|
||||
until version 1.14 (May, 2004), which introduced initial support for
|
||||
sparse archives in @acronym{PAX} archives (@pxref{posix}). This
|
||||
format was not free from design flows, either and it was subsequently
|
||||
format was not free from design flaws, either and it was subsequently
|
||||
improved in versions 1.15.2 (November, 2005) and 1.15.92 (June,
|
||||
2006).
|
||||
2006).
|
||||
|
||||
In addition to GNU sparse format, @GNUTAR{} is able to read and
|
||||
extract sparse files archived by @command{star}.
|
||||
@@ -37,7 +37,7 @@ The following subsections describe each format in detail.
|
||||
|
||||
@cindex sparse formats, Old GNU
|
||||
@cindex Old GNU sparse format
|
||||
The format introduced some time around 1990 (v. 1.09). It was
|
||||
The format introduced in November 1990 (v. 1.09) was
|
||||
designed on top of standard @code{ustar} headers in such an
|
||||
unfortunate way that some of its fields overwrote fields required by
|
||||
POSIX.
|
||||
@@ -61,7 +61,7 @@ extension sparse header follows, @code{0} otherwise.
|
||||
@end multitable
|
||||
|
||||
Each of @code{sparse_header} object at offset 386 describes a single
|
||||
data chunk. It has the following structure:
|
||||
data chunk. It has the following structure:
|
||||
|
||||
@multitable @columnfractions 0.10 0.10 0.20 0.60
|
||||
@headitem Offset @tab Size @tab Data type @tab Contents
|
||||
@@ -78,7 +78,7 @@ the following structure:
|
||||
@multitable @columnfractions 0.10 0.10 0.20 0.20 0.40
|
||||
@headitem Offset @tab Size @tab Name @tab Data type @tab Contents
|
||||
@item 0 @tab 21 @tab sp @tab @code{sparse_header} @tab
|
||||
(21 entires) File map.
|
||||
(21 entries) File map.
|
||||
@item 504 @tab 1 @tab isextended @tab Bool @tab @code{1} if an
|
||||
extension sparse header follows, or @code{0} otherwise.
|
||||
@end multitable
|
||||
@@ -97,19 +97,19 @@ versions 1.14--1.15.1. The sparse file map is kept in extended
|
||||
@table @code
|
||||
@vrindex GNU.sparse.size, extended header variable
|
||||
@item GNU.sparse.size
|
||||
Real size of the stored file
|
||||
Real size of the stored file;
|
||||
|
||||
@item GNU.sparse.numblocks
|
||||
@vrindex GNU.sparse.numblocks, extended header variable
|
||||
Number of blocks in the sparse map
|
||||
Number of blocks in the sparse map;
|
||||
|
||||
@item GNU.sparse.offset
|
||||
@vrindex GNU.sparse.offset, extended header variable
|
||||
Offset of the data block
|
||||
Offset of the data block;
|
||||
|
||||
@item GNU.sparse.numbytes
|
||||
@vrindex GNU.sparse.numbytes, extended header variable
|
||||
Size of the data block
|
||||
Size of the data block.
|
||||
@end table
|
||||
|
||||
The latter two variables repeat for each data block, so the overall
|
||||
@@ -117,11 +117,11 @@ structure is like this:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
GNU.sparse.size=@var{size}
|
||||
GNU.sparse.numblocks=@var{numblocks}
|
||||
GNU.sparse.size=@var{size}
|
||||
GNU.sparse.numblocks=@var{numblocks}
|
||||
repeat @var{numblocks} times
|
||||
GNU.sparse.offset=@var{offset}
|
||||
GNU.sparse.numbytes=@var{numbytes}
|
||||
GNU.sparse.offset=@var{offset}
|
||||
GNU.sparse.numbytes=@var{numbytes}
|
||||
end repeat
|
||||
@end group
|
||||
@end smallexample
|
||||
@@ -136,8 +136,8 @@ meaningful. Thus, multiple occurrences of @code{GNU.sparse.offset} and
|
||||
@code{GNU.sparse.numbytes} are conflicting with the POSIX specs.
|
||||
|
||||
@item
|
||||
Attempting to extract such archives using a third-party @command{tar}s
|
||||
results in extraction of sparse files in @emph{compressed form}. If
|
||||
Attempting to extract such archives using a third-party's @command{tar}
|
||||
results in extraction of sparse files in @emph{condensed form}. If
|
||||
the @command{tar} implementation in question does not support POSIX
|
||||
format, it will also extract a file containing extension header
|
||||
attributes. This file can be used to expand the file to its original
|
||||
@@ -160,7 +160,7 @@ it uses a single variable:
|
||||
@item GNU.sparse.map
|
||||
@vrindex GNU.sparse.map, extended header variable
|
||||
Map of non-null data chunks. It is a string consisting of
|
||||
comma-separated values "@var{offset},@var{size}[,@var{offset-1},@var{size-1}...]"
|
||||
comma-separated values "@var{offset},@var{size}[,@var{offset-1},@var{size-1}...]"
|
||||
@end table
|
||||
|
||||
To address the 2nd problem, the @code{name} field in @code{ustar}
|
||||
@@ -181,7 +181,7 @@ restore such members using non-GNU @command{tar}s.
|
||||
|
||||
The resulting @code{GNU.sparse.map} string can be @emph{very} long.
|
||||
Although POSIX does not impose any limit on the length of a @code{x}
|
||||
header variable, this possibly can confuse some tars.
|
||||
header variable, this possibly can confuse some @command{tar}s.
|
||||
|
||||
@node PAX 1
|
||||
@appendixsubsec PAX Format, Version 1.0
|
||||
@@ -218,18 +218,18 @@ The real name of the sparse file is stored in the variable
|
||||
variable @code{GNU.sparse.realsize}.
|
||||
|
||||
The sparse map itself is stored in the file data block, preceding the actual
|
||||
file data. It consists of a series of octal numbers of arbitrary length, delimited
|
||||
file data. It consists of a series of octal numbers of arbitrary length, delimited
|
||||
by newlines. The map is padded with nulls to the nearest block boundary.
|
||||
|
||||
The first number gives the number of entries in the map. Following are map entries,
|
||||
each one consisting of two numbers giving the offset and size of the
|
||||
data block it describes.
|
||||
|
||||
The format is designed in such a way that non-posix aware tars and tars not
|
||||
The format is designed in such a way that non-posix aware @command{tar}s and @command{tar}s not
|
||||
supporting @code{GNU.sparse.*} keywords will extract each sparse file
|
||||
in its condensed form with the file map prepended and will place it
|
||||
into a separate directory. Then, using a simple program it would be
|
||||
possible to expand the file to its original form even without @GNUTAR{}.
|
||||
@xref{Sparse Recovery}, for the detailed information on how to extract
|
||||
sparse members without @GNUTAR{}.
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
@cindex snapshot files, editing
|
||||
@cindex snapshot files, fixing device numbers
|
||||
Sometimes device numbers can change after upgrading your kernel
|
||||
version or recofiguring the harvare. Reportedly this is the case with
|
||||
version or reconfiguring the hardware. Reportedly this is the case with
|
||||
some newer @i{Linux} kernels, when using @acronym{LVM}. In majority of
|
||||
cases this change is unnoticed by the users. However, it influences
|
||||
@command{tar} incremental backups: the device number is stored in tar
|
||||
@@ -21,9 +21,9 @@ the @command{tar-snapshot-edit} utility for inspecting and updating
|
||||
device numbers in snapshot files. The utility, written by
|
||||
Dustin J.@: Mitchell, is available from
|
||||
@uref{http://www.gnu.org/@/software/@/tar/@/utils/@/tar-snapshot-edit.html,
|
||||
@GNUTAR{} home page}.
|
||||
@GNUTAR{} home page}.
|
||||
|
||||
To obtain the device numbers used in the snapshot file, run
|
||||
To obtain the device numbers used in the snapshot file, run
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar-snapshot-edit @var{snapfile}}
|
||||
@@ -31,7 +31,7 @@ $ @kbd{tar-snapshot-edit @var{snapfile}}
|
||||
|
||||
@noindent
|
||||
where @var{snapfile} is the name of the snapshot file (you can supply as many
|
||||
files as you wish in a single command line ).
|
||||
files as you wish in a single command line).
|
||||
|
||||
To update all occurrences of the given device number in the file, use
|
||||
@option{-r} option. It takes a single argument of the form
|
||||
|
||||
752
doc/tar.texi
752
doc/tar.texi
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,9 @@
|
||||
alloca
|
||||
argmatch
|
||||
argp
|
||||
argp-version-etc
|
||||
backupfile
|
||||
canonicalize
|
||||
closeout
|
||||
configmake
|
||||
dirname
|
||||
@@ -18,22 +20,23 @@ ftruncate
|
||||
full-write
|
||||
getdate
|
||||
getline
|
||||
getopt
|
||||
getopt-gnu
|
||||
getpagesize
|
||||
gettext
|
||||
gettime
|
||||
gitlog-to-changelog
|
||||
hash
|
||||
human
|
||||
inttypes
|
||||
lchown
|
||||
localcharset
|
||||
memset
|
||||
mkdtemp
|
||||
modechange
|
||||
obstack
|
||||
priv-set
|
||||
progname
|
||||
quote
|
||||
quotearg
|
||||
rmdir
|
||||
rpmatch
|
||||
safe-read
|
||||
save-cwd
|
||||
@@ -44,17 +47,17 @@ stat-time
|
||||
stdbool
|
||||
stdint
|
||||
stpcpy
|
||||
strdup
|
||||
strdup-posix
|
||||
strerror
|
||||
strtol
|
||||
strtoul
|
||||
timespec
|
||||
unlinkdir
|
||||
unlocked-io
|
||||
utime
|
||||
utimens
|
||||
version-etc-fsf
|
||||
xalloc
|
||||
xalloc-die
|
||||
xgetcwd
|
||||
xstrtoumax
|
||||
xvasprintf
|
||||
|
||||
281
lib/.cvsignore
281
lib/.cvsignore
@@ -1,281 +0,0 @@
|
||||
.cvsignore
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
alloca.c
|
||||
alloca.h
|
||||
alloca.in.h
|
||||
argmatch.c
|
||||
argmatch.h
|
||||
argp-ba.c
|
||||
argp-eexst.c
|
||||
argp-fmtstream.c
|
||||
argp-fmtstream.h
|
||||
argp-fs-xinl.c
|
||||
argp-help.c
|
||||
argp-namefrob.h
|
||||
argp-parse.c
|
||||
argp-pin.c
|
||||
argp-pv.c
|
||||
argp-pvh.c
|
||||
argp-xinl.c
|
||||
argp.h
|
||||
asnprintf.c
|
||||
at-func.c
|
||||
backupfile.c
|
||||
backupfile.h
|
||||
basename.c
|
||||
c-ctype.c
|
||||
c-ctype.h
|
||||
canonicalize-lgpl.c
|
||||
canonicalize.h
|
||||
charset.alias
|
||||
chdir-long.c
|
||||
chdir-long.h
|
||||
chown.c
|
||||
close-stream.c
|
||||
close-stream.h
|
||||
close.c
|
||||
closeout.c
|
||||
closeout.h
|
||||
config.charset
|
||||
configmake.h
|
||||
creat-safer.c
|
||||
dirent.h
|
||||
dirent.in.h
|
||||
dirfd.c
|
||||
dirfd.h
|
||||
dirname.c
|
||||
dirname.h
|
||||
dup-safer.c
|
||||
dup2.c
|
||||
errno.in.h
|
||||
error.c
|
||||
error.h
|
||||
exclude.c
|
||||
exclude.h
|
||||
exitfail.c
|
||||
exitfail.h
|
||||
fchdir.c
|
||||
fchmodat.c
|
||||
fchown-stub.c
|
||||
fchownat.c
|
||||
fclose.c
|
||||
fcntl--.h
|
||||
fcntl-safer.h
|
||||
fcntl.h
|
||||
fcntl.in.h
|
||||
fd-safer.c
|
||||
fileblocks.c
|
||||
float+.h
|
||||
float.h
|
||||
float.in.h
|
||||
fnmatch.c
|
||||
fnmatch.h
|
||||
fnmatch.in.h
|
||||
fnmatch_loop.c
|
||||
fpending.c
|
||||
fpending.h
|
||||
fseeko.c
|
||||
fstatat.c
|
||||
ftruncate.c
|
||||
full-write.c
|
||||
full-write.h
|
||||
getcwd.c
|
||||
getdate.c
|
||||
getdate.h
|
||||
getdate.y
|
||||
getdelim.c
|
||||
getline.c
|
||||
getopt.c
|
||||
getopt.h
|
||||
getopt.in.h
|
||||
getopt1.c
|
||||
getopt_int.h
|
||||
getpagesize.c
|
||||
getpagesize.h
|
||||
gettext.h
|
||||
gettime.c
|
||||
gettimeofday.c
|
||||
gnulib.mk
|
||||
hash.c
|
||||
hash.h
|
||||
human.c
|
||||
human.h
|
||||
imaxtostr.c
|
||||
intprops.h
|
||||
inttostr.c
|
||||
inttostr.h
|
||||
inttypes.h
|
||||
inttypes.in.h
|
||||
lchown.c
|
||||
localcharset.c
|
||||
localcharset.h
|
||||
lseek.c
|
||||
lstat.c
|
||||
lstat.h
|
||||
malloc.c
|
||||
malloca.c
|
||||
malloca.h
|
||||
malloca.valgrind
|
||||
mbchar.c
|
||||
mbchar.h
|
||||
mbscasecmp.c
|
||||
mbuiter.h
|
||||
memchr.c
|
||||
mempcpy.c
|
||||
memrchr.c
|
||||
memset.c
|
||||
mkdirat.c
|
||||
mkdtemp.c
|
||||
mktime.c
|
||||
modechange.c
|
||||
modechange.h
|
||||
obstack.c
|
||||
obstack.h
|
||||
offtostr.c
|
||||
open-safer.c
|
||||
open.c
|
||||
openat-die.c
|
||||
openat-priv.h
|
||||
openat-proc.c
|
||||
openat.c
|
||||
openat.h
|
||||
pathmax.h
|
||||
paxerror.c
|
||||
paxexit.c
|
||||
paxlib.h
|
||||
paxnames.c
|
||||
pipe-safer.c
|
||||
printf-args.c
|
||||
printf-args.h
|
||||
printf-parse.c
|
||||
printf-parse.h
|
||||
quote.c
|
||||
quote.h
|
||||
quotearg.c
|
||||
quotearg.h
|
||||
rawmemchr.c
|
||||
rawmemchr.valgrind
|
||||
readlink.c
|
||||
realloc.c
|
||||
ref-add.sed
|
||||
ref-add.sin
|
||||
ref-del.sed
|
||||
ref-del.sin
|
||||
regcomp.c
|
||||
regex.c
|
||||
regex.h
|
||||
regex_internal.c
|
||||
regex_internal.h
|
||||
regexec.c
|
||||
rmdir.c
|
||||
rmt-command.h
|
||||
rmt.h
|
||||
rpmatch.c
|
||||
rtapelib.c
|
||||
safe-read.c
|
||||
safe-read.h
|
||||
safe-write.c
|
||||
safe-write.h
|
||||
same-inode.h
|
||||
save-cwd.c
|
||||
save-cwd.h
|
||||
savedir.c
|
||||
savedir.h
|
||||
setenv.c
|
||||
setenv.h
|
||||
sleep.c
|
||||
snprintf.c
|
||||
stat-macros.h
|
||||
stat-time.h
|
||||
stdarg.in.h
|
||||
stdbool.h
|
||||
stdbool.in.h
|
||||
stdint.h
|
||||
stdint.in.h
|
||||
stdio-impl.h
|
||||
stdio-write.c
|
||||
stdio.h
|
||||
stdio.in.h
|
||||
stdlib.h
|
||||
stdlib.in.h
|
||||
stpcpy.c
|
||||
strcasecmp.c
|
||||
strchrnul.c
|
||||
strchrnul.valgrind
|
||||
strdup.c
|
||||
streq.h
|
||||
strerror.c
|
||||
string.h
|
||||
string.in.h
|
||||
strings.in.h
|
||||
stripslash.c
|
||||
strncasecmp.c
|
||||
strndup.c
|
||||
strnlen.c
|
||||
strnlen1.c
|
||||
strnlen1.h
|
||||
strtoimax.c
|
||||
strtol.c
|
||||
strtoll.c
|
||||
strtoul.c
|
||||
strtoull.c
|
||||
strtoumax.c
|
||||
sys
|
||||
sys_stat.h
|
||||
sys_stat.in.h
|
||||
sys_time.h
|
||||
sys_time.in.h
|
||||
sysexits.h
|
||||
sysexits.in.h
|
||||
system-ioctl.h
|
||||
system.h
|
||||
tempname.c
|
||||
tempname.h
|
||||
time.h
|
||||
time.in.h
|
||||
time_r.c
|
||||
timespec.h
|
||||
uinttostr.c
|
||||
umaxtostr.c
|
||||
unistd--.h
|
||||
unistd-safer.h
|
||||
unistd.h
|
||||
unistd.in.h
|
||||
unitypes.h
|
||||
uniwidth
|
||||
uniwidth.h
|
||||
unlinkdir.c
|
||||
unlinkdir.h
|
||||
unlocked-io.h
|
||||
unsetenv.c
|
||||
utime.c
|
||||
utimens.c
|
||||
utimens.h
|
||||
vasnprintf.c
|
||||
vasnprintf.h
|
||||
verify.h
|
||||
version-etc-fsf.c
|
||||
version-etc.c
|
||||
version-etc.h
|
||||
vsnprintf.c
|
||||
wchar.h
|
||||
wchar.in.h
|
||||
wctype.h
|
||||
wctype.in.h
|
||||
wcwidth.c
|
||||
write.c
|
||||
xalloc-die.c
|
||||
xalloc.h
|
||||
xgetcwd.c
|
||||
xgetcwd.h
|
||||
xmalloc.c
|
||||
xsize.h
|
||||
xstrndup.c
|
||||
xstrndup.h
|
||||
xstrtol-error.c
|
||||
xstrtol.c
|
||||
xstrtol.h
|
||||
xstrtoul.c
|
||||
xstrtoumax.c
|
||||
@@ -1,7 +1,7 @@
|
||||
# Makefile for GNU tar library. -*- Makefile -*-
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
|
||||
# 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
# 2005, 2006, 2007, 2009, 2010 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
|
||||
@@ -17,19 +17,19 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
include gnulib.mk
|
||||
|
||||
noinst_LIBRARIES=libtar.a
|
||||
rmt-command.h : Makefile
|
||||
rm -f $@-t $@
|
||||
echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
|
||||
echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
|
||||
echo "#endif" >> $@-t
|
||||
mv $@-t $@
|
||||
BUILT_SOURCES += rmt-command.h
|
||||
CLEANFILES += rmt-command.h rmt-command.h-t
|
||||
$(AM_V_GEN)rm -f $@-t $@
|
||||
$(AM_V_at)echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
|
||||
$(AM_V_at)echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
|
||||
$(AM_V_at)echo "#endif" >> $@-t
|
||||
$(AM_V_at)mv $@-t $@
|
||||
BUILT_SOURCES = rmt-command.h
|
||||
CLEANFILES = rmt-command.h rmt-command.h-t
|
||||
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
|
||||
|
||||
noinst_HEADERS += system.h system-ioctl.h rmt.h paxlib.h stdopen.h
|
||||
libtar_a_SOURCES += \
|
||||
noinst_HEADERS = system.h system-ioctl.h rmt.h paxlib.h stdopen.h
|
||||
libtar_a_SOURCES = \
|
||||
paxerror.c paxexit.c paxlib.h paxnames.c \
|
||||
prepargs.c prepargs.h \
|
||||
rtapelib.c \
|
||||
@@ -37,5 +37,3 @@ libtar_a_SOURCES += \
|
||||
stdopen.c stdopen.h \
|
||||
system.h system-ioctl.h
|
||||
|
||||
libtar_a_LIBADD += $(LIBOBJS)
|
||||
libtar_a_DEPENDENCIES += $(LIBOBJS)
|
||||
|
||||
508
lib/alloca.c
508
lib/alloca.c
@@ -1,508 +0,0 @@
|
||||
/* alloca.c -- allocate automatically reclaimed memory
|
||||
(Mostly) portable public-domain implementation -- D A Gwyn
|
||||
|
||||
This implementation of the PWB library alloca function,
|
||||
which is used to allocate space off the run-time stack so
|
||||
that it is automatically reclaimed upon procedure exit,
|
||||
was inspired by discussions with J. Q. Johnson of Cornell.
|
||||
J.Otto Tennant <jot@cray.com> contributed the Cray support.
|
||||
|
||||
There are some preprocessor constants that can
|
||||
be defined when compiling for your specific system, for
|
||||
improved efficiency; however, the defaults should be okay.
|
||||
|
||||
The general concept of this implementation is to keep
|
||||
track of all alloca-allocated blocks, and reclaim any
|
||||
that are found to be deeper in the stack than the current
|
||||
invocation. This heuristic does not reclaim storage as
|
||||
soon as it becomes invalid, but it will do so eventually.
|
||||
|
||||
As a special case, alloca(0) reclaims storage without
|
||||
allocating any. It is a good idea to use alloca(0) in
|
||||
your main control loop, etc. to force garbage collection. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef emacs
|
||||
# include "lisp.h"
|
||||
# include "blockinput.h"
|
||||
# define xalloc_die() memory_full ()
|
||||
# ifdef EMACS_FREE
|
||||
# undef free
|
||||
# define free EMACS_FREE
|
||||
# endif
|
||||
#else
|
||||
# include <xalloc.h>
|
||||
#endif
|
||||
|
||||
/* If compiling with GCC 2, this file's not needed. */
|
||||
#if !defined (__GNUC__) || __GNUC__ < 2
|
||||
|
||||
/* If someone has defined alloca as a macro,
|
||||
there must be some other way alloca is supposed to work. */
|
||||
# ifndef alloca
|
||||
|
||||
# ifdef emacs
|
||||
# ifdef static
|
||||
/* actually, only want this if static is defined as ""
|
||||
-- this is for usg, in which emacs must undefine static
|
||||
in order to make unexec workable
|
||||
*/
|
||||
# ifndef STACK_DIRECTION
|
||||
you
|
||||
lose
|
||||
-- must know STACK_DIRECTION at compile-time
|
||||
/* Using #error here is not wise since this file should work for
|
||||
old and obscure compilers. */
|
||||
# endif /* STACK_DIRECTION undefined */
|
||||
# endif /* static */
|
||||
# endif /* emacs */
|
||||
|
||||
/* If your stack is a linked list of frames, you have to
|
||||
provide an "address metric" ADDRESS_FUNCTION macro. */
|
||||
|
||||
# if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
long i00afunc ();
|
||||
# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
|
||||
# else
|
||||
# define ADDRESS_FUNCTION(arg) &(arg)
|
||||
# endif
|
||||
|
||||
# ifndef POINTER_TYPE
|
||||
# ifdef __STDC__
|
||||
# define POINTER_TYPE void
|
||||
# else
|
||||
# define POINTER_TYPE char
|
||||
# endif
|
||||
# endif
|
||||
typedef POINTER_TYPE *pointer;
|
||||
|
||||
# ifndef NULL
|
||||
# define NULL 0
|
||||
# endif
|
||||
|
||||
/* Define STACK_DIRECTION if you know the direction of stack
|
||||
growth for your system; otherwise it will be automatically
|
||||
deduced at run-time.
|
||||
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
|
||||
# ifndef STACK_DIRECTION
|
||||
# define STACK_DIRECTION 0 /* Direction unknown. */
|
||||
# endif
|
||||
|
||||
# if STACK_DIRECTION != 0
|
||||
|
||||
# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
|
||||
|
||||
# else /* STACK_DIRECTION == 0; need run-time code. */
|
||||
|
||||
static int stack_dir; /* 1 or -1 once known. */
|
||||
# define STACK_DIR stack_dir
|
||||
|
||||
static void
|
||||
find_stack_direction ()
|
||||
{
|
||||
static char *addr = NULL; /* Address of first `dummy', once known. */
|
||||
auto char dummy; /* To get stack address. */
|
||||
|
||||
if (addr == NULL)
|
||||
{ /* Initial entry. */
|
||||
addr = ADDRESS_FUNCTION (dummy);
|
||||
|
||||
find_stack_direction (); /* Recurse once. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Second entry. */
|
||||
if (ADDRESS_FUNCTION (dummy) > addr)
|
||||
stack_dir = 1; /* Stack grew upward. */
|
||||
else
|
||||
stack_dir = -1; /* Stack grew downward. */
|
||||
}
|
||||
}
|
||||
|
||||
# endif /* STACK_DIRECTION == 0 */
|
||||
|
||||
/* An "alloca header" is used to:
|
||||
(a) chain together all alloca'ed blocks;
|
||||
(b) keep track of stack depth.
|
||||
|
||||
It is very important that sizeof(header) agree with malloc
|
||||
alignment chunk size. The following default should work okay. */
|
||||
|
||||
# ifndef ALIGN_SIZE
|
||||
# define ALIGN_SIZE sizeof(double)
|
||||
# endif
|
||||
|
||||
typedef union hdr
|
||||
{
|
||||
char align[ALIGN_SIZE]; /* To force sizeof(header). */
|
||||
struct
|
||||
{
|
||||
union hdr *next; /* For chaining headers. */
|
||||
char *deep; /* For stack depth measure. */
|
||||
} h;
|
||||
} header;
|
||||
|
||||
static header *last_alloca_header = NULL; /* -> last alloca header. */
|
||||
|
||||
/* Return a pointer to at least SIZE bytes of storage,
|
||||
which will be automatically reclaimed upon exit from
|
||||
the procedure that called alloca. Originally, this space
|
||||
was supposed to be taken from the current stack frame of the
|
||||
caller, but that method cannot be made to work for some
|
||||
implementations of C, for example under Gould's UTX/32. */
|
||||
|
||||
pointer
|
||||
alloca (size)
|
||||
size_t size;
|
||||
{
|
||||
auto char probe; /* Probes stack depth: */
|
||||
register char *depth = ADDRESS_FUNCTION (probe);
|
||||
|
||||
# if STACK_DIRECTION == 0
|
||||
if (STACK_DIR == 0) /* Unknown growth direction. */
|
||||
find_stack_direction ();
|
||||
# endif
|
||||
|
||||
/* Reclaim garbage, defined as all alloca'd storage that
|
||||
was allocated from deeper in the stack than currently. */
|
||||
|
||||
{
|
||||
register header *hp; /* Traverses linked list. */
|
||||
|
||||
# ifdef emacs
|
||||
BLOCK_INPUT;
|
||||
# endif
|
||||
|
||||
for (hp = last_alloca_header; hp != NULL;)
|
||||
if ((STACK_DIR > 0 && hp->h.deep > depth)
|
||||
|| (STACK_DIR < 0 && hp->h.deep < depth))
|
||||
{
|
||||
register header *np = hp->h.next;
|
||||
|
||||
free ((pointer) hp); /* Collect garbage. */
|
||||
|
||||
hp = np; /* -> next header. */
|
||||
}
|
||||
else
|
||||
break; /* Rest are not deeper. */
|
||||
|
||||
last_alloca_header = hp; /* -> last valid storage. */
|
||||
|
||||
# ifdef emacs
|
||||
UNBLOCK_INPUT;
|
||||
# endif
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
return NULL; /* No allocation required. */
|
||||
|
||||
/* Allocate combined header + user data storage. */
|
||||
|
||||
{
|
||||
/* Address of header. */
|
||||
register pointer new;
|
||||
|
||||
size_t combined_size = sizeof (header) + size;
|
||||
if (combined_size < sizeof (header))
|
||||
xalloc_die ();
|
||||
|
||||
new = xmalloc (combined_size);
|
||||
|
||||
if (new == 0)
|
||||
abort();
|
||||
|
||||
((header *) new)->h.next = last_alloca_header;
|
||||
((header *) new)->h.deep = depth;
|
||||
|
||||
last_alloca_header = (header *) new;
|
||||
|
||||
/* User storage begins just after header. */
|
||||
|
||||
return (pointer) ((char *) new + sizeof (header));
|
||||
}
|
||||
}
|
||||
|
||||
# if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
|
||||
# ifdef DEBUG_I00AFUNC
|
||||
# include <stdio.h>
|
||||
# endif
|
||||
|
||||
# ifndef CRAY_STACK
|
||||
# define CRAY_STACK
|
||||
# ifndef CRAY2
|
||||
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
|
||||
struct stack_control_header
|
||||
{
|
||||
long shgrow:32; /* Number of times stack has grown. */
|
||||
long shaseg:32; /* Size of increments to stack. */
|
||||
long shhwm:32; /* High water mark of stack. */
|
||||
long shsize:32; /* Current size of stack (all segments). */
|
||||
};
|
||||
|
||||
/* The stack segment linkage control information occurs at
|
||||
the high-address end of a stack segment. (The stack
|
||||
grows from low addresses to high addresses.) The initial
|
||||
part of the stack segment linkage control information is
|
||||
0200 (octal) words. This provides for register storage
|
||||
for the routine which overflows the stack. */
|
||||
|
||||
struct stack_segment_linkage
|
||||
{
|
||||
long ss[0200]; /* 0200 overflow words. */
|
||||
long sssize:32; /* Number of words in this segment. */
|
||||
long ssbase:32; /* Offset to stack base. */
|
||||
long:32;
|
||||
long sspseg:32; /* Offset to linkage control of previous
|
||||
segment of stack. */
|
||||
long:32;
|
||||
long sstcpt:32; /* Pointer to task common address block. */
|
||||
long sscsnm; /* Private control structure number for
|
||||
microtasking. */
|
||||
long ssusr1; /* Reserved for user. */
|
||||
long ssusr2; /* Reserved for user. */
|
||||
long sstpid; /* Process ID for pid based multi-tasking. */
|
||||
long ssgvup; /* Pointer to multitasking thread giveup. */
|
||||
long sscray[7]; /* Reserved for Cray Research. */
|
||||
long ssa0;
|
||||
long ssa1;
|
||||
long ssa2;
|
||||
long ssa3;
|
||||
long ssa4;
|
||||
long ssa5;
|
||||
long ssa6;
|
||||
long ssa7;
|
||||
long sss0;
|
||||
long sss1;
|
||||
long sss2;
|
||||
long sss3;
|
||||
long sss4;
|
||||
long sss5;
|
||||
long sss6;
|
||||
long sss7;
|
||||
};
|
||||
|
||||
# else /* CRAY2 */
|
||||
/* The following structure defines the vector of words
|
||||
returned by the STKSTAT library routine. */
|
||||
struct stk_stat
|
||||
{
|
||||
long now; /* Current total stack size. */
|
||||
long maxc; /* Amount of contiguous space which would
|
||||
be required to satisfy the maximum
|
||||
stack demand to date. */
|
||||
long high_water; /* Stack high-water mark. */
|
||||
long overflows; /* Number of stack overflow ($STKOFEN) calls. */
|
||||
long hits; /* Number of internal buffer hits. */
|
||||
long extends; /* Number of block extensions. */
|
||||
long stko_mallocs; /* Block allocations by $STKOFEN. */
|
||||
long underflows; /* Number of stack underflow calls ($STKRETN). */
|
||||
long stko_free; /* Number of deallocations by $STKRETN. */
|
||||
long stkm_free; /* Number of deallocations by $STKMRET. */
|
||||
long segments; /* Current number of stack segments. */
|
||||
long maxs; /* Maximum number of stack segments so far. */
|
||||
long pad_size; /* Stack pad size. */
|
||||
long current_address; /* Current stack segment address. */
|
||||
long current_size; /* Current stack segment size. This
|
||||
number is actually corrupted by STKSTAT to
|
||||
include the fifteen word trailer area. */
|
||||
long initial_address; /* Address of initial segment. */
|
||||
long initial_size; /* Size of initial segment. */
|
||||
};
|
||||
|
||||
/* The following structure describes the data structure which trails
|
||||
any stack segment. I think that the description in 'asdef' is
|
||||
out of date. I only describe the parts that I am sure about. */
|
||||
|
||||
struct stk_trailer
|
||||
{
|
||||
long this_address; /* Address of this block. */
|
||||
long this_size; /* Size of this block (does not include
|
||||
this trailer). */
|
||||
long unknown2;
|
||||
long unknown3;
|
||||
long link; /* Address of trailer block of previous
|
||||
segment. */
|
||||
long unknown5;
|
||||
long unknown6;
|
||||
long unknown7;
|
||||
long unknown8;
|
||||
long unknown9;
|
||||
long unknown10;
|
||||
long unknown11;
|
||||
long unknown12;
|
||||
long unknown13;
|
||||
long unknown14;
|
||||
};
|
||||
|
||||
# endif /* CRAY2 */
|
||||
# endif /* not CRAY_STACK */
|
||||
|
||||
# ifdef CRAY2
|
||||
/* Determine a "stack measure" for an arbitrary ADDRESS.
|
||||
I doubt that "lint" will like this much. */
|
||||
|
||||
static long
|
||||
i00afunc (long *address)
|
||||
{
|
||||
struct stk_stat status;
|
||||
struct stk_trailer *trailer;
|
||||
long *block, size;
|
||||
long result = 0;
|
||||
|
||||
/* We want to iterate through all of the segments. The first
|
||||
step is to get the stack status structure. We could do this
|
||||
more quickly and more directly, perhaps, by referencing the
|
||||
$LM00 common block, but I know that this works. */
|
||||
|
||||
STKSTAT (&status);
|
||||
|
||||
/* Set up the iteration. */
|
||||
|
||||
trailer = (struct stk_trailer *) (status.current_address
|
||||
+ status.current_size
|
||||
- 15);
|
||||
|
||||
/* There must be at least one stack segment. Therefore it is
|
||||
a fatal error if "trailer" is null. */
|
||||
|
||||
if (trailer == 0)
|
||||
abort ();
|
||||
|
||||
/* Discard segments that do not contain our argument address. */
|
||||
|
||||
while (trailer != 0)
|
||||
{
|
||||
block = (long *) trailer->this_address;
|
||||
size = trailer->this_size;
|
||||
if (block == 0 || size == 0)
|
||||
abort ();
|
||||
trailer = (struct stk_trailer *) trailer->link;
|
||||
if ((block <= address) && (address < (block + size)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the result to the offset in this segment and add the sizes
|
||||
of all predecessor segments. */
|
||||
|
||||
result = address - block;
|
||||
|
||||
if (trailer == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (trailer->this_size <= 0)
|
||||
abort ();
|
||||
result += trailer->this_size;
|
||||
trailer = (struct stk_trailer *) trailer->link;
|
||||
}
|
||||
while (trailer != 0);
|
||||
|
||||
/* We are done. Note that if you present a bogus address (one
|
||||
not in any segment), you will get a different number back, formed
|
||||
from subtracting the address of the first block. This is probably
|
||||
not what you want. */
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
# else /* not CRAY2 */
|
||||
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
|
||||
Determine the number of the cell within the stack,
|
||||
given the address of the cell. The purpose of this
|
||||
routine is to linearize, in some sense, stack addresses
|
||||
for alloca. */
|
||||
|
||||
static long
|
||||
i00afunc (long address)
|
||||
{
|
||||
long stkl = 0;
|
||||
|
||||
long size, pseg, this_segment, stack;
|
||||
long result = 0;
|
||||
|
||||
struct stack_segment_linkage *ssptr;
|
||||
|
||||
/* Register B67 contains the address of the end of the
|
||||
current stack segment. If you (as a subprogram) store
|
||||
your registers on the stack and find that you are past
|
||||
the contents of B67, you have overflowed the segment.
|
||||
|
||||
B67 also points to the stack segment linkage control
|
||||
area, which is what we are really interested in. */
|
||||
|
||||
stkl = CRAY_STACKSEG_END ();
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
|
||||
/* If one subtracts 'size' from the end of the segment,
|
||||
one has the address of the first word of the segment.
|
||||
|
||||
If this is not the first segment, 'pseg' will be
|
||||
nonzero. */
|
||||
|
||||
pseg = ssptr->sspseg;
|
||||
size = ssptr->sssize;
|
||||
|
||||
this_segment = stkl - size;
|
||||
|
||||
/* It is possible that calling this routine itself caused
|
||||
a stack overflow. Discard stack segments which do not
|
||||
contain the target address. */
|
||||
|
||||
while (!(this_segment <= address && address <= stkl))
|
||||
{
|
||||
# ifdef DEBUG_I00AFUNC
|
||||
fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
|
||||
# endif
|
||||
if (pseg == 0)
|
||||
break;
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
pseg = ssptr->sspseg;
|
||||
this_segment = stkl - size;
|
||||
}
|
||||
|
||||
result = address - this_segment;
|
||||
|
||||
/* If you subtract pseg from the current end of the stack,
|
||||
you get the address of the previous stack segment's end.
|
||||
This seems a little convoluted to me, but I'll bet you save
|
||||
a cycle somewhere. */
|
||||
|
||||
while (pseg != 0)
|
||||
{
|
||||
# ifdef DEBUG_I00AFUNC
|
||||
fprintf (stderr, "%011o %011o\n", pseg, size);
|
||||
# endif
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
pseg = ssptr->sspseg;
|
||||
result += size;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
# endif /* not CRAY2 */
|
||||
# endif /* CRAY */
|
||||
|
||||
# endif /* no alloca */
|
||||
#endif /* not GCC version 2 */
|
||||
280
lib/argmatch.c
280
lib/argmatch.c
@@ -1,280 +0,0 @@
|
||||
/* argmatch.c -- find a match for a string in an array
|
||||
|
||||
Copyright (C) 1990, 1998, 1999, 2001, 2002, 2003 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@ai.mit.edu>
|
||||
Modified by Akim Demaille <demaille@inf.enst.fr> */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Specification. */
|
||||
#include "argmatch.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gettext.h"
|
||||
#define _(msgid) gettext (msgid)
|
||||
|
||||
#include "error.h"
|
||||
#include "quotearg.h"
|
||||
#include "quote.h"
|
||||
#include "unlocked-io.h"
|
||||
|
||||
/* When reporting an invalid argument, show nonprinting characters
|
||||
by using the quoting style ARGMATCH_QUOTING_STYLE. Do not use
|
||||
literal_quoting_style. */
|
||||
#ifndef ARGMATCH_QUOTING_STYLE
|
||||
# define ARGMATCH_QUOTING_STYLE locale_quoting_style
|
||||
#endif
|
||||
|
||||
#ifndef EXIT_FAILURE
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
/* Non failing version of argmatch call this function after failing. */
|
||||
#ifndef ARGMATCH_DIE
|
||||
# define ARGMATCH_DIE exit (EXIT_FAILURE)
|
||||
#endif
|
||||
|
||||
#ifdef ARGMATCH_DIE_DECL
|
||||
ARGMATCH_DIE_DECL;
|
||||
#endif
|
||||
|
||||
static void
|
||||
__argmatch_die (void)
|
||||
{
|
||||
ARGMATCH_DIE;
|
||||
}
|
||||
|
||||
/* Used by XARGMATCH and XARGCASEMATCH. See description in argmatch.h.
|
||||
Default to __argmatch_die, but allow caller to change this at run-time. */
|
||||
argmatch_exit_fn argmatch_die = __argmatch_die;
|
||||
|
||||
|
||||
/* If ARG is an unambiguous match for an element of the
|
||||
null-terminated array ARGLIST, return the index in ARGLIST
|
||||
of the matched element, else -1 if it does not match any element
|
||||
or -2 if it is ambiguous (is a prefix of more than one element).
|
||||
|
||||
If VALLIST is none null, use it to resolve ambiguities limited to
|
||||
synonyms, i.e., for
|
||||
"yes", "yop" -> 0
|
||||
"no", "nope" -> 1
|
||||
"y" is a valid argument, for `0', and "n" for `1'. */
|
||||
|
||||
int
|
||||
argmatch (const char *arg, const char *const *arglist,
|
||||
const char *vallist, size_t valsize)
|
||||
{
|
||||
int i; /* Temporary index in ARGLIST. */
|
||||
size_t arglen; /* Length of ARG. */
|
||||
int matchind = -1; /* Index of first nonexact match. */
|
||||
int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
|
||||
|
||||
arglen = strlen (arg);
|
||||
|
||||
/* Test all elements for either exact match or abbreviated matches. */
|
||||
for (i = 0; arglist[i]; i++)
|
||||
{
|
||||
if (!strncmp (arglist[i], arg, arglen))
|
||||
{
|
||||
if (strlen (arglist[i]) == arglen)
|
||||
/* Exact match found. */
|
||||
return i;
|
||||
else if (matchind == -1)
|
||||
/* First nonexact match found. */
|
||||
matchind = i;
|
||||
else
|
||||
{
|
||||
/* Second nonexact match found. */
|
||||
if (vallist == NULL
|
||||
|| memcmp (vallist + valsize * matchind,
|
||||
vallist + valsize * i, valsize))
|
||||
{
|
||||
/* There is a real ambiguity, or we could not
|
||||
disambiguate. */
|
||||
ambiguous = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ambiguous)
|
||||
return -2;
|
||||
else
|
||||
return matchind;
|
||||
}
|
||||
|
||||
/* Error reporting for argmatch.
|
||||
CONTEXT is a description of the type of entity that was being matched.
|
||||
VALUE is the invalid value that was given.
|
||||
PROBLEM is the return value from argmatch. */
|
||||
|
||||
void
|
||||
argmatch_invalid (const char *context, const char *value, int problem)
|
||||
{
|
||||
char const *format = (problem == -1
|
||||
? _("invalid argument %s for %s")
|
||||
: _("ambiguous argument %s for %s"));
|
||||
|
||||
error (0, 0, format, quotearg_n_style (0, ARGMATCH_QUOTING_STYLE, value),
|
||||
quote_n (1, context));
|
||||
}
|
||||
|
||||
/* List the valid arguments for argmatch.
|
||||
ARGLIST is the same as in argmatch.
|
||||
VALLIST is a pointer to an array of values.
|
||||
VALSIZE is the size of the elements of VALLIST */
|
||||
void
|
||||
argmatch_valid (const char *const *arglist,
|
||||
const char *vallist, size_t valsize)
|
||||
{
|
||||
int i;
|
||||
const char *last_val = NULL;
|
||||
|
||||
/* We try to put synonyms on the same line. The assumption is that
|
||||
synonyms follow each other */
|
||||
fprintf (stderr, _("Valid arguments are:"));
|
||||
for (i = 0; arglist[i]; i++)
|
||||
if ((i == 0)
|
||||
|| memcmp (last_val, vallist + valsize * i, valsize))
|
||||
{
|
||||
fprintf (stderr, "\n - `%s'", arglist[i]);
|
||||
last_val = vallist + valsize * i;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, ", `%s'", arglist[i]);
|
||||
}
|
||||
putc ('\n', stderr);
|
||||
}
|
||||
|
||||
/* Never failing versions of the previous functions.
|
||||
|
||||
CONTEXT is the context for which argmatch is called (e.g.,
|
||||
"--version-control", or "$VERSION_CONTROL" etc.). Upon failure,
|
||||
calls the (supposed never to return) function EXIT_FN. */
|
||||
|
||||
int
|
||||
__xargmatch_internal (const char *context,
|
||||
const char *arg, const char *const *arglist,
|
||||
const char *vallist, size_t valsize,
|
||||
argmatch_exit_fn exit_fn)
|
||||
{
|
||||
int res = argmatch (arg, arglist, vallist, valsize);
|
||||
if (res >= 0)
|
||||
/* Success. */
|
||||
return res;
|
||||
|
||||
/* We failed. Explain why. */
|
||||
argmatch_invalid (context, arg, res);
|
||||
argmatch_valid (arglist, vallist, valsize);
|
||||
(*exit_fn) ();
|
||||
|
||||
return -1; /* To please the compilers. */
|
||||
}
|
||||
|
||||
/* Look for VALUE in VALLIST, an array of objects of size VALSIZE and
|
||||
return the first corresponding argument in ARGLIST */
|
||||
const char *
|
||||
argmatch_to_argument (const char *value,
|
||||
const char *const *arglist,
|
||||
const char *vallist, size_t valsize)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; arglist[i]; i++)
|
||||
if (!memcmp (value, vallist + valsize * i, valsize))
|
||||
return arglist[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
/*
|
||||
* Based on "getversion.c" by David MacKenzie <djm@gnu.ai.mit.edu>
|
||||
*/
|
||||
char *program_name;
|
||||
extern const char *getenv ();
|
||||
|
||||
/* When to make backup files. */
|
||||
enum backup_type
|
||||
{
|
||||
/* Never make backups. */
|
||||
none,
|
||||
|
||||
/* Make simple backups of every file. */
|
||||
simple,
|
||||
|
||||
/* Make numbered backups of files that already have numbered backups,
|
||||
and simple backups of the others. */
|
||||
numbered_existing,
|
||||
|
||||
/* Make numbered backups of every file. */
|
||||
numbered
|
||||
};
|
||||
|
||||
/* Two tables describing arguments (keys) and their corresponding
|
||||
values */
|
||||
static const char *const backup_args[] =
|
||||
{
|
||||
"no", "none", "off",
|
||||
"simple", "never",
|
||||
"existing", "nil",
|
||||
"numbered", "t",
|
||||
0
|
||||
};
|
||||
|
||||
static const enum backup_type backup_vals[] =
|
||||
{
|
||||
none, none, none,
|
||||
simple, simple,
|
||||
numbered_existing, numbered_existing,
|
||||
numbered, numbered
|
||||
};
|
||||
|
||||
int
|
||||
main (int argc, const char *const *argv)
|
||||
{
|
||||
const char *cp;
|
||||
enum backup_type backup_type = none;
|
||||
|
||||
program_name = (char *) argv[0];
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s [VERSION_CONTROL]\n", program_name);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if ((cp = getenv ("VERSION_CONTROL")))
|
||||
backup_type = XARGMATCH ("$VERSION_CONTROL", cp,
|
||||
backup_args, backup_vals);
|
||||
|
||||
if (argc == 2)
|
||||
backup_type = XARGMATCH (program_name, argv[1],
|
||||
backup_args, backup_vals);
|
||||
|
||||
printf ("The version control is `%s'\n",
|
||||
ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -1,9 +0,0 @@
|
||||
#ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
char *base_name PARAMS ((char const *name));
|
||||
407
lib/error.c
407
lib/error.c
@@ -1,407 +0,0 @@
|
||||
/* Error handler for noninteractive utilities
|
||||
Copyright (C) 1990-1998, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# include "gettext.h"
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <wchar.h>
|
||||
# define mbsrtowcs __mbsrtowcs
|
||||
#endif
|
||||
|
||||
#if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC
|
||||
# if __STDC__
|
||||
# include <stdarg.h>
|
||||
# define VA_START(args, lastarg) va_start(args, lastarg)
|
||||
# else
|
||||
# include <varargs.h>
|
||||
# define VA_START(args, lastarg) va_start(args)
|
||||
# endif
|
||||
#else
|
||||
# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
|
||||
# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
|
||||
#endif
|
||||
|
||||
#if STDC_HEADERS || _LIBC
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#else
|
||||
void exit ();
|
||||
#endif
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#if !_LIBC
|
||||
# include "unlocked-io.h"
|
||||
#endif
|
||||
|
||||
#ifndef _
|
||||
# define _(String) String
|
||||
#endif
|
||||
|
||||
/* If NULL, error will flush stdout, then print on stderr the program
|
||||
name, a colon and a space. Otherwise, error will call this
|
||||
function without parameters instead. */
|
||||
void (*error_print_progname) (
|
||||
#if __STDC__ - 0
|
||||
void
|
||||
#endif
|
||||
);
|
||||
|
||||
/* This variable is incremented each time `error' is called. */
|
||||
unsigned int error_message_count;
|
||||
|
||||
#ifdef _LIBC
|
||||
/* In the GNU C library, there is a predefined variable for this. */
|
||||
|
||||
# define program_name program_invocation_name
|
||||
# include <errno.h>
|
||||
# include <libio/libioP.h>
|
||||
|
||||
/* In GNU libc we want do not want to use the common name `error' directly.
|
||||
Instead make it a weak alias. */
|
||||
extern void __error (int status, int errnum, const char *message, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
extern void __error_at_line (int status, int errnum, const char *file_name,
|
||||
unsigned int line_number, const char *message,
|
||||
...)
|
||||
__attribute__ ((__format__ (__printf__, 5, 6)));;
|
||||
# define error __error
|
||||
# define error_at_line __error_at_line
|
||||
|
||||
# ifdef USE_IN_LIBIO
|
||||
# include <libio/iolibio.h>
|
||||
# define fflush(s) INTUSE(_IO_fflush) (s)
|
||||
# undef putc
|
||||
# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
|
||||
# endif
|
||||
|
||||
#else /* not _LIBC */
|
||||
|
||||
# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
|
||||
# ifndef HAVE_DECL_STRERROR_R
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
char *strerror_r ();
|
||||
# endif
|
||||
|
||||
/* The calling program should define program_name and set it to the
|
||||
name of the executing program. */
|
||||
extern char *program_name;
|
||||
|
||||
# if HAVE_STRERROR_R || defined strerror_r
|
||||
# define __strerror_r strerror_r
|
||||
# else
|
||||
# if HAVE_STRERROR
|
||||
# ifndef HAVE_DECL_STRERROR
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
# if !HAVE_DECL_STRERROR
|
||||
char *strerror ();
|
||||
# endif
|
||||
# else
|
||||
static char *
|
||||
private_strerror (int errnum)
|
||||
{
|
||||
extern char *sys_errlist[];
|
||||
extern int sys_nerr;
|
||||
|
||||
if (errnum > 0 && errnum <= sys_nerr)
|
||||
return _(sys_errlist[errnum]);
|
||||
return _("Unknown system error");
|
||||
}
|
||||
# define strerror private_strerror
|
||||
# endif /* HAVE_STRERROR */
|
||||
# endif /* HAVE_STRERROR_R || defined strerror_r */
|
||||
#endif /* not _LIBC */
|
||||
|
||||
static void
|
||||
print_errno_message (int errnum)
|
||||
{
|
||||
char const *s;
|
||||
|
||||
#if defined HAVE_STRERROR_R || _LIBC
|
||||
char errbuf[1024];
|
||||
# if STRERROR_R_CHAR_P || _LIBC
|
||||
s = __strerror_r (errnum, errbuf, sizeof errbuf);
|
||||
# else
|
||||
if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
|
||||
s = errbuf;
|
||||
else
|
||||
s = 0;
|
||||
# endif
|
||||
#else
|
||||
s = strerror (errnum);
|
||||
#endif
|
||||
|
||||
#if !_LIBC
|
||||
if (! s)
|
||||
s = _("Unknown system error");
|
||||
#endif
|
||||
|
||||
#if _LIBC && USE_IN_LIBIO
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
{
|
||||
__fwprintf (stderr, L": %s", s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf (stderr, ": %s", s);
|
||||
}
|
||||
|
||||
#ifdef VA_START
|
||||
static void
|
||||
error_tail (int status, int errnum, const char *message, va_list args)
|
||||
{
|
||||
# if HAVE_VPRINTF || _LIBC
|
||||
# if _LIBC && USE_IN_LIBIO
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
{
|
||||
# define ALLOCA_LIMIT 2000
|
||||
size_t len = strlen (message) + 1;
|
||||
wchar_t *wmessage = NULL;
|
||||
mbstate_t st;
|
||||
size_t res;
|
||||
const char *tmp;
|
||||
|
||||
do
|
||||
{
|
||||
if (len < ALLOCA_LIMIT)
|
||||
wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
|
||||
else
|
||||
{
|
||||
if (wmessage != NULL && len / 2 < ALLOCA_LIMIT)
|
||||
wmessage = NULL;
|
||||
|
||||
wmessage = (wchar_t *) realloc (wmessage,
|
||||
len * sizeof (wchar_t));
|
||||
|
||||
if (wmessage == NULL)
|
||||
{
|
||||
fputws_unlocked (L"out of memory\n", stderr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
memset (&st, '\0', sizeof (st));
|
||||
tmp =message;
|
||||
}
|
||||
while ((res = mbsrtowcs (wmessage, &tmp, len, &st)) == len);
|
||||
|
||||
if (res == (size_t) -1)
|
||||
/* The string cannot be converted. */
|
||||
wmessage = (wchar_t *) L"???";
|
||||
|
||||
__vfwprintf (stderr, wmessage, args);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
vfprintf (stderr, message, args);
|
||||
# else
|
||||
_doprnt (message, args, stderr);
|
||||
# endif
|
||||
va_end (args);
|
||||
|
||||
++error_message_count;
|
||||
if (errnum)
|
||||
print_errno_message (errnum);
|
||||
# if _LIBC && USE_IN_LIBIO
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
putwc (L'\n', stderr);
|
||||
else
|
||||
# endif
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
exit (status);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Print the program name and error message MESSAGE, which is a printf-style
|
||||
format string with optional args.
|
||||
If ERRNUM is nonzero, print its corresponding system error message.
|
||||
Exit with status STATUS if it is nonzero. */
|
||||
/* VARARGS */
|
||||
void
|
||||
#if defined VA_START && __STDC__
|
||||
error (int status, int errnum, const char *message, ...)
|
||||
#else
|
||||
error (status, errnum, message, va_alist)
|
||||
int status;
|
||||
int errnum;
|
||||
char *message;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
#ifdef VA_START
|
||||
va_list args;
|
||||
#endif
|
||||
|
||||
fflush (stdout);
|
||||
#ifdef _LIBC
|
||||
# ifdef USE_IN_LIBIO
|
||||
_IO_flockfile (stderr);
|
||||
# else
|
||||
__flockfile (stderr);
|
||||
# endif
|
||||
#endif
|
||||
if (error_print_progname)
|
||||
(*error_print_progname) ();
|
||||
else
|
||||
{
|
||||
#if _LIBC && USE_IN_LIBIO
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s: ", program_name);
|
||||
else
|
||||
#endif
|
||||
fprintf (stderr, "%s: ", program_name);
|
||||
}
|
||||
|
||||
#ifdef VA_START
|
||||
VA_START (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
#else
|
||||
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
|
||||
++error_message_count;
|
||||
if (errnum)
|
||||
print_errno_message (errnum);
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
exit (status);
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# ifdef USE_IN_LIBIO
|
||||
_IO_funlockfile (stderr);
|
||||
# else
|
||||
__funlockfile (stderr);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Sometimes we want to have at most one error per line. This
|
||||
variable controls whether this mode is selected or not. */
|
||||
int error_one_per_line;
|
||||
|
||||
void
|
||||
#if defined VA_START && __STDC__
|
||||
error_at_line (int status, int errnum, const char *file_name,
|
||||
unsigned int line_number, const char *message, ...)
|
||||
#else
|
||||
error_at_line (status, errnum, file_name, line_number, message, va_alist)
|
||||
int status;
|
||||
int errnum;
|
||||
const char *file_name;
|
||||
unsigned int line_number;
|
||||
char *message;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
#ifdef VA_START
|
||||
va_list args;
|
||||
#endif
|
||||
|
||||
if (error_one_per_line)
|
||||
{
|
||||
static const char *old_file_name;
|
||||
static unsigned int old_line_number;
|
||||
|
||||
if (old_line_number == line_number
|
||||
&& (file_name == old_file_name
|
||||
|| strcmp (old_file_name, file_name) == 0))
|
||||
/* Simply return and print nothing. */
|
||||
return;
|
||||
|
||||
old_file_name = file_name;
|
||||
old_line_number = line_number;
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
#ifdef _LIBC
|
||||
# ifdef USE_IN_LIBIO
|
||||
_IO_flockfile (stderr);
|
||||
# else
|
||||
__flockfile (stderr);
|
||||
# endif
|
||||
#endif
|
||||
if (error_print_progname)
|
||||
(*error_print_progname) ();
|
||||
else
|
||||
{
|
||||
#if _LIBC && USE_IN_LIBIO
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s: ", program_name);
|
||||
else
|
||||
#endif
|
||||
fprintf (stderr, "%s:", program_name);
|
||||
}
|
||||
|
||||
if (file_name != NULL)
|
||||
{
|
||||
#if _LIBC && USE_IN_LIBIO
|
||||
if (_IO_fwide (stderr, 0) > 0)
|
||||
__fwprintf (stderr, L"%s:%d: ", file_name, line_number);
|
||||
else
|
||||
#endif
|
||||
fprintf (stderr, "%s:%d: ", file_name, line_number);
|
||||
}
|
||||
|
||||
#ifdef VA_START
|
||||
VA_START (args, message);
|
||||
error_tail (status, errnum, message, args);
|
||||
#else
|
||||
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
|
||||
++error_message_count;
|
||||
if (errnum)
|
||||
print_errno_message (errnum);
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
exit (status);
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# ifdef USE_IN_LIBIO
|
||||
_IO_funlockfile (stderr);
|
||||
# else
|
||||
__funlockfile (stderr);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _LIBC
|
||||
/* Make the weak alias. */
|
||||
# undef error
|
||||
# undef error_at_line
|
||||
weak_alias (__error, error)
|
||||
weak_alias (__error_at_line, error_at_line)
|
||||
#endif
|
||||
267
lib/exclude.c
267
lib/exclude.c
@@ -1,267 +0,0 @@
|
||||
/* exclude.c -- exclude file names
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1997, 1999, 2000, 2001, 2002, 2003 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com> */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#if HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#else
|
||||
# if HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "exclude.h"
|
||||
#include "fnmatch.h"
|
||||
#include "unlocked-io.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
|
||||
/* Verify a requirement at compile-time (unlike assert, which is runtime). */
|
||||
#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
|
||||
|
||||
/* Non-GNU systems lack these options, so we don't need to check them. */
|
||||
#ifndef FNM_CASEFOLD
|
||||
# define FNM_CASEFOLD 0
|
||||
#endif
|
||||
#ifndef FNM_LEADING_DIR
|
||||
# define FNM_LEADING_DIR 0
|
||||
#endif
|
||||
|
||||
verify (EXCLUDE_macros_do_not_collide_with_FNM_macros,
|
||||
(((EXCLUDE_ANCHORED | EXCLUDE_INCLUDE | EXCLUDE_WILDCARDS)
|
||||
& (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD | FNM_LEADING_DIR
|
||||
| FNM_CASEFOLD))
|
||||
== 0));
|
||||
|
||||
/* An exclude pattern-options pair. The options are fnmatch options
|
||||
ORed with EXCLUDE_* options. */
|
||||
|
||||
struct patopts
|
||||
{
|
||||
char const *pattern;
|
||||
int options;
|
||||
};
|
||||
|
||||
/* An exclude list, of pattern-options pairs. */
|
||||
|
||||
struct exclude
|
||||
{
|
||||
struct patopts *exclude;
|
||||
size_t exclude_alloc;
|
||||
size_t exclude_count;
|
||||
};
|
||||
|
||||
/* Return a newly allocated and empty exclude list. */
|
||||
|
||||
struct exclude *
|
||||
new_exclude (void)
|
||||
{
|
||||
struct exclude *ex = xmalloc (sizeof *ex);
|
||||
ex->exclude_count = 0;
|
||||
ex->exclude_alloc = (1 << 6); /* This must be a power of 2. */
|
||||
ex->exclude = xmalloc (ex->exclude_alloc * sizeof ex->exclude[0]);
|
||||
return ex;
|
||||
}
|
||||
|
||||
/* Free the storage associated with an exclude list. */
|
||||
|
||||
void
|
||||
free_exclude (struct exclude *ex)
|
||||
{
|
||||
free (ex->exclude);
|
||||
free (ex);
|
||||
}
|
||||
|
||||
/* Return zero if PATTERN matches F, obeying OPTIONS, except that
|
||||
(unlike fnmatch) wildcards are disabled in PATTERN. */
|
||||
|
||||
static int
|
||||
fnmatch_no_wildcards (char const *pattern, char const *f, int options)
|
||||
{
|
||||
if (! (options & FNM_LEADING_DIR))
|
||||
return ((options & FNM_CASEFOLD)
|
||||
? strcasecmp (pattern, f)
|
||||
: strcmp (pattern, f));
|
||||
else
|
||||
{
|
||||
size_t patlen = strlen (pattern);
|
||||
int r = ((options & FNM_CASEFOLD)
|
||||
? strncasecmp (pattern, f, patlen)
|
||||
: strncmp (pattern, f, patlen));
|
||||
if (! r)
|
||||
{
|
||||
r = f[patlen];
|
||||
if (r == '/')
|
||||
r = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if EX excludes F. */
|
||||
|
||||
bool
|
||||
excluded_filename (struct exclude const *ex, char const *f)
|
||||
{
|
||||
size_t exclude_count = ex->exclude_count;
|
||||
|
||||
/* If no options are given, the default is to include. */
|
||||
if (exclude_count == 0)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
struct patopts const *exclude = ex->exclude;
|
||||
size_t i;
|
||||
|
||||
/* Otherwise, the default is the opposite of the first option. */
|
||||
bool excluded = !! (exclude[0].options & EXCLUDE_INCLUDE);
|
||||
|
||||
/* Scan through the options, seeing whether they change F from
|
||||
excluded to included or vice versa. */
|
||||
for (i = 0; i < exclude_count; i++)
|
||||
{
|
||||
char const *pattern = exclude[i].pattern;
|
||||
int options = exclude[i].options;
|
||||
if (excluded == !! (options & EXCLUDE_INCLUDE))
|
||||
{
|
||||
int (*matcher) (char const *, char const *, int) =
|
||||
(options & EXCLUDE_WILDCARDS
|
||||
? fnmatch
|
||||
: fnmatch_no_wildcards);
|
||||
bool matched = ((*matcher) (pattern, f, options) == 0);
|
||||
char const *p;
|
||||
|
||||
if (! (options & EXCLUDE_ANCHORED))
|
||||
for (p = f; *p && ! matched; p++)
|
||||
if (*p == '/' && p[1] != '/')
|
||||
matched = ((*matcher) (pattern, p + 1, options) == 0);
|
||||
|
||||
excluded ^= matched;
|
||||
}
|
||||
}
|
||||
|
||||
return excluded;
|
||||
}
|
||||
}
|
||||
|
||||
/* Append to EX the exclusion PATTERN with OPTIONS. */
|
||||
|
||||
void
|
||||
add_exclude (struct exclude *ex, char const *pattern, int options)
|
||||
{
|
||||
struct patopts *patopts;
|
||||
|
||||
if (ex->exclude_alloc <= ex->exclude_count)
|
||||
{
|
||||
size_t s = 2 * ex->exclude_alloc;
|
||||
if (! (0 < s && s <= SIZE_MAX / sizeof ex->exclude[0]))
|
||||
xalloc_die ();
|
||||
ex->exclude_alloc = s;
|
||||
ex->exclude = xrealloc (ex->exclude, s * sizeof ex->exclude[0]);
|
||||
}
|
||||
|
||||
patopts = &ex->exclude[ex->exclude_count++];
|
||||
patopts->pattern = pattern;
|
||||
patopts->options = options;
|
||||
}
|
||||
|
||||
/* Use ADD_FUNC to append to EX the patterns in FILENAME, each with
|
||||
OPTIONS. LINE_END terminates each pattern in the file. Return -1
|
||||
on failure, 0 on success. */
|
||||
|
||||
int
|
||||
add_exclude_file (void (*add_func) (struct exclude *, char const *, int),
|
||||
struct exclude *ex, char const *filename, int options,
|
||||
char line_end)
|
||||
{
|
||||
bool use_stdin = filename[0] == '-' && !filename[1];
|
||||
FILE *in;
|
||||
char *buf;
|
||||
char *p;
|
||||
char const *pattern;
|
||||
char const *lim;
|
||||
size_t buf_alloc = (1 << 10); /* This must be a power of two. */
|
||||
size_t buf_count = 0;
|
||||
int c;
|
||||
int e = 0;
|
||||
|
||||
if (use_stdin)
|
||||
in = stdin;
|
||||
else if (! (in = fopen (filename, "r")))
|
||||
return -1;
|
||||
|
||||
buf = xmalloc (buf_alloc);
|
||||
|
||||
while ((c = getc (in)) != EOF)
|
||||
{
|
||||
buf[buf_count++] = c;
|
||||
if (buf_count == buf_alloc)
|
||||
{
|
||||
buf_alloc *= 2;
|
||||
if (! buf_alloc)
|
||||
xalloc_die ();
|
||||
buf = xrealloc (buf, buf_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
if (ferror (in))
|
||||
e = errno;
|
||||
|
||||
if (!use_stdin && fclose (in) != 0)
|
||||
e = errno;
|
||||
|
||||
buf = xrealloc (buf, buf_count + 1);
|
||||
|
||||
for (pattern = p = buf, lim = buf + buf_count; p <= lim; p++)
|
||||
if (p < lim ? *p == line_end : buf < p && p[-1])
|
||||
{
|
||||
*p = '\0';
|
||||
(*add_func) (ex, pattern, options);
|
||||
pattern = p + 1;
|
||||
}
|
||||
|
||||
errno = e;
|
||||
return e ? -1 : 0;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/* exclude.h -- declarations for excluding file names
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1997, 1999, 2001, 2002, 2003 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com> */
|
||||
|
||||
/* Exclude options, which can be ORed with fnmatch options. */
|
||||
|
||||
/* Patterns must match the start of file names, instead of matching
|
||||
anywhere after a '/'. */
|
||||
#define EXCLUDE_ANCHORED (1 << 30)
|
||||
|
||||
/* Include instead of exclude. */
|
||||
#define EXCLUDE_INCLUDE (1 << 29)
|
||||
|
||||
/* '?', '*', '[', and '\\' are special in patterns. Without this
|
||||
option, these characters are ordinary and fnmatch is not used. */
|
||||
#define EXCLUDE_WILDCARDS (1 << 28)
|
||||
|
||||
struct exclude;
|
||||
|
||||
struct exclude *new_exclude (void);
|
||||
void free_exclude (struct exclude *);
|
||||
void add_exclude (struct exclude *, char const *, int);
|
||||
int add_exclude_file (void (*) (struct exclude *, char const *, int),
|
||||
struct exclude *, char const *, int, char);
|
||||
bool excluded_filename (struct exclude const *, char const *);
|
||||
385
lib/fnmatch.c
385
lib/fnmatch.c
@@ -1,385 +0,0 @@
|
||||
/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Enable GNU extensions in fnmatch.h. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
# define HAVE_ALLOCA 1
|
||||
#else
|
||||
# if defined HAVE_ALLOCA_H || defined _LIBC
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
# pragma alloca
|
||||
# else
|
||||
# ifndef alloca
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ! defined __builtin_expect && __GNUC__ < 3
|
||||
# define __builtin_expect(expr, expected) (expr)
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if HAVE_STRING_H || defined _LIBC
|
||||
# include <string.h>
|
||||
#else
|
||||
# if HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined STDC_HEADERS || defined _LIBC
|
||||
# include <stddef.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define WIDE_CHAR_SUPPORT (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC)
|
||||
|
||||
/* For platform which support the ISO C amendement 1 functionality we
|
||||
support user defined character classes. */
|
||||
#if defined _LIBC || WIDE_CHAR_SUPPORT
|
||||
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
|
||||
# include <wchar.h>
|
||||
# include <wctype.h>
|
||||
#endif
|
||||
|
||||
/* We need some of the locale data (the collation sequence information)
|
||||
but there is no interface to get this information in general. Therefore
|
||||
we support a correct implementation only in glibc. */
|
||||
#ifdef _LIBC
|
||||
# include "../locale/localeinfo.h"
|
||||
# include "../locale/elem-hash.h"
|
||||
# include "../locale/coll-lookup.h"
|
||||
# include <shlib-compat.h>
|
||||
|
||||
# define CONCAT(a,b) __CONCAT(a,b)
|
||||
# define mbsinit __mbsinit
|
||||
# define mbsrtowcs __mbsrtowcs
|
||||
# define fnmatch __fnmatch
|
||||
extern int fnmatch (const char *pattern, const char *string, int flags);
|
||||
#endif
|
||||
|
||||
/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */
|
||||
#define NO_LEADING_PERIOD(flags) \
|
||||
((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, are not
|
||||
actually compiling the library itself, and have not detected a bug
|
||||
in the library. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU
|
||||
|
||||
|
||||
# if defined STDC_HEADERS || !defined isascii
|
||||
# define ISASCII(c) 1
|
||||
# else
|
||||
# define ISASCII(c) isascii(c)
|
||||
# endif
|
||||
|
||||
# ifdef isblank
|
||||
# define ISBLANK(c) (ISASCII (c) && isblank (c))
|
||||
# else
|
||||
# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
|
||||
# endif
|
||||
# ifdef isgraph
|
||||
# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
|
||||
# else
|
||||
# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
|
||||
# endif
|
||||
|
||||
# define ISPRINT(c) (ISASCII (c) && isprint (c))
|
||||
# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
|
||||
# define ISALNUM(c) (ISASCII (c) && isalnum (c))
|
||||
# define ISALPHA(c) (ISASCII (c) && isalpha (c))
|
||||
# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
|
||||
# define ISLOWER(c) (ISASCII (c) && islower (c))
|
||||
# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
|
||||
# define ISSPACE(c) (ISASCII (c) && isspace (c))
|
||||
# define ISUPPER(c) (ISASCII (c) && isupper (c))
|
||||
# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
|
||||
|
||||
# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
|
||||
|
||||
# if defined _LIBC || WIDE_CHAR_SUPPORT
|
||||
/* The GNU C library provides support for user-defined character classes
|
||||
and the functions from ISO C amendement 1. */
|
||||
# ifdef CHARCLASS_NAME_MAX
|
||||
# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
|
||||
# else
|
||||
/* This shouldn't happen but some implementation might still have this
|
||||
problem. Use a reasonable default value. */
|
||||
# define CHAR_CLASS_MAX_LENGTH 256
|
||||
# endif
|
||||
|
||||
# ifdef _LIBC
|
||||
# define IS_CHAR_CLASS(string) __wctype (string)
|
||||
# else
|
||||
# define IS_CHAR_CLASS(string) wctype (string)
|
||||
# endif
|
||||
|
||||
# ifdef _LIBC
|
||||
# define ISWCTYPE(WC, WT) __iswctype (WC, WT)
|
||||
# else
|
||||
# define ISWCTYPE(WC, WT) iswctype (WC, WT)
|
||||
# endif
|
||||
|
||||
# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
|
||||
/* In this case we are implementing the multibyte character handling. */
|
||||
# define HANDLE_MULTIBYTE 1
|
||||
# endif
|
||||
|
||||
# else
|
||||
# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
|
||||
|
||||
# define IS_CHAR_CLASS(string) \
|
||||
(STREQ (string, "alpha") || STREQ (string, "upper") \
|
||||
|| STREQ (string, "lower") || STREQ (string, "digit") \
|
||||
|| STREQ (string, "alnum") || STREQ (string, "xdigit") \
|
||||
|| STREQ (string, "space") || STREQ (string, "print") \
|
||||
|| STREQ (string, "punct") || STREQ (string, "graph") \
|
||||
|| STREQ (string, "cntrl") || STREQ (string, "blank"))
|
||||
# endif
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
# if !defined _LIBC && !defined getenv && !HAVE_DECL_GETENV
|
||||
extern char *getenv ();
|
||||
# endif
|
||||
|
||||
# ifndef errno
|
||||
extern int errno;
|
||||
# endif
|
||||
|
||||
/* Global variable. */
|
||||
static int posixly_correct;
|
||||
|
||||
# ifndef internal_function
|
||||
/* Inside GNU libc we mark some function in a special way. In other
|
||||
environments simply ignore the marking. */
|
||||
# define internal_function
|
||||
# endif
|
||||
|
||||
/* Note that this evaluates C many times. */
|
||||
# ifdef _LIBC
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
|
||||
# else
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
|
||||
# endif
|
||||
# define CHAR char
|
||||
# define UCHAR unsigned char
|
||||
# define INT int
|
||||
# define FCT internal_fnmatch
|
||||
# define EXT ext_match
|
||||
# define END end_pattern
|
||||
# define L(CS) CS
|
||||
# ifdef _LIBC
|
||||
# define BTOWC(C) __btowc (C)
|
||||
# else
|
||||
# define BTOWC(C) btowc (C)
|
||||
# endif
|
||||
# define STRLEN(S) strlen (S)
|
||||
# define STRCAT(D, S) strcat (D, S)
|
||||
# ifdef _LIBC
|
||||
# define MEMPCPY(D, S, N) __mempcpy (D, S, N)
|
||||
# else
|
||||
# if HAVE_MEMPCPY
|
||||
# define MEMPCPY(D, S, N) mempcpy (D, S, N)
|
||||
# else
|
||||
# define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
|
||||
# endif
|
||||
# endif
|
||||
# define MEMCHR(S, C, N) memchr (S, C, N)
|
||||
# define STRCOLL(S1, S2) strcoll (S1, S2)
|
||||
# include "fnmatch_loop.c"
|
||||
|
||||
|
||||
# if HANDLE_MULTIBYTE
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
|
||||
# define CHAR wchar_t
|
||||
# define UCHAR wint_t
|
||||
# define INT wint_t
|
||||
# define FCT internal_fnwmatch
|
||||
# define EXT ext_wmatch
|
||||
# define END end_wpattern
|
||||
# define L(CS) L##CS
|
||||
# define BTOWC(C) (C)
|
||||
# ifdef _LIBC
|
||||
# define STRLEN(S) __wcslen (S)
|
||||
# define STRCAT(D, S) __wcscat (D, S)
|
||||
# define MEMPCPY(D, S, N) __wmempcpy (D, S, N)
|
||||
# else
|
||||
# define STRLEN(S) wcslen (S)
|
||||
# define STRCAT(D, S) wcscat (D, S)
|
||||
# if HAVE_WMEMPCPY
|
||||
# define MEMPCPY(D, S, N) wmempcpy (D, S, N)
|
||||
# else
|
||||
# define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N))
|
||||
# endif
|
||||
# endif
|
||||
# define MEMCHR(S, C, N) wmemchr (S, C, N)
|
||||
# define STRCOLL(S1, S2) wcscoll (S1, S2)
|
||||
# define WIDE_CHAR_VERSION 1
|
||||
|
||||
# undef IS_CHAR_CLASS
|
||||
/* We have to convert the wide character string in a multibyte string. But
|
||||
we know that the character class names consist of alphanumeric characters
|
||||
from the portable character set, and since the wide character encoding
|
||||
for a member of the portable character set is the same code point as
|
||||
its single-byte encoding, we can use a simplified method to convert the
|
||||
string to a multibyte character string. */
|
||||
static wctype_t
|
||||
is_char_class (const wchar_t *wcs)
|
||||
{
|
||||
char s[CHAR_CLASS_MAX_LENGTH + 1];
|
||||
char *cp = s;
|
||||
|
||||
do
|
||||
{
|
||||
/* Test for a printable character from the portable character set. */
|
||||
# ifdef _LIBC
|
||||
if (*wcs < 0x20 || *wcs > 0x7e
|
||||
|| *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
|
||||
return (wctype_t) 0;
|
||||
# else
|
||||
switch (*wcs)
|
||||
{
|
||||
case L' ': case L'!': case L'"': case L'#': case L'%':
|
||||
case L'&': case L'\'': case L'(': case L')': case L'*':
|
||||
case L'+': case L',': case L'-': case L'.': case L'/':
|
||||
case L'0': case L'1': case L'2': case L'3': case L'4':
|
||||
case L'5': case L'6': case L'7': case L'8': case L'9':
|
||||
case L':': case L';': case L'<': case L'=': case L'>':
|
||||
case L'?':
|
||||
case L'A': case L'B': case L'C': case L'D': case L'E':
|
||||
case L'F': case L'G': case L'H': case L'I': case L'J':
|
||||
case L'K': case L'L': case L'M': case L'N': case L'O':
|
||||
case L'P': case L'Q': case L'R': case L'S': case L'T':
|
||||
case L'U': case L'V': case L'W': case L'X': case L'Y':
|
||||
case L'Z':
|
||||
case L'[': case L'\\': case L']': case L'^': case L'_':
|
||||
case L'a': case L'b': case L'c': case L'd': case L'e':
|
||||
case L'f': case L'g': case L'h': case L'i': case L'j':
|
||||
case L'k': case L'l': case L'm': case L'n': case L'o':
|
||||
case L'p': case L'q': case L'r': case L's': case L't':
|
||||
case L'u': case L'v': case L'w': case L'x': case L'y':
|
||||
case L'z': case L'{': case L'|': case L'}': case L'~':
|
||||
break;
|
||||
default:
|
||||
return (wctype_t) 0;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Avoid overrunning the buffer. */
|
||||
if (cp == s + CHAR_CLASS_MAX_LENGTH)
|
||||
return (wctype_t) 0;
|
||||
|
||||
*cp++ = (char) *wcs++;
|
||||
}
|
||||
while (*wcs != L'\0');
|
||||
|
||||
*cp = '\0';
|
||||
|
||||
# ifdef _LIBC
|
||||
return __wctype (s);
|
||||
# else
|
||||
return wctype (s);
|
||||
# endif
|
||||
}
|
||||
# define IS_CHAR_CLASS(string) is_char_class (string)
|
||||
|
||||
# include "fnmatch_loop.c"
|
||||
# endif
|
||||
|
||||
|
||||
int
|
||||
fnmatch (pattern, string, flags)
|
||||
const char *pattern;
|
||||
const char *string;
|
||||
int flags;
|
||||
{
|
||||
# if HANDLE_MULTIBYTE
|
||||
if (__builtin_expect (MB_CUR_MAX, 1) != 1)
|
||||
{
|
||||
mbstate_t ps;
|
||||
size_t n;
|
||||
wchar_t *wpattern;
|
||||
wchar_t *wstring;
|
||||
|
||||
/* Convert the strings into wide characters. */
|
||||
memset (&ps, '\0', sizeof (ps));
|
||||
n = mbsrtowcs (NULL, &pattern, 0, &ps);
|
||||
if (__builtin_expect (n, 0) == (size_t) -1)
|
||||
/* Something wrong.
|
||||
XXX Do we have to set `errno' to something which mbsrtows hasn't
|
||||
already done? */
|
||||
return -1;
|
||||
wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
|
||||
assert (mbsinit (&ps));
|
||||
(void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
|
||||
|
||||
assert (mbsinit (&ps));
|
||||
n = mbsrtowcs (NULL, &string, 0, &ps);
|
||||
if (__builtin_expect (n, 0) == (size_t) -1)
|
||||
/* Something wrong.
|
||||
XXX Do we have to set `errno' to something which mbsrtows hasn't
|
||||
already done? */
|
||||
return -1;
|
||||
wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
|
||||
assert (mbsinit (&ps));
|
||||
(void) mbsrtowcs (wstring, &string, n + 1, &ps);
|
||||
|
||||
return internal_fnwmatch (wpattern, wstring, wstring + n,
|
||||
flags & FNM_PERIOD, flags);
|
||||
}
|
||||
# endif /* mbstate_t and mbsrtowcs or _LIBC. */
|
||||
|
||||
return internal_fnmatch (pattern, string, string + strlen (string),
|
||||
flags & FNM_PERIOD, flags);
|
||||
}
|
||||
|
||||
# ifdef _LIBC
|
||||
# undef fnmatch
|
||||
versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
|
||||
# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
|
||||
strong_alias (__fnmatch, __fnmatch_old)
|
||||
compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
@@ -1,84 +0,0 @@
|
||||
/* Copyright (C) 1991, 92, 93, 96, 97, 98 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _FNMATCH_H
|
||||
#define _FNMATCH_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
|
||||
# if !defined __GLIBC__ || !defined __P
|
||||
# undef __P
|
||||
# define __P(protos) protos
|
||||
# endif
|
||||
#else /* Not C++ or ANSI C. */
|
||||
# undef __P
|
||||
# define __P(protos) ()
|
||||
/* We can get away without defining `const' here only because in this file
|
||||
it is used only inside the prototype for `fnmatch', which is elided in
|
||||
non-ANSI C where `const' is problematical. */
|
||||
#endif /* C++ or ANSI C. */
|
||||
|
||||
#ifndef const
|
||||
# if (defined __STDC__ && __STDC__) || defined __cplusplus
|
||||
# define __const const
|
||||
# else
|
||||
# define __const
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* We #undef these before defining them because some losing systems
|
||||
(HP-UX A.08.07 for example) define these in <unistd.h>. */
|
||||
#undef FNM_PATHNAME
|
||||
#undef FNM_NOESCAPE
|
||||
#undef FNM_PERIOD
|
||||
|
||||
/* Bits set in the FLAGS argument to `fnmatch'. */
|
||||
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
|
||||
#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
|
||||
#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
|
||||
|
||||
#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
|
||||
# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
|
||||
# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
|
||||
# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
#endif
|
||||
|
||||
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
|
||||
#define FNM_NOMATCH 1
|
||||
|
||||
/* This value is returned if the implementation does not support
|
||||
`fnmatch'. Since this is not the case here it will never be
|
||||
returned but the conformance test suites still require the symbol
|
||||
to be defined. */
|
||||
#ifdef _XOPEN_SOURCE
|
||||
# define FNM_NOSYS (-1)
|
||||
#endif
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN,
|
||||
returning zero if it matches, FNM_NOMATCH if not. */
|
||||
extern int fnmatch __P ((__const char *__pattern, __const char *__string,
|
||||
int __flags));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* fnmatch.h */
|
||||
@@ -1,474 +0,0 @@
|
||||
/* Copyright (C) 1991-1993, 1996-1999, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN, returning zero if
|
||||
it matches, nonzero if not. */
|
||||
static int FCT (const CHAR *pattern, const CHAR *string,
|
||||
int no_leading_period, int flags) internal_function;
|
||||
|
||||
static int
|
||||
internal_function
|
||||
FCT (pattern, string, no_leading_period, flags)
|
||||
const CHAR *pattern;
|
||||
const CHAR *string;
|
||||
int no_leading_period;
|
||||
int flags;
|
||||
{
|
||||
register const CHAR *p = pattern, *n = string;
|
||||
register UCHAR c;
|
||||
#ifdef _LIBC
|
||||
const UCHAR *collseq = (const UCHAR *)
|
||||
_NL_CURRENT(LC_COLLATE, CONCAT(_NL_COLLATE_COLLSEQ,SUFFIX));
|
||||
# ifdef WIDE_CHAR_VERSION
|
||||
const wint_t *names = (const wint_t *)
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_NAMES);
|
||||
size_t size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_HASH_SIZE);
|
||||
size_t layers = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_HASH_LAYERS);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
while ((c = *p++) != L('\0'))
|
||||
{
|
||||
c = FOLD (c);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case L('?'):
|
||||
if (*n == L('\0'))
|
||||
return FNM_NOMATCH;
|
||||
else if (*n == L('/') && (flags & FNM_FILE_NAME))
|
||||
return FNM_NOMATCH;
|
||||
else if (*n == L('.') && no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == L('/') && (flags & FNM_FILE_NAME))))
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case L('\\'):
|
||||
if (!(flags & FNM_NOESCAPE))
|
||||
{
|
||||
c = *p++;
|
||||
if (c == L('\0'))
|
||||
/* Trailing \ loses. */
|
||||
return FNM_NOMATCH;
|
||||
c = FOLD (c);
|
||||
}
|
||||
if (FOLD ((UCHAR) *n) != c)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case L('*'):
|
||||
if (*n == L('.') && no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == L('/') && (flags & FNM_FILE_NAME))))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
for (c = *p++; c == L('?') || c == L('*'); c = *p++)
|
||||
{
|
||||
if (*n == L('/') && (flags & FNM_FILE_NAME))
|
||||
/* A slash does not match a wildcard under FNM_FILE_NAME. */
|
||||
return FNM_NOMATCH;
|
||||
else if (c == L('?'))
|
||||
{
|
||||
/* A ? needs to match one character. */
|
||||
if (*n == L('\0'))
|
||||
/* There isn't another character; no match. */
|
||||
return FNM_NOMATCH;
|
||||
else
|
||||
/* One character of the string is consumed in matching
|
||||
this ? wildcard, so *??? won't match if there are
|
||||
less than three characters. */
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == L('\0'))
|
||||
/* The wildcard(s) is/are the last element of the pattern.
|
||||
If the name is a file name and contains another slash
|
||||
this does mean it cannot match. If the FNM_LEADING_DIR
|
||||
flag is set and exactly one slash is following, we have
|
||||
a match. */
|
||||
{
|
||||
int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
|
||||
|
||||
if (flags & FNM_FILE_NAME)
|
||||
{
|
||||
const CHAR *slashp = STRCHR (n, L('/'));
|
||||
|
||||
if (flags & FNM_LEADING_DIR)
|
||||
{
|
||||
if (slashp != NULL
|
||||
&& STRCHR (slashp + 1, L('/')) == NULL)
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (slashp == NULL)
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
const CHAR *endp;
|
||||
|
||||
endp = STRCHRNUL (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'));
|
||||
|
||||
if (c == L('['))
|
||||
{
|
||||
int flags2 = ((flags & FNM_FILE_NAME)
|
||||
? flags : (flags & ~FNM_PERIOD));
|
||||
|
||||
for (--p; n < endp; ++n)
|
||||
if (FCT (p, n, (no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == L('/')
|
||||
&& (flags & FNM_FILE_NAME)))),
|
||||
flags2) == 0)
|
||||
return 0;
|
||||
}
|
||||
else if (c == L('/') && (flags & FNM_FILE_NAME))
|
||||
{
|
||||
while (*n != L('\0') && *n != L('/'))
|
||||
++n;
|
||||
if (*n == L('/')
|
||||
&& (FCT (p, n + 1, flags & FNM_PERIOD, flags) == 0))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int flags2 = ((flags & FNM_FILE_NAME)
|
||||
? flags : (flags & ~FNM_PERIOD));
|
||||
|
||||
if (c == L('\\') && !(flags & FNM_NOESCAPE))
|
||||
c = *p;
|
||||
c = FOLD (c);
|
||||
for (--p; n < endp; ++n)
|
||||
if (FOLD ((UCHAR) *n) == c
|
||||
&& (FCT (p, n, (no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == L('/')
|
||||
&& (flags & FNM_FILE_NAME)))),
|
||||
flags2) == 0))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we come here no match is possible with the wildcard. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
case L('['):
|
||||
{
|
||||
/* Nonzero if the sense of the character class is inverted. */
|
||||
static int posixly_correct;
|
||||
register int not;
|
||||
CHAR cold;
|
||||
|
||||
if (posixly_correct == 0)
|
||||
posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
|
||||
|
||||
if (*n == L('\0'))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (*n == L('.') && no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == L('/') && (flags & FNM_FILE_NAME))))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (*n == L('/') && (flags & FNM_FILE_NAME))
|
||||
/* `/' cannot be matched. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
not = (*p == L('!') || (posixly_correct < 0 && *p == L('^')));
|
||||
if (not)
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for (;;)
|
||||
{
|
||||
UCHAR fn = FOLD ((UCHAR) *n);
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == L('\\'))
|
||||
{
|
||||
if (*p == L('\0'))
|
||||
return FNM_NOMATCH;
|
||||
c = FOLD ((UCHAR) *p);
|
||||
++p;
|
||||
|
||||
if (c == fn)
|
||||
goto matched;
|
||||
}
|
||||
else if (c == L('[') && *p == L(':'))
|
||||
{
|
||||
/* Leave room for the null. */
|
||||
CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
|
||||
size_t c1 = 0;
|
||||
#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
|
||||
wctype_t wt;
|
||||
#endif
|
||||
const CHAR *startp = p;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (c1 == CHAR_CLASS_MAX_LENGTH)
|
||||
/* The name is too long and therefore the pattern
|
||||
is ill-formed. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
c = *++p;
|
||||
if (c == L(':') && p[1] == L(']'))
|
||||
{
|
||||
p += 2;
|
||||
break;
|
||||
}
|
||||
if (c < L('a') || c >= L('z'))
|
||||
{
|
||||
/* This cannot possibly be a character class name.
|
||||
Match it as a normal range. */
|
||||
p = startp;
|
||||
c = L('[');
|
||||
goto normal_bracket;
|
||||
}
|
||||
str[c1++] = c;
|
||||
}
|
||||
str[c1] = L('\0');
|
||||
|
||||
#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
|
||||
wt = IS_CHAR_CLASS (str);
|
||||
if (wt == 0)
|
||||
/* Invalid character class name. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (ISWCTYPE (BTOWC ((UCHAR) *n), wt))
|
||||
goto matched;
|
||||
#else
|
||||
if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n))
|
||||
|| (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n))
|
||||
|| (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n))
|
||||
|| (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n))
|
||||
|| (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n))
|
||||
|| (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n))
|
||||
|| (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n))
|
||||
|| (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n))
|
||||
|| (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n))
|
||||
|| (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n))
|
||||
|| (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n))
|
||||
|| (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n)))
|
||||
goto matched;
|
||||
#endif
|
||||
}
|
||||
else if (c == L('\0'))
|
||||
/* [ (unterminated) loses. */
|
||||
return FNM_NOMATCH;
|
||||
else
|
||||
{
|
||||
c = FOLD (c);
|
||||
normal_bracket:
|
||||
if (c == fn)
|
||||
goto matched;
|
||||
|
||||
cold = c;
|
||||
c = *p++;
|
||||
|
||||
if (c == L('-') && *p != L(']'))
|
||||
{
|
||||
#if _LIBC
|
||||
/* We have to find the collation sequence
|
||||
value for C. Collation sequence is nothing
|
||||
we can regularly access. The sequence
|
||||
value is defined by the order in which the
|
||||
definitions of the collation values for the
|
||||
various characters appear in the source
|
||||
file. A strange concept, nowhere
|
||||
documented. */
|
||||
int32_t fseqidx;
|
||||
int32_t lseqidx;
|
||||
UCHAR cend = *p++;
|
||||
# ifdef WIDE_CHAR_VERSION
|
||||
size_t cnt;
|
||||
# endif
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
|
||||
cend = *p++;
|
||||
if (cend == L('\0'))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
# ifdef WIDE_CHAR_VERSION
|
||||
/* Search in the `names' array for the characters. */
|
||||
fseqidx = fn % size;
|
||||
cnt = 0;
|
||||
while (names[fseqidx] != fn)
|
||||
{
|
||||
if (++cnt == layers)
|
||||
/* XXX We don't know anything about
|
||||
the character we are supposed to
|
||||
match. This means we are failing. */
|
||||
goto range_not_matched;
|
||||
|
||||
fseqidx += size;
|
||||
}
|
||||
lseqidx = cold % size;
|
||||
cnt = 0;
|
||||
while (names[lseqidx] != cold)
|
||||
{
|
||||
if (++cnt == layers)
|
||||
{
|
||||
lseqidx = -1;
|
||||
break;
|
||||
}
|
||||
lseqidx += size;
|
||||
}
|
||||
# else
|
||||
fseqidx = fn;
|
||||
lseqidx = cold;
|
||||
# endif
|
||||
|
||||
/* XXX It is not entirely clear to me how to handle
|
||||
characters which are not mentioned in the
|
||||
collation specification. */
|
||||
if (
|
||||
# ifdef WIDE_CHAR_VERSION
|
||||
lseqidx == -1 ||
|
||||
# endif
|
||||
collseq[lseqidx] <= collseq[fseqidx])
|
||||
{
|
||||
/* We have to look at the upper bound. */
|
||||
int32_t hseqidx;
|
||||
|
||||
cend = FOLD (cend);
|
||||
# ifdef WIDE_CHAR_VERSION
|
||||
hseqidx = cend % size;
|
||||
cnt = 0;
|
||||
while (names[hseqidx] != cend)
|
||||
{
|
||||
if (++cnt == layers)
|
||||
{
|
||||
/* Hum, no information about the upper
|
||||
bound. The matching succeeds if the
|
||||
lower bound is matched exactly. */
|
||||
if (lseqidx == -1 || cold != fn)
|
||||
goto range_not_matched;
|
||||
|
||||
goto matched;
|
||||
}
|
||||
}
|
||||
# else
|
||||
hseqidx = cend;
|
||||
# endif
|
||||
|
||||
if (
|
||||
# ifdef WIDE_CHAR_VERSION
|
||||
(lseqidx == -1
|
||||
&& collseq[fseqidx] == collseq[hseqidx]) ||
|
||||
# endif
|
||||
collseq[fseqidx] <= collseq[hseqidx])
|
||||
goto matched;
|
||||
}
|
||||
# ifdef WIDE_CHAR_VERSION
|
||||
range_not_matched:
|
||||
# endif
|
||||
#else
|
||||
/* We use a boring value comparison of the character
|
||||
values. This is better than comparing using
|
||||
`strcoll' since the latter would have surprising
|
||||
and sometimes fatal consequences. */
|
||||
UCHAR cend = *p++;
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
|
||||
cend = *p++;
|
||||
if (cend == L('\0'))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
/* It is a range. */
|
||||
if (cold <= fc && fc <= c)
|
||||
goto matched;
|
||||
#endif
|
||||
|
||||
c = *p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == L(']'))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!not)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
matched:
|
||||
/* Skip the rest of the [...] that already matched. */
|
||||
while (c != L(']'))
|
||||
{
|
||||
if (c == L('\0'))
|
||||
/* [... (unterminated) loses. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
c = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && c == L('\\'))
|
||||
{
|
||||
if (*p == L('\0'))
|
||||
return FNM_NOMATCH;
|
||||
/* XXX 1003.2d11 is unclear if this is right. */
|
||||
++p;
|
||||
}
|
||||
else if (c == L('[') && *p == L(':'))
|
||||
{
|
||||
do
|
||||
if (*++p == L('\0'))
|
||||
return FNM_NOMATCH;
|
||||
while (*p != L(':') || p[1] == L(']'));
|
||||
p += 2;
|
||||
c = *p;
|
||||
}
|
||||
}
|
||||
if (not)
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (c != FOLD ((UCHAR) *n))
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
if (*n == '\0')
|
||||
return 0;
|
||||
|
||||
if ((flags & FNM_LEADING_DIR) && *n == L('/'))
|
||||
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
|
||||
return 0;
|
||||
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
#undef FOLD
|
||||
#undef CHAR
|
||||
#undef UCHAR
|
||||
#undef FCT
|
||||
#undef STRCHR
|
||||
#undef STRCHRNUL
|
||||
#undef STRCOLL
|
||||
#undef L
|
||||
#undef BTOWC
|
||||
#undef SUFFIX
|
||||
@@ -1,50 +0,0 @@
|
||||
/* full-read.c -- an interface to read that retries after interrupts
|
||||
Copyright (C) 1993, 1994, 1997, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
|
||||
Return the actual number of bytes read, zero for EOF, or negative
|
||||
for an error. */
|
||||
|
||||
ssize_t
|
||||
full_read (int desc, char *ptr, size_t len)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
ssize_t n = read (desc, ptr, len);
|
||||
#ifdef EINTR
|
||||
if (n < 0 && errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
return n;
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/* An interface to read and write that retries (if necessary) until complete.
|
||||
|
||||
Copyright (C) 1993, 1994, 1997-2003 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Specification. */
|
||||
#ifdef FULL_READ
|
||||
# include "full-read.h"
|
||||
#else
|
||||
# include "full-write.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#ifdef FULL_READ
|
||||
# include "safe-read.h"
|
||||
# define safe_rw safe_read
|
||||
# define full_rw full_read
|
||||
# undef const
|
||||
# define const /* empty */
|
||||
#else
|
||||
# include "safe-write.h"
|
||||
# define safe_rw safe_write
|
||||
# define full_rw full_write
|
||||
#endif
|
||||
|
||||
#ifdef FULL_READ
|
||||
/* Set errno to zero upon EOF. */
|
||||
# define ZERO_BYTE_TRANSFER_ERRNO 0
|
||||
#else
|
||||
/* Some buggy drivers return 0 when one tries to write beyond
|
||||
a device's end. (Example: Linux 1.2.13 on /dev/fd0.)
|
||||
Set errno to ENOSPC so they get a sensible diagnostic. */
|
||||
# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC
|
||||
#endif
|
||||
|
||||
/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if
|
||||
interrupted or if a partial write(read) occurs. Return the number
|
||||
of bytes transferred.
|
||||
When writing, set errno if fewer than COUNT bytes are written.
|
||||
When reading, if fewer than COUNT bytes are read, you must examine
|
||||
errno to distinguish failure from EOF (errno == 0). */
|
||||
size_t
|
||||
full_rw (int fd, const void *buf, size_t count)
|
||||
{
|
||||
size_t total = 0;
|
||||
const char *ptr = buf;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
size_t n_rw = safe_rw (fd, ptr, count);
|
||||
if (n_rw == (size_t) -1)
|
||||
break;
|
||||
if (n_rw == 0)
|
||||
{
|
||||
errno = ZERO_BYTE_TRANSFER_ERRNO;
|
||||
break;
|
||||
}
|
||||
total += n_rw;
|
||||
ptr += n_rw;
|
||||
count -= n_rw;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/* An interface to write() that writes all it is asked to write.
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted
|
||||
or if partial writes occur. Return the number of bytes successfully
|
||||
written, setting errno if that is less than COUNT. */
|
||||
extern size_t full_write (int fd, const void *buf, size_t count);
|
||||
1114
lib/getdate.y
1114
lib/getdate.y
File diff suppressed because it is too large
Load Diff
366
lib/human.c
366
lib/human.c
@@ -1,366 +0,0 @@
|
||||
/* human.c -- print human readable file size
|
||||
|
||||
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Originally contributed by lm@sgi.com;
|
||||
--si, output block size selection, and large file support
|
||||
added by eggert@twinsun.com. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DECL_GETENV
|
||||
"this configure-time declaration test was not run"
|
||||
#endif
|
||||
#if !HAVE_DECL_GETENV
|
||||
char *getenv ();
|
||||
#endif
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(Text) gettext (Text)
|
||||
#else
|
||||
# define _(Text) Text
|
||||
#endif
|
||||
|
||||
#include <argmatch.h>
|
||||
#include <error.h>
|
||||
#include <xstrtol.h>
|
||||
|
||||
#include "human.h"
|
||||
|
||||
static const char suffixes[] =
|
||||
{
|
||||
0, /* not used */
|
||||
'K', /* kibi ('k' for kilo is a special case) */
|
||||
'M', /* mega or mebi */
|
||||
'G', /* giga or gibi */
|
||||
'T', /* tera or tebi */
|
||||
'P', /* peta or pebi */
|
||||
'E', /* exa or exbi */
|
||||
'Z', /* zetta or 2**70 */
|
||||
'Y' /* yotta or 2**80 */
|
||||
};
|
||||
|
||||
/* Generate into P[-1] (and possibly P[-2]) the proper suffix for
|
||||
POWER and BASE. Return the address of the generated suffix. */
|
||||
static char *
|
||||
generate_suffix_backwards (char *p, int power, int base)
|
||||
{
|
||||
char letter = suffixes[power];
|
||||
|
||||
if (base == 1000)
|
||||
{
|
||||
*--p = 'B';
|
||||
if (power == 1)
|
||||
letter = 'k';
|
||||
}
|
||||
|
||||
*--p = letter;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* If INEXACT_STYLE is not human_round_to_even, and if easily
|
||||
possible, adjust VALUE according to the style. */
|
||||
static double
|
||||
adjust_value (enum human_inexact_style inexact_style, double value)
|
||||
{
|
||||
/* Do not use the floor or ceil functions, as that would mean
|
||||
linking with the standard math library, which is a porting pain.
|
||||
So leave the value alone if it is too large to easily round. */
|
||||
if (inexact_style != human_round_to_even && value < (uintmax_t) -1)
|
||||
{
|
||||
uintmax_t u = value;
|
||||
value = u + (inexact_style == human_ceiling && u != value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Like human_readable_inexact, except always round to even. */
|
||||
char *
|
||||
human_readable (uintmax_t n, char *buf,
|
||||
int from_block_size, int output_block_size)
|
||||
{
|
||||
return human_readable_inexact (n, buf, from_block_size, output_block_size,
|
||||
human_round_to_even);
|
||||
}
|
||||
|
||||
/* Convert N to a human readable format in BUF.
|
||||
|
||||
N is expressed in units of FROM_BLOCK_SIZE. FROM_BLOCK_SIZE must
|
||||
be nonnegative.
|
||||
|
||||
OUTPUT_BLOCK_SIZE must be nonzero. If it is positive, use units of
|
||||
OUTPUT_BLOCK_SIZE in the output number.
|
||||
|
||||
Use INEXACT_STYLE to determine whether to take the ceiling or floor
|
||||
of any result that cannot be expressed exactly.
|
||||
|
||||
If OUTPUT_BLOCK_SIZE is negative, use a format like "127K" if
|
||||
possible, using powers of -OUTPUT_BLOCK_SIZE; otherwise, use
|
||||
ordinary decimal format. Normally -OUTPUT_BLOCK_SIZE is either
|
||||
1000 or 1024; it must be at least 2. Most people visually process
|
||||
strings of 3-4 digits effectively, but longer strings of digits are
|
||||
more prone to misinterpretation. Hence, converting to an
|
||||
abbreviated form usually improves readability. Use a suffix
|
||||
indicating which power is being used. For example, assuming
|
||||
-OUTPUT_BLOCK_SIZE is 1024, 8500 would be converted to 8.3K,
|
||||
133456345 to 127M, 56990456345 to 53G, and so on. Numbers smaller
|
||||
than -OUTPUT_BLOCK_SIZE aren't modified. If -OUTPUT_BLOCK_SIZE is
|
||||
1024, append a "B" after any size letter. */
|
||||
|
||||
char *
|
||||
human_readable_inexact (uintmax_t n, char *buf,
|
||||
int from_block_size, int output_block_size,
|
||||
enum human_inexact_style inexact_style)
|
||||
{
|
||||
uintmax_t amt;
|
||||
int base;
|
||||
int to_block_size;
|
||||
int tenths = 0;
|
||||
int power;
|
||||
char *p;
|
||||
|
||||
/* 0 means adjusted N == AMT.TENTHS;
|
||||
1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05;
|
||||
2 means adjusted N == AMT.TENTHS + 0.05;
|
||||
3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1. */
|
||||
int rounding = 0;
|
||||
|
||||
if (output_block_size < 0)
|
||||
{
|
||||
base = -output_block_size;
|
||||
to_block_size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
base = 0;
|
||||
to_block_size = output_block_size;
|
||||
}
|
||||
|
||||
p = buf + LONGEST_HUMAN_READABLE;
|
||||
*p = '\0';
|
||||
|
||||
#ifdef lint
|
||||
/* Suppress `used before initialized' warning. */
|
||||
power = 0;
|
||||
#endif
|
||||
|
||||
/* Adjust AMT out of FROM_BLOCK_SIZE units and into TO_BLOCK_SIZE units. */
|
||||
|
||||
{
|
||||
int multiplier;
|
||||
int divisor;
|
||||
int r2;
|
||||
int r10;
|
||||
if (to_block_size <= from_block_size
|
||||
? (from_block_size % to_block_size != 0
|
||||
|| (multiplier = from_block_size / to_block_size,
|
||||
(amt = n * multiplier) / multiplier != n))
|
||||
: (from_block_size == 0
|
||||
|| to_block_size % from_block_size != 0
|
||||
|| (divisor = to_block_size / from_block_size,
|
||||
r10 = (n % divisor) * 10,
|
||||
r2 = (r10 % divisor) * 2,
|
||||
amt = n / divisor,
|
||||
tenths = r10 / divisor,
|
||||
rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2),
|
||||
0)))
|
||||
{
|
||||
/* Either the result cannot be computed easily using uintmax_t,
|
||||
or from_block_size is zero. Fall back on floating point.
|
||||
FIXME: This can yield answers that are slightly off. */
|
||||
|
||||
double damt = n * (from_block_size / (double) to_block_size);
|
||||
|
||||
if (! base)
|
||||
sprintf (buf, "%.0f", adjust_value (inexact_style, damt));
|
||||
else
|
||||
{
|
||||
char suffix[3];
|
||||
char const *psuffix;
|
||||
double e = 1;
|
||||
power = 0;
|
||||
|
||||
do
|
||||
{
|
||||
e *= base;
|
||||
power++;
|
||||
}
|
||||
while (e * base <= damt && power < sizeof suffixes - 1);
|
||||
|
||||
damt /= e;
|
||||
|
||||
suffix[2] = '\0';
|
||||
psuffix = generate_suffix_backwards (suffix + 2, power, base);
|
||||
sprintf (buf, "%.1f%s",
|
||||
adjust_value (inexact_style, damt), psuffix);
|
||||
if (4 + (base == 1000) < strlen (buf))
|
||||
sprintf (buf, "%.0f%s",
|
||||
adjust_value (inexact_style, damt * 10) / 10, psuffix);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use power of BASE notation if adjusted AMT is large enough. */
|
||||
|
||||
if (base && base <= amt)
|
||||
{
|
||||
power = 0;
|
||||
|
||||
do
|
||||
{
|
||||
int r10 = (amt % base) * 10 + tenths;
|
||||
int r2 = (r10 % base) * 2 + (rounding >> 1);
|
||||
amt /= base;
|
||||
tenths = r10 / base;
|
||||
rounding = (r2 < base
|
||||
? 0 < r2 + rounding
|
||||
: 2 + (base < r2 + rounding));
|
||||
power++;
|
||||
}
|
||||
while (base <= amt && power < sizeof suffixes - 1);
|
||||
|
||||
p = generate_suffix_backwards (p, power, base);
|
||||
|
||||
if (amt < 10)
|
||||
{
|
||||
if (2 * (1 - (int) inexact_style)
|
||||
< rounding + (tenths & (inexact_style == human_round_to_even)))
|
||||
{
|
||||
tenths++;
|
||||
rounding = 0;
|
||||
|
||||
if (tenths == 10)
|
||||
{
|
||||
amt++;
|
||||
tenths = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (amt < 10)
|
||||
{
|
||||
*--p = '0' + tenths;
|
||||
*--p = '.';
|
||||
tenths = rounding = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inexact_style == human_ceiling
|
||||
? 0 < tenths + rounding
|
||||
: inexact_style == human_round_to_even
|
||||
? 5 < tenths + (2 < rounding + (amt & 1))
|
||||
: /* inexact_style == human_floor */ 0)
|
||||
{
|
||||
amt++;
|
||||
|
||||
if (amt == base && power < sizeof suffixes - 1)
|
||||
{
|
||||
*p = suffixes[power + 1];
|
||||
*--p = '0';
|
||||
*--p = '.';
|
||||
amt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
*--p = '0' + (int) (amt % 10);
|
||||
while ((amt /= 10) != 0);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/* The default block size used for output. This number may change in
|
||||
the future as disks get larger. */
|
||||
#ifndef DEFAULT_BLOCK_SIZE
|
||||
# define DEFAULT_BLOCK_SIZE 1024
|
||||
#endif
|
||||
|
||||
static char const *const block_size_args[] = { "human-readable", "si", 0 };
|
||||
static int const block_size_types[] = { -1024, -1000 };
|
||||
|
||||
static int
|
||||
default_block_size (void)
|
||||
{
|
||||
return getenv ("POSIXLY_CORRECT") ? 512 : DEFAULT_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
static strtol_error
|
||||
humblock (char const *spec, int *block_size)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (! spec && ! (spec = getenv ("BLOCK_SIZE")))
|
||||
*block_size = default_block_size ();
|
||||
else if (0 <= (i = ARGMATCH (spec, block_size_args, block_size_types)))
|
||||
*block_size = block_size_types[i];
|
||||
else
|
||||
{
|
||||
char *ptr;
|
||||
unsigned long val;
|
||||
strtol_error e = xstrtoul (spec, &ptr, 0, &val, "eEgGkKmMpPtTyYzZ0");
|
||||
if (e != LONGINT_OK)
|
||||
return e;
|
||||
if (*ptr)
|
||||
return LONGINT_INVALID_SUFFIX_CHAR;
|
||||
if ((int) val < 0 || val != (int) val)
|
||||
return LONGINT_OVERFLOW;
|
||||
*block_size = (int) val;
|
||||
}
|
||||
|
||||
return LONGINT_OK;
|
||||
}
|
||||
|
||||
void
|
||||
human_block_size (char const *spec, int report_errors, int *block_size)
|
||||
{
|
||||
strtol_error e = humblock (spec, block_size);
|
||||
if (*block_size == 0)
|
||||
{
|
||||
*block_size = default_block_size ();
|
||||
e = LONGINT_INVALID;
|
||||
}
|
||||
if (e != LONGINT_OK && report_errors)
|
||||
STRTOL_FATAL_ERROR (spec, _("block size"), e);
|
||||
}
|
||||
46
lib/human.h
46
lib/human.h
@@ -1,46 +0,0 @@
|
||||
#ifndef HUMAN_H_
|
||||
# define HUMAN_H_ 1
|
||||
|
||||
# if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
# endif
|
||||
|
||||
# if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
# endif
|
||||
|
||||
# if HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
# endif
|
||||
# ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
# endif
|
||||
|
||||
/* A conservative bound on the maximum length of a human-readable string.
|
||||
The output can be the product of the largest uintmax_t and the largest int,
|
||||
so add their sizes before converting to a bound on digits. */
|
||||
# define LONGEST_HUMAN_READABLE ((sizeof (uintmax_t) + sizeof (int)) \
|
||||
* CHAR_BIT / 3)
|
||||
|
||||
# ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
enum human_inexact_style
|
||||
{
|
||||
human_floor = -1,
|
||||
human_round_to_even = 0,
|
||||
human_ceiling = 1
|
||||
};
|
||||
|
||||
char *human_readable PARAMS ((uintmax_t, char *, int, int));
|
||||
char *human_readable_inexact PARAMS ((uintmax_t, char *, int, int,
|
||||
enum human_inexact_style));
|
||||
|
||||
void human_block_size PARAMS ((char const *, int, int *));
|
||||
|
||||
#endif /* HUMAN_H_ */
|
||||
@@ -1,9 +0,0 @@
|
||||
/* Some systems don't have ENOSYS. */
|
||||
#ifndef ENOSYS
|
||||
# ifdef ENOTSUP
|
||||
# define ENOSYS ENOTSUP
|
||||
# else
|
||||
/* Some systems don't have ENOTSUP either. */
|
||||
# define ENOSYS ENOMSG
|
||||
# endif
|
||||
#endif
|
||||
445
lib/modechange.c
445
lib/modechange.c
@@ -1,445 +0,0 @@
|
||||
/* modechange.c -- file mode manipulation
|
||||
Copyright (C) 1989, 1990, 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@ai.mit.edu> */
|
||||
|
||||
/* The ASCII mode string is compiled into a linked list of `struct
|
||||
modechange', which can then be applied to each file to be changed.
|
||||
We do this instead of re-parsing the ASCII string for each file
|
||||
because the compiled form requires less computation to use; when
|
||||
changing the mode of many files, this probably results in a
|
||||
performance gain. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "modechange.h"
|
||||
#include <sys/stat.h>
|
||||
#include "xstrtol.h"
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
char *malloc ();
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
#if STAT_MACROS_BROKEN
|
||||
# undef S_ISDIR
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISUID
|
||||
# define S_ISUID 04000
|
||||
#endif
|
||||
#ifndef S_ISGID
|
||||
# define S_ISGID 04000
|
||||
#endif
|
||||
#ifndef S_ISVTX
|
||||
# define S_ISVTX 01000
|
||||
#endif
|
||||
#ifndef S_IRUSR
|
||||
# define S_IRUSR 0400
|
||||
#endif
|
||||
#ifndef S_IWUSR
|
||||
# define S_IWUSR 0200
|
||||
#endif
|
||||
#ifndef S_IXUSR
|
||||
# define S_IXUSR 0100
|
||||
#endif
|
||||
#ifndef S_IRGRP
|
||||
# define S_IRGRP 0040
|
||||
#endif
|
||||
#ifndef S_IWGRP
|
||||
# define S_IWGRP 0020
|
||||
#endif
|
||||
#ifndef S_IXGRP
|
||||
# define S_IXGRP 0010
|
||||
#endif
|
||||
#ifndef S_IROTH
|
||||
# define S_IROTH 0004
|
||||
#endif
|
||||
#ifndef S_IWOTH
|
||||
# define S_IWOTH 0002
|
||||
#endif
|
||||
#ifndef S_IXOTH
|
||||
# define S_IXOTH 0001
|
||||
#endif
|
||||
#ifndef S_IRWXU
|
||||
# define S_IRWXU 0700
|
||||
#endif
|
||||
#ifndef S_IRWXG
|
||||
# define S_IRWXG 0070
|
||||
#endif
|
||||
#ifndef S_IRWXO
|
||||
# define S_IRWXO 0007
|
||||
#endif
|
||||
|
||||
/* All the mode bits that can be affected by chmod. */
|
||||
#define CHMOD_MODE_BITS \
|
||||
(S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
|
||||
|
||||
/* Return newly allocated memory to hold one element of type TYPE. */
|
||||
#define talloc(type) ((type *) malloc (sizeof (type)))
|
||||
|
||||
/* Create a mode_change entry with the specified `=ddd'-style
|
||||
mode change operation, where NEW_MODE is `ddd'. Return the
|
||||
new entry, or NULL upon failure. */
|
||||
|
||||
static struct mode_change *
|
||||
make_node_op_equals (mode_t new_mode)
|
||||
{
|
||||
struct mode_change *p;
|
||||
p = talloc (struct mode_change);
|
||||
if (p == NULL)
|
||||
return p;
|
||||
p->next = NULL;
|
||||
p->op = '=';
|
||||
p->flags = 0;
|
||||
p->value = new_mode;
|
||||
p->affected = CHMOD_MODE_BITS; /* Affect all permissions. */
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Append entry E to the end of the link list with the specified
|
||||
HEAD and TAIL. */
|
||||
|
||||
static void
|
||||
mode_append_entry (struct mode_change **head,
|
||||
struct mode_change **tail,
|
||||
struct mode_change *e)
|
||||
{
|
||||
if (*head == NULL)
|
||||
*head = *tail = e;
|
||||
else
|
||||
{
|
||||
(*tail)->next = e;
|
||||
*tail = e;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a linked list of file mode change operations created from
|
||||
MODE_STRING, an ASCII string that contains either an octal number
|
||||
specifying an absolute mode, or symbolic mode change operations with
|
||||
the form:
|
||||
[ugoa...][[+-=][rwxXstugo...]...][,...]
|
||||
MASKED_OPS is a bitmask indicating which symbolic mode operators (=+-)
|
||||
should not affect bits set in the umask when no users are given.
|
||||
Operators not selected in MASKED_OPS ignore the umask.
|
||||
|
||||
Return MODE_INVALID if `mode_string' does not contain a valid
|
||||
representation of file mode change operations;
|
||||
return MODE_MEMORY_EXHAUSTED if there is insufficient memory. */
|
||||
|
||||
struct mode_change *
|
||||
mode_compile (const char *mode_string, unsigned int masked_ops)
|
||||
{
|
||||
struct mode_change *head; /* First element of the linked list. */
|
||||
struct mode_change *tail; /* An element of the linked list. */
|
||||
uintmax_t mode_value; /* The mode value, if octal. */
|
||||
char *string_end; /* Pointer to end of parsed value. */
|
||||
mode_t umask_value; /* The umask value (surprise). */
|
||||
|
||||
head = NULL;
|
||||
#ifdef lint
|
||||
tail = NULL;
|
||||
#endif
|
||||
|
||||
if (xstrtoumax (mode_string, &string_end, 8, &mode_value, "") == LONGINT_OK)
|
||||
{
|
||||
struct mode_change *p;
|
||||
if (mode_value != (mode_value & CHMOD_MODE_BITS))
|
||||
return MODE_INVALID;
|
||||
p = make_node_op_equals ((mode_t) mode_value);
|
||||
if (p == NULL)
|
||||
return MODE_MEMORY_EXHAUSTED;
|
||||
mode_append_entry (&head, &tail, p);
|
||||
return head;
|
||||
}
|
||||
|
||||
umask_value = umask (0);
|
||||
umask (umask_value); /* Restore the old value. */
|
||||
--mode_string;
|
||||
|
||||
/* One loop iteration for each "ugoa...=+-rwxXstugo...[=+-rwxXstugo...]". */
|
||||
do
|
||||
{
|
||||
/* Which bits in the mode are operated on. */
|
||||
mode_t affected_bits = 0;
|
||||
/* `affected_bits' modified by umask. */
|
||||
mode_t affected_masked;
|
||||
/* Operators to actually use umask on. */
|
||||
unsigned ops_to_mask = 0;
|
||||
|
||||
int who_specified_p;
|
||||
|
||||
affected_bits = 0;
|
||||
ops_to_mask = 0;
|
||||
/* Turn on all the bits in `affected_bits' for each group given. */
|
||||
for (++mode_string;; ++mode_string)
|
||||
switch (*mode_string)
|
||||
{
|
||||
case 'u':
|
||||
affected_bits |= S_ISUID | S_IRWXU;
|
||||
break;
|
||||
case 'g':
|
||||
affected_bits |= S_ISGID | S_IRWXG;
|
||||
break;
|
||||
case 'o':
|
||||
affected_bits |= S_ISVTX | S_IRWXO;
|
||||
break;
|
||||
case 'a':
|
||||
affected_bits |= CHMOD_MODE_BITS;
|
||||
break;
|
||||
default:
|
||||
goto no_more_affected;
|
||||
}
|
||||
|
||||
no_more_affected:
|
||||
/* If none specified, affect all bits, except perhaps those
|
||||
set in the umask. */
|
||||
if (affected_bits)
|
||||
who_specified_p = 1;
|
||||
else
|
||||
{
|
||||
who_specified_p = 0;
|
||||
affected_bits = CHMOD_MODE_BITS;
|
||||
ops_to_mask = masked_ops;
|
||||
}
|
||||
|
||||
while (*mode_string == '=' || *mode_string == '+' || *mode_string == '-')
|
||||
{
|
||||
struct mode_change *change = talloc (struct mode_change);
|
||||
if (change == NULL)
|
||||
{
|
||||
mode_free (head);
|
||||
return MODE_MEMORY_EXHAUSTED;
|
||||
}
|
||||
|
||||
change->next = NULL;
|
||||
change->op = *mode_string; /* One of "=+-". */
|
||||
affected_masked = affected_bits;
|
||||
|
||||
/* Per the Single Unix Spec, if `who' is not specified and the
|
||||
`=' operator is used, then clear all the bits first. */
|
||||
if (!who_specified_p &&
|
||||
ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS : 0))
|
||||
{
|
||||
struct mode_change *p = make_node_op_equals (0);
|
||||
if (p == NULL)
|
||||
return MODE_MEMORY_EXHAUSTED;
|
||||
mode_append_entry (&head, &tail, p);
|
||||
}
|
||||
|
||||
if (ops_to_mask & (*mode_string == '=' ? MODE_MASK_EQUALS
|
||||
: *mode_string == '+' ? MODE_MASK_PLUS
|
||||
: MODE_MASK_MINUS))
|
||||
affected_masked &= ~umask_value;
|
||||
change->affected = affected_masked;
|
||||
change->value = 0;
|
||||
change->flags = 0;
|
||||
|
||||
/* Add the element to the tail of the list, so the operations
|
||||
are performed in the correct order. */
|
||||
mode_append_entry (&head, &tail, change);
|
||||
|
||||
/* Set `value' according to the bits set in `affected_masked'. */
|
||||
for (++mode_string;; ++mode_string)
|
||||
switch (*mode_string)
|
||||
{
|
||||
case 'r':
|
||||
change->value |= ((S_IRUSR | S_IRGRP | S_IROTH)
|
||||
& affected_masked);
|
||||
break;
|
||||
case 'w':
|
||||
change->value |= ((S_IWUSR | S_IWGRP | S_IWOTH)
|
||||
& affected_masked);
|
||||
break;
|
||||
case 'X':
|
||||
change->flags |= MODE_X_IF_ANY_X;
|
||||
/* Fall through. */
|
||||
case 'x':
|
||||
change->value |= ((S_IXUSR | S_IXGRP | S_IXOTH)
|
||||
& affected_masked);
|
||||
break;
|
||||
case 's':
|
||||
/* Set the setuid/gid bits if `u' or `g' is selected. */
|
||||
change->value |= (S_ISUID | S_ISGID) & affected_masked;
|
||||
break;
|
||||
case 't':
|
||||
/* Set the "save text image" bit if `o' is selected. */
|
||||
change->value |= S_ISVTX & affected_masked;
|
||||
break;
|
||||
case 'u':
|
||||
/* Set the affected bits to the value of the `u' bits
|
||||
on the same file. */
|
||||
if (change->value)
|
||||
goto invalid;
|
||||
change->value = S_IRWXU;
|
||||
change->flags |= MODE_COPY_EXISTING;
|
||||
break;
|
||||
case 'g':
|
||||
/* Set the affected bits to the value of the `g' bits
|
||||
on the same file. */
|
||||
if (change->value)
|
||||
goto invalid;
|
||||
change->value = S_IRWXG;
|
||||
change->flags |= MODE_COPY_EXISTING;
|
||||
break;
|
||||
case 'o':
|
||||
/* Set the affected bits to the value of the `o' bits
|
||||
on the same file. */
|
||||
if (change->value)
|
||||
goto invalid;
|
||||
change->value = S_IRWXO;
|
||||
change->flags |= MODE_COPY_EXISTING;
|
||||
break;
|
||||
default:
|
||||
goto no_more_values;
|
||||
}
|
||||
no_more_values:;
|
||||
}
|
||||
} while (*mode_string == ',');
|
||||
if (*mode_string == 0)
|
||||
return head;
|
||||
invalid:
|
||||
mode_free (head);
|
||||
return MODE_INVALID;
|
||||
}
|
||||
|
||||
/* Return a file mode change operation that sets permissions to match those
|
||||
of REF_FILE. Return MODE_BAD_REFERENCE if REF_FILE can't be accessed. */
|
||||
|
||||
struct mode_change *
|
||||
mode_create_from_ref (const char *ref_file)
|
||||
{
|
||||
struct mode_change *change; /* the only change element */
|
||||
struct stat ref_stats;
|
||||
|
||||
if (stat (ref_file, &ref_stats))
|
||||
return MODE_BAD_REFERENCE;
|
||||
|
||||
change = talloc (struct mode_change);
|
||||
|
||||
if (change == NULL)
|
||||
return MODE_MEMORY_EXHAUSTED;
|
||||
|
||||
change->op = '=';
|
||||
change->flags = 0;
|
||||
change->affected = CHMOD_MODE_BITS;
|
||||
change->value = ref_stats.st_mode;
|
||||
change->next = NULL;
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
/* Return file mode OLDMODE, adjusted as indicated by the list of change
|
||||
operations CHANGES. If OLDMODE is a directory, the type `X'
|
||||
change affects it even if no execute bits were set in OLDMODE.
|
||||
The returned value has the S_IFMT bits cleared. */
|
||||
|
||||
mode_t
|
||||
mode_adjust (mode_t oldmode, const struct mode_change *changes)
|
||||
{
|
||||
mode_t newmode; /* The adjusted mode and one operand. */
|
||||
mode_t value; /* The other operand. */
|
||||
|
||||
newmode = oldmode & CHMOD_MODE_BITS;
|
||||
|
||||
for (; changes; changes = changes->next)
|
||||
{
|
||||
if (changes->flags & MODE_COPY_EXISTING)
|
||||
{
|
||||
/* Isolate in `value' the bits in `newmode' to copy, given in
|
||||
the mask `changes->value'. */
|
||||
value = newmode & changes->value;
|
||||
|
||||
if (changes->value & S_IRWXU)
|
||||
/* Copy `u' permissions onto `g' and `o'. */
|
||||
value |= ((value & S_IRUSR ? S_IRGRP | S_IROTH : 0)
|
||||
| (value & S_IWUSR ? S_IWGRP | S_IROTH : 0)
|
||||
| (value & S_IXUSR ? S_IXGRP | S_IXOTH : 0));
|
||||
else if (changes->value & S_IRWXG)
|
||||
/* Copy `g' permissions onto `u' and `o'. */
|
||||
value |= ((value & S_IRGRP ? S_IRUSR | S_IROTH : 0)
|
||||
| (value & S_IWGRP ? S_IWUSR | S_IROTH : 0)
|
||||
| (value & S_IXGRP ? S_IXUSR | S_IXOTH : 0));
|
||||
else
|
||||
/* Copy `o' permissions onto `u' and `g'. */
|
||||
value |= ((value & S_IROTH ? S_IRUSR | S_IRGRP : 0)
|
||||
| (value & S_IWOTH ? S_IWUSR | S_IRGRP : 0)
|
||||
| (value & S_IXOTH ? S_IXUSR | S_IXGRP : 0));
|
||||
|
||||
/* In order to change only `u', `g', or `o' permissions,
|
||||
or some combination thereof, clear unselected bits.
|
||||
This can not be done in mode_compile because the value
|
||||
to which the `changes->affected' mask is applied depends
|
||||
on the old mode of each file. */
|
||||
value &= changes->affected;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = changes->value;
|
||||
/* If `X', do not affect the execute bits if the file is not a
|
||||
directory and no execute bits are already set. */
|
||||
if ((changes->flags & MODE_X_IF_ANY_X)
|
||||
&& !S_ISDIR (oldmode)
|
||||
&& (newmode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
|
||||
/* Clear the execute bits. */
|
||||
value &= ~ (S_IXUSR | S_IXGRP | S_IXOTH);
|
||||
}
|
||||
|
||||
switch (changes->op)
|
||||
{
|
||||
case '=':
|
||||
/* Preserve the previous values in `newmode' of bits that are
|
||||
not affected by this change operation. */
|
||||
newmode = (newmode & ~changes->affected) | value;
|
||||
break;
|
||||
case '+':
|
||||
newmode |= value;
|
||||
break;
|
||||
case '-':
|
||||
newmode &= ~value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return newmode;
|
||||
}
|
||||
|
||||
/* Free the memory used by the list of file mode change operations
|
||||
CHANGES. */
|
||||
|
||||
void
|
||||
mode_free (register struct mode_change *changes)
|
||||
{
|
||||
register struct mode_change *next;
|
||||
|
||||
while (changes)
|
||||
{
|
||||
next = changes->next;
|
||||
free (changes);
|
||||
changes = next;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/* Print a copyright notice suitable for the current locale.
|
||||
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "print-copyr.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include "unicodeio.h"
|
||||
#else
|
||||
# define unicode_to_mb(code, callback, error_callback, callback_arg) \
|
||||
error_callback (code, callback_arg)
|
||||
#endif
|
||||
|
||||
#define COPYRIGHT_SIGN 0x00A9
|
||||
|
||||
/* Print "(C)". */
|
||||
|
||||
static int
|
||||
print_parenthesized_c (unsigned int code, void *callback_arg)
|
||||
{
|
||||
FILE *stream = callback_arg;
|
||||
return fputs ("(C)", stream);
|
||||
}
|
||||
|
||||
/* Print "Copyright (C) " followed by NOTICE and then a newline,
|
||||
transliterating "(C)" to an actual copyright sign (C-in-a-circle)
|
||||
if possible. */
|
||||
|
||||
void
|
||||
print_copyright (char const *notice)
|
||||
{
|
||||
fputs ("Copyright ", stdout);
|
||||
unicode_to_mb (COPYRIGHT_SIGN, print_unicode_char, print_parenthesized_c,
|
||||
stdout);
|
||||
fputc (' ', stdout);
|
||||
puts (notice);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
# ifndef PARAMS
|
||||
# if PROTOTYPES || (defined (__STDC__) && __STDC__)
|
||||
# define PARAMS(args) args
|
||||
# else
|
||||
# define PARAMS(args) ()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
void print_copyright PARAMS((char const *));
|
||||
658
lib/quotearg.c
658
lib/quotearg.c
@@ -1,658 +0,0 @@
|
||||
/* quotearg.c - quote arguments for output
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com> */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDDEF_H
|
||||
# include <stddef.h> /* For the definition of size_t on windows w/MSVC. */
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <quotearg.h>
|
||||
#include <xalloc.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(text) gettext (text)
|
||||
#else
|
||||
# define _(text) text
|
||||
#endif
|
||||
#define N_(text) text
|
||||
|
||||
#if HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
#ifndef UCHAR_MAX
|
||||
# define UCHAR_MAX ((unsigned char) -1)
|
||||
#endif
|
||||
#ifndef UINT_MAX
|
||||
# define UINT_MAX ((unsigned int) -1)
|
||||
#endif
|
||||
|
||||
#if HAVE_C_BACKSLASH_A
|
||||
# define ALERT_CHAR '\a'
|
||||
#else
|
||||
# define ALERT_CHAR '\7'
|
||||
#endif
|
||||
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_WCHAR_H
|
||||
|
||||
/* BSD/OS 4.1 wchar.h requires FILE and struct tm to be declared. */
|
||||
# include <stdio.h>
|
||||
# include <time.h>
|
||||
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
|
||||
#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
|
||||
# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
|
||||
# define mbsinit(ps) 1
|
||||
# define iswprint(wc) ISPRINT ((unsigned char) (wc))
|
||||
#endif
|
||||
|
||||
#ifndef iswprint
|
||||
# if HAVE_WCTYPE_H
|
||||
# include <wctype.h>
|
||||
# endif
|
||||
# if !defined iswprint && !HAVE_ISWPRINT
|
||||
# define iswprint(wc) 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define INT_BITS (sizeof (int) * CHAR_BIT)
|
||||
|
||||
#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
|
||||
# define IN_CTYPE_DOMAIN(c) 1
|
||||
#else
|
||||
# define IN_CTYPE_DOMAIN(c) isascii(c)
|
||||
#endif
|
||||
|
||||
/* Undefine to protect against the definition in wctype.h of solaris2.6. */
|
||||
#undef ISPRINT
|
||||
#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
|
||||
|
||||
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. */
|
||||
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)
|
||||
{
|
||||
struct quoting_options *p
|
||||
= (struct quoting_options *) xmalloc (sizeof (struct quoting_options));
|
||||
*p = *(o ? o : &default_quoting_options);
|
||||
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;
|
||||
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 -1, 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;
|
||||
int backslash_escapes = 0;
|
||||
int 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 = 1;
|
||||
quote_string = "\"";
|
||||
quote_string_len = 1;
|
||||
break;
|
||||
|
||||
case escape_quoting_style:
|
||||
backslash_escapes = 1;
|
||||
break;
|
||||
|
||||
case locale_quoting_style:
|
||||
case clocale_quoting_style:
|
||||
{
|
||||
/* 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. */
|
||||
|
||||
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 = 1;
|
||||
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_t) -1 ? 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. */
|
||||
i += 2;
|
||||
c = arg[i + 2];
|
||||
STORE ('?');
|
||||
STORE ('\\');
|
||||
STORE ('?');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ALERT_CHAR: 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 '~':
|
||||
if (i != 0)
|
||||
break;
|
||||
/* Fall through. */
|
||||
case ' ':
|
||||
case '!': /* special in bash */
|
||||
case '"': case '$': case '&':
|
||||
case '(': case ')': case '*': case ';':
|
||||
case '<': 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 '=':
|
||||
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':
|
||||
case '{': case '}':
|
||||
/* 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;
|
||||
|
||||
int printable;
|
||||
|
||||
if (unibyte_locale)
|
||||
{
|
||||
m = 1;
|
||||
printable = ISPRINT (c);
|
||||
}
|
||||
else
|
||||
{
|
||||
mbstate_t mbstate;
|
||||
memset (&mbstate, 0, sizeof mbstate);
|
||||
|
||||
m = 0;
|
||||
printable = 1;
|
||||
if (argsize == (size_t) -1)
|
||||
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 = 0;
|
||||
break;
|
||||
}
|
||||
else if (bytes == (size_t) -2)
|
||||
{
|
||||
printable = 0;
|
||||
while (i + m < argsize && arg[i + m])
|
||||
m++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! iswprint (w))
|
||||
printable = 0;
|
||||
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 (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 -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)
|
||||
{
|
||||
struct quoting_options const *p = o ? o : &default_quoting_options;
|
||||
return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
|
||||
p->style, p);
|
||||
}
|
||||
|
||||
/* Use storage slot N to return a quoted version of argument ARG.
|
||||
ARG is of size ARGSIZE, but if that is -1, 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)
|
||||
{
|
||||
/* 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;
|
||||
unsigned int n0 = n;
|
||||
struct slotvec
|
||||
{
|
||||
size_t size;
|
||||
char *val;
|
||||
};
|
||||
static struct slotvec slotvec0 = {sizeof slot0, slot0};
|
||||
static struct slotvec *slotvec = &slotvec0;
|
||||
|
||||
if (n < 0)
|
||||
abort ();
|
||||
|
||||
if (nslots <= n0)
|
||||
{
|
||||
unsigned int n1 = n0 + 1;
|
||||
size_t s = n1 * sizeof *slotvec;
|
||||
|
||||
if (SIZE_MAX / UINT_MAX <= sizeof *slotvec
|
||||
&& n1 != s / sizeof *slotvec)
|
||||
xalloc_die ();
|
||||
|
||||
if (slotvec == &slotvec0)
|
||||
{
|
||||
slotvec = (struct slotvec *) xmalloc (sizeof *slotvec);
|
||||
*slotvec = slotvec0;
|
||||
}
|
||||
slotvec = (struct slotvec *) xrealloc (slotvec, s);
|
||||
memset (slotvec + nslots, 0, (n1 - nslots) * sizeof *slotvec);
|
||||
nslots = n1;
|
||||
}
|
||||
|
||||
{
|
||||
size_t size = slotvec[n].size;
|
||||
char *val = slotvec[n].val;
|
||||
size_t qsize = quotearg_buffer (val, size, arg, argsize, options);
|
||||
|
||||
if (size <= qsize)
|
||||
{
|
||||
slotvec[n].size = size = qsize + 1;
|
||||
slotvec[n].val = val = xrealloc (val == slot0 ? 0 : val, size);
|
||||
quotearg_buffer (val, size, arg, argsize, options);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_n (int n, char const *arg)
|
||||
{
|
||||
return quotearg_n_options (n, arg, (size_t) -1, &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_t) -1, &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_t) -1, &options);
|
||||
}
|
||||
|
||||
char *
|
||||
quotearg_colon (char const *arg)
|
||||
{
|
||||
return quotearg_char (arg, ':');
|
||||
}
|
||||
100
lib/quotearg.h
100
lib/quotearg.h
@@ -1,100 +0,0 @@
|
||||
/* quotearg.h - quote arguments for output
|
||||
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Paul Eggert <eggert@twinsun.com> */
|
||||
|
||||
/* Basic quoting styles. */
|
||||
enum quoting_style
|
||||
{
|
||||
literal_quoting_style, /* --quoting-style=literal */
|
||||
shell_quoting_style, /* --quoting-style=shell */
|
||||
shell_always_quoting_style, /* --quoting-style=shell-always */
|
||||
c_quoting_style, /* --quoting-style=c */
|
||||
escape_quoting_style /* --quoting-style=escape */
|
||||
};
|
||||
|
||||
/* For now, --quoting-style=literal is the default, but
|
||||
this is planned to change to --quoting-style=shell in the future. */
|
||||
#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;
|
||||
|
||||
#ifndef PARAMS
|
||||
# if defined PROTOTYPES || defined __STDC__
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
PARAMS ((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 PARAMS ((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 PARAMS ((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 PARAMS ((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 PARAMS ((char *buffer, size_t buffersize,
|
||||
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 PARAMS ((unsigned int n, char const *arg));
|
||||
|
||||
/* Equivalent to quotearg_n (0, ARG). */
|
||||
char *quotearg PARAMS ((char const *arg));
|
||||
|
||||
/* Like quotearg (ARG), except also quote any instances of CH. */
|
||||
char *quotearg_char PARAMS ((char const *arg, char ch));
|
||||
|
||||
/* Equivalent to quotearg_char (ARG, ':'). */
|
||||
char *quotearg_colon PARAMS ((char const *arg));
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
ssize_t full_write PARAMS ((int desc, const char *ptr, size_t len));
|
||||
ssize_t safe_read PARAMS ((int desc, void *ptr, size_t len));
|
||||
129
lib/savedir.c
129
lib/savedir.c
@@ -1,129 +0,0 @@
|
||||
/* savedir.c -- save the list of files in a directory in a string
|
||||
|
||||
Copyright 1990, 1997, 1998, 1999, 2000, 2001 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef CLOSEDIR_VOID
|
||||
/* Fake a return value. */
|
||||
# define CLOSEDIR(d) (closedir (d), 0)
|
||||
#else
|
||||
# define CLOSEDIR(d) closedir (d)
|
||||
#endif
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
#include "savedir.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Return a freshly allocated string containing the filenames
|
||||
in directory DIR, separated by '\0' characters;
|
||||
the end is marked by two '\0' characters in a row.
|
||||
Return NULL (setting errno) if DIR cannot be opened, read, or closed. */
|
||||
|
||||
#ifndef NAME_SIZE_DEFAULT
|
||||
# define NAME_SIZE_DEFAULT 512
|
||||
#endif
|
||||
|
||||
char *
|
||||
savedir (const char *dir)
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
char *name_space;
|
||||
size_t allocated = NAME_SIZE_DEFAULT;
|
||||
size_t used = 0;
|
||||
int save_errno;
|
||||
|
||||
dirp = opendir (dir);
|
||||
if (dirp == NULL)
|
||||
return NULL;
|
||||
|
||||
name_space = xmalloc (allocated);
|
||||
|
||||
errno = 0;
|
||||
while ((dp = readdir (dirp)) != NULL)
|
||||
{
|
||||
/* Skip "", ".", and "..". "" is returned by at least one buggy
|
||||
implementation: Solaris 2.4 readdir on NFS filesystems. */
|
||||
char const *entry = dp->d_name;
|
||||
if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
|
||||
{
|
||||
size_t entry_size = strlen (entry) + 1;
|
||||
if (used + entry_size < used)
|
||||
xalloc_die ();
|
||||
if (allocated <= used + entry_size)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (2 * allocated < allocated)
|
||||
xalloc_die ();
|
||||
allocated *= 2;
|
||||
}
|
||||
while (allocated <= used + entry_size);
|
||||
|
||||
name_space = xrealloc (name_space, allocated);
|
||||
}
|
||||
memcpy (name_space + used, entry, entry_size);
|
||||
used += entry_size;
|
||||
}
|
||||
}
|
||||
name_space[used] = '\0';
|
||||
save_errno = errno;
|
||||
if (CLOSEDIR (dirp) != 0)
|
||||
save_errno = errno;
|
||||
if (save_errno != 0)
|
||||
{
|
||||
free (name_space);
|
||||
errno = save_errno;
|
||||
return NULL;
|
||||
}
|
||||
return name_space;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#if !defined SAVEDIR_H_
|
||||
# define SAVEDIR_H_
|
||||
|
||||
# ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
char *savedir PARAMS ((const char *dir));
|
||||
|
||||
#endif
|
||||
101
lib/strtoimax.c
101
lib/strtoimax.c
@@ -1,101 +0,0 @@
|
||||
/* Convert string representation of a number into an intmax_t value.
|
||||
|
||||
Copyright (C) 1999, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef PARAMS
|
||||
# if defined PROTOTYPES || defined __STDC__
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Verify a requirement at compile-time (unlike assert, which is runtime). */
|
||||
#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
|
||||
|
||||
#ifdef UNSIGNED
|
||||
# ifndef HAVE_DECL_STRTOUL
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
# if !HAVE_DECL_STRTOUL
|
||||
unsigned long strtoul PARAMS ((char const *, char **, int));
|
||||
# endif
|
||||
# ifndef HAVE_DECL_STRTOULL
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
# if !HAVE_DECL_STRTOULL && HAVE_UNSIGNED_LONG_LONG
|
||||
unsigned long long strtoull PARAMS ((char const *, char **, int));
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
# ifndef HAVE_DECL_STRTOL
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
# if !HAVE_DECL_STRTOL
|
||||
long strtol PARAMS ((char const *, char **, int));
|
||||
# endif
|
||||
# ifndef HAVE_DECL_STRTOLL
|
||||
"this configure-time declaration test was not run"
|
||||
# endif
|
||||
# if !HAVE_DECL_STRTOLL && HAVE_LONG_LONG
|
||||
long long strtoll PARAMS ((char const *, char **, int));
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef UNSIGNED
|
||||
# undef HAVE_LONG_LONG
|
||||
# define HAVE_LONG_LONG HAVE_UNSIGNED_LONG_LONG
|
||||
# define INT uintmax_t
|
||||
# define strtoimax strtoumax
|
||||
# define strtol strtoul
|
||||
# define strtoll strtoull
|
||||
#else
|
||||
# define INT intmax_t
|
||||
#endif
|
||||
|
||||
INT
|
||||
strtoimax (char const *ptr, char **endptr, int base)
|
||||
{
|
||||
#if HAVE_LONG_LONG
|
||||
verify (size_is_that_of_long_or_long_long,
|
||||
(sizeof (INT) == sizeof (long)
|
||||
|| sizeof (INT) == sizeof (long long)));
|
||||
|
||||
if (sizeof (INT) != sizeof (long))
|
||||
return strtoll (ptr, endptr, base);
|
||||
#else
|
||||
verify (size_is_that_of_long,
|
||||
sizeof (INT) == sizeof (long));
|
||||
#endif
|
||||
|
||||
return strtol (ptr, endptr, base);
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
#define UNSIGNED 1
|
||||
#include "strtoimax.c"
|
||||
263
lib/unicodeio.c
263
lib/unicodeio.c
@@ -1,263 +0,0 @@
|
||||
/* Unicode character output to streams with locale dependent encoding.
|
||||
|
||||
Copyright (C) 2000-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
USA. */
|
||||
|
||||
/* Written by Bruno Haible <haible@clisp.cons.org>. */
|
||||
|
||||
/* Note: This file requires the locale_charset() function. See in
|
||||
libiconv-1.7/libcharset/INTEGRATE for how to obtain it. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDDEF_H
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if HAVE_ICONV
|
||||
# include <iconv.h>
|
||||
#endif
|
||||
|
||||
#include <error.h>
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# define gettext(Text) Text
|
||||
#endif
|
||||
#define _(Text) gettext (Text)
|
||||
#define N_(Text) Text
|
||||
|
||||
/* Specification. */
|
||||
#include "unicodeio.h"
|
||||
|
||||
/* When we pass a Unicode character to iconv(), we must pass it in a
|
||||
suitable encoding. The standardized Unicode encodings are
|
||||
UTF-8, UCS-2, UCS-4, UTF-16, UTF-16BE, UTF-16LE, UTF-7.
|
||||
UCS-2 supports only characters up to \U0000FFFF.
|
||||
UTF-16 and variants support only characters up to \U0010FFFF.
|
||||
UTF-7 is way too complex and not supported by glibc-2.1.
|
||||
UCS-4 specification leaves doubts about endianness and byte order
|
||||
mark. glibc currently interprets it as big endian without byte order
|
||||
mark, but this is not backed by an RFC.
|
||||
So we use UTF-8. It supports characters up to \U7FFFFFFF and is
|
||||
unambiguously defined. */
|
||||
|
||||
/* Stores the UTF-8 representation of the Unicode character wc in r[0..5].
|
||||
Returns the number of bytes stored, or -1 if wc is out of range. */
|
||||
static int
|
||||
utf8_wctomb (unsigned char *r, unsigned int wc)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (wc < 0x80)
|
||||
count = 1;
|
||||
else if (wc < 0x800)
|
||||
count = 2;
|
||||
else if (wc < 0x10000)
|
||||
count = 3;
|
||||
else if (wc < 0x200000)
|
||||
count = 4;
|
||||
else if (wc < 0x4000000)
|
||||
count = 5;
|
||||
else if (wc <= 0x7fffffff)
|
||||
count = 6;
|
||||
else
|
||||
return -1;
|
||||
|
||||
switch (count)
|
||||
{
|
||||
/* Note: code falls through cases! */
|
||||
case 6: r[5] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x4000000;
|
||||
case 5: r[4] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x200000;
|
||||
case 4: r[3] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x10000;
|
||||
case 3: r[2] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x800;
|
||||
case 2: r[1] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0xc0;
|
||||
case 1: r[0] = wc;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Luckily, the encoding's name is platform independent. */
|
||||
#define UTF8_NAME "UTF-8"
|
||||
|
||||
/* Converts the Unicode character CODE to its multibyte representation
|
||||
in the current locale and calls the SUCCESS callback on the resulting
|
||||
byte sequence. If an error occurs, invokes the FAILURE callback instead,
|
||||
passing it CODE and an English error string.
|
||||
Returns whatever the callback returned.
|
||||
Assumes that the locale doesn't change between two calls. */
|
||||
long
|
||||
unicode_to_mb (unsigned int code,
|
||||
long (*success) PARAMS ((const char *buf, size_t buflen,
|
||||
void *callback_arg)),
|
||||
long (*failure) PARAMS ((unsigned int code, const char *msg,
|
||||
void *callback_arg)),
|
||||
void *callback_arg)
|
||||
{
|
||||
static int initialized;
|
||||
static int is_utf8;
|
||||
#if HAVE_ICONV
|
||||
static iconv_t utf8_to_local;
|
||||
#endif
|
||||
|
||||
char inbuf[6];
|
||||
int count;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
extern const char *locale_charset PARAMS ((void));
|
||||
const char *charset = locale_charset ();
|
||||
|
||||
is_utf8 = !strcmp (charset, UTF8_NAME);
|
||||
#if HAVE_ICONV
|
||||
if (!is_utf8)
|
||||
{
|
||||
utf8_to_local = iconv_open (charset, UTF8_NAME);
|
||||
if (utf8_to_local == (iconv_t)(-1))
|
||||
/* For an unknown encoding, assume ASCII. */
|
||||
utf8_to_local = iconv_open ("ASCII", UTF8_NAME);
|
||||
}
|
||||
#endif
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
/* Test whether the utf8_to_local converter is available at all. */
|
||||
if (!is_utf8)
|
||||
{
|
||||
#if HAVE_ICONV
|
||||
if (utf8_to_local == (iconv_t)(-1))
|
||||
return failure (code, N_("iconv function not usable"), callback_arg);
|
||||
#else
|
||||
return failure (code, N_("iconv function not available"), callback_arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert the character to UTF-8. */
|
||||
count = utf8_wctomb ((unsigned char *) inbuf, code);
|
||||
if (count < 0)
|
||||
return failure (code, N_("character out of range"), callback_arg);
|
||||
|
||||
#if HAVE_ICONV
|
||||
if (!is_utf8)
|
||||
{
|
||||
char outbuf[25];
|
||||
const char *inptr;
|
||||
size_t inbytesleft;
|
||||
char *outptr;
|
||||
size_t outbytesleft;
|
||||
size_t res;
|
||||
|
||||
inptr = inbuf;
|
||||
inbytesleft = count;
|
||||
outptr = outbuf;
|
||||
outbytesleft = sizeof (outbuf);
|
||||
|
||||
/* Convert the character from UTF-8 to the locale's charset. */
|
||||
res = iconv (utf8_to_local,
|
||||
(ICONV_CONST char **)&inptr, &inbytesleft,
|
||||
&outptr, &outbytesleft);
|
||||
if (inbytesleft > 0 || res == (size_t)(-1)
|
||||
/* Irix iconv() inserts a NUL byte if it cannot convert. */
|
||||
# if !defined _LIBICONV_VERSION && (defined sgi || defined __sgi)
|
||||
|| (res > 0 && code != 0 && outptr - outbuf == 1 && *outbuf == '\0')
|
||||
# endif
|
||||
)
|
||||
return failure (code, NULL, callback_arg);
|
||||
|
||||
/* Avoid glibc-2.1 bug and Solaris 2.7 bug. */
|
||||
# if defined _LIBICONV_VERSION \
|
||||
|| !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun)
|
||||
|
||||
/* Get back to the initial shift state. */
|
||||
res = iconv (utf8_to_local, NULL, NULL, &outptr, &outbytesleft);
|
||||
if (res == (size_t)(-1))
|
||||
return failure (code, NULL, callback_arg);
|
||||
# endif
|
||||
|
||||
return success (outbuf, outptr - outbuf, callback_arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* At this point, is_utf8 is true, so no conversion is needed. */
|
||||
return success (inbuf, count, callback_arg);
|
||||
}
|
||||
|
||||
/* Simple success callback that outputs the converted string.
|
||||
The STREAM is passed as callback_arg. */
|
||||
long
|
||||
fwrite_success_callback (const char *buf, size_t buflen, void *callback_arg)
|
||||
{
|
||||
FILE *stream = (FILE *) callback_arg;
|
||||
|
||||
fwrite (buf, 1, buflen, stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Simple failure callback that displays an error and exits. */
|
||||
static long
|
||||
exit_failure_callback (unsigned int code, const char *msg, void *callback_arg)
|
||||
{
|
||||
if (msg == NULL)
|
||||
error (1, 0, _("cannot convert U+%04X to local character set"), code);
|
||||
else
|
||||
error (1, 0, _("cannot convert U+%04X to local character set: %s"), code,
|
||||
gettext (msg));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Simple failure callback that displays a fallback representation in plain
|
||||
ASCII, using the same notation as ISO C99 strings. */
|
||||
static long
|
||||
fallback_failure_callback (unsigned int code, const char *msg, void *callback_arg)
|
||||
{
|
||||
FILE *stream = (FILE *) callback_arg;
|
||||
|
||||
if (code < 0x10000)
|
||||
fprintf (stream, "\\u%04X", code);
|
||||
else
|
||||
fprintf (stream, "\\U%08X", code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Outputs the Unicode character CODE to the output stream STREAM.
|
||||
Upon failure, exit if exit_on_error is true, otherwise output a fallback
|
||||
notation. */
|
||||
void
|
||||
print_unicode_char (FILE *stream, unsigned int code, int exit_on_error)
|
||||
{
|
||||
unicode_to_mb (code, fwrite_success_callback,
|
||||
exit_on_error
|
||||
? exit_failure_callback
|
||||
: fallback_failure_callback,
|
||||
stream);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/* Unicode character output to streams with locale dependent encoding.
|
||||
|
||||
Copyright (C) 2000-2002 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library 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 UNICODEIO_H
|
||||
# define UNICODEIO_H
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
# ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* Outputs the Unicode character CODE to the output stream STREAM.
|
||||
Upon failure, exit if exit_on_error is true, otherwise output a fallback
|
||||
notation. */
|
||||
extern void print_unicode_char PARAMS ((FILE *stream, unsigned int code,
|
||||
int exit_on_error));
|
||||
|
||||
/* Simple success callback that outputs the converted string.
|
||||
The STREAM is passed as callback_arg. */
|
||||
extern long fwrite_success_callback PARAMS ((const char *buf, size_t buflen,
|
||||
void *callback_arg));
|
||||
|
||||
#endif
|
||||
@@ -1,75 +0,0 @@
|
||||
/* Emulate waitpid on systems that just have wait.
|
||||
Copyright 1994, 1995, 1998, 1999, 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 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#define WAITPID_CHILDREN 8
|
||||
static pid_t waited_pid[WAITPID_CHILDREN];
|
||||
static int waited_status[WAITPID_CHILDREN];
|
||||
|
||||
pid_t
|
||||
waitpid (pid_t pid, int *stat_loc, int options)
|
||||
{
|
||||
int i;
|
||||
pid_t p;
|
||||
|
||||
if (!options && (pid == -1 || 0 < pid))
|
||||
{
|
||||
/* If we have already waited for this child, return it immediately. */
|
||||
for (i = 0; i < WAITPID_CHILDREN; i++)
|
||||
{
|
||||
p = waited_pid[i];
|
||||
if (p && (p == pid || pid == -1))
|
||||
{
|
||||
waited_pid[i] = 0;
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
/* The child has not returned yet; wait for it, accumulating status. */
|
||||
for (i = 0; i < WAITPID_CHILDREN; i++)
|
||||
if (! waited_pid[i])
|
||||
{
|
||||
p = wait (&waited_status[i]);
|
||||
if (p < 0)
|
||||
return p;
|
||||
if (p == pid || pid == -1)
|
||||
goto success;
|
||||
waited_pid[i] = p;
|
||||
}
|
||||
}
|
||||
|
||||
/* We cannot emulate this wait call, e.g. because of too many children. */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
|
||||
success:
|
||||
if (stat_loc)
|
||||
*stat_loc = waited_status[i];
|
||||
return p;
|
||||
}
|
||||
87
lib/xalloc.h
87
lib/xalloc.h
@@ -1,87 +0,0 @@
|
||||
/* xalloc.h -- malloc with out-of-memory checking
|
||||
Copyright (C) 1990-1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef XALLOC_H_
|
||||
# define XALLOC_H_
|
||||
|
||||
# ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef __attribute__
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
|
||||
# define __attribute__(x)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef ATTRIBUTE_NORETURN
|
||||
# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
|
||||
# endif
|
||||
|
||||
/* Exit value when the requested amount of memory is not available.
|
||||
It is initialized to EXIT_FAILURE, but the caller may set it to
|
||||
some other value. */
|
||||
extern int xalloc_exit_failure;
|
||||
|
||||
/* If this pointer is non-zero, run the specified function upon each
|
||||
allocation failure. It is initialized to zero. */
|
||||
extern void (*xalloc_fail_func) PARAMS ((void));
|
||||
|
||||
/* If XALLOC_FAIL_FUNC is undefined or a function that returns, this
|
||||
message is output. It is translated via gettext.
|
||||
Its value is "memory exhausted". */
|
||||
extern char const xalloc_msg_memory_exhausted[];
|
||||
|
||||
/* This function is always triggered when memory is exhausted. It is
|
||||
in charge of honoring the three previous items. This is the
|
||||
function to call when one wants the program to die because of a
|
||||
memory allocation failure. */
|
||||
extern void xalloc_die PARAMS ((void)) ATTRIBUTE_NORETURN;
|
||||
|
||||
void *xmalloc PARAMS ((size_t n));
|
||||
void *xcalloc PARAMS ((size_t n, size_t s));
|
||||
void *xrealloc PARAMS ((void *p, size_t n));
|
||||
char *xstrdup PARAMS ((const char *str));
|
||||
|
||||
# define XMALLOC(Type, N_items) ((Type *) xmalloc (sizeof (Type) * (N_items)))
|
||||
# define XCALLOC(Type, N_items) ((Type *) xcalloc (sizeof (Type), (N_items)))
|
||||
# define XREALLOC(Ptr, Type, N_items) \
|
||||
((Type *) xrealloc ((void *) (Ptr), sizeof (Type) * (N_items)))
|
||||
|
||||
/* Declare and alloc memory for VAR of type TYPE. */
|
||||
# define NEW(Type, Var) Type *(Var) = XMALLOC (Type, 1)
|
||||
|
||||
/* Free VAR only if non NULL. */
|
||||
# define XFREE(Var) \
|
||||
do { \
|
||||
if (Var) \
|
||||
free (Var); \
|
||||
} while (0)
|
||||
|
||||
/* Return a pointer to a malloc'ed copy of the array SRC of NUM elements. */
|
||||
# define CCLONE(Src, Num) \
|
||||
(memcpy (xmalloc (sizeof (*Src) * (Num)), (Src), sizeof (*Src) * (Num)))
|
||||
|
||||
/* Return a malloc'ed copy of SRC. */
|
||||
# define CLONE(Src) CCLONE (Src, 1)
|
||||
|
||||
|
||||
#endif /* !XALLOC_H_ */
|
||||
@@ -1,79 +0,0 @@
|
||||
/* xgetcwd.c -- return current directory with unlimited length
|
||||
Copyright (C) 1992, 1996, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_GETCWD
|
||||
char *getcwd ();
|
||||
#else
|
||||
char *getwd ();
|
||||
# define getcwd(Buf, Max) getwd (Buf)
|
||||
#endif
|
||||
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Return the current directory, newly allocated, arbitrarily long.
|
||||
Return NULL and set errno on error. */
|
||||
|
||||
char *
|
||||
xgetcwd ()
|
||||
{
|
||||
#if defined __GLIBC__ && __GLIBC__ >= 2
|
||||
return getcwd (NULL, 0);
|
||||
#else
|
||||
size_t buf_size = 128; /* must be a power of 2 */
|
||||
char *buf = NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *cwd;
|
||||
buf = (char *) xrealloc (buf, buf_size);
|
||||
|
||||
cwd = getcwd (buf, buf_size);
|
||||
if (cwd != NULL)
|
||||
return cwd;
|
||||
if (errno != ERANGE)
|
||||
{
|
||||
free (buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf_size *= 2;
|
||||
if (buf_size == 0)
|
||||
xalloc_die ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
116
lib/xmalloc.c
116
lib/xmalloc.c
@@ -1,116 +0,0 @@
|
||||
/* xmalloc.c -- malloc with out of memory checking
|
||||
Copyright (C) 1990-1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
void *calloc ();
|
||||
void *malloc ();
|
||||
void *realloc ();
|
||||
void free ();
|
||||
#endif
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(Text) gettext (Text)
|
||||
#else
|
||||
# define textdomain(Domain)
|
||||
# define _(Text) Text
|
||||
#endif
|
||||
#define N_(Text) Text
|
||||
|
||||
#include "error.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#ifndef EXIT_FAILURE
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DONE_WORKING_MALLOC_CHECK
|
||||
"you must run the autoconf test for a properly working malloc -- see malloc.m4"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DONE_WORKING_REALLOC_CHECK
|
||||
"you must run the autoconf test for a properly working realloc --see realloc.m4"
|
||||
#endif
|
||||
|
||||
/* Exit value when the requested amount of memory is not available.
|
||||
The caller may set it to some other value. */
|
||||
int xalloc_exit_failure = EXIT_FAILURE;
|
||||
|
||||
/* If non NULL, call this function when memory is exhausted. */
|
||||
void (*xalloc_fail_func) PARAMS ((void)) = 0;
|
||||
|
||||
/* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
|
||||
before exiting when memory is exhausted. Goes through gettext. */
|
||||
char const xalloc_msg_memory_exhausted[] = N_("memory exhausted");
|
||||
|
||||
void
|
||||
xalloc_die (void)
|
||||
{
|
||||
if (xalloc_fail_func)
|
||||
(*xalloc_fail_func) ();
|
||||
error (xalloc_exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));
|
||||
/* The `noreturn' cannot be given to error, since it may return if
|
||||
its first argument is 0. To help compilers understand the
|
||||
xalloc_die does terminate, call exit. */
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Allocate N bytes of memory dynamically, with error checking. */
|
||||
|
||||
void *
|
||||
xmalloc (size_t n)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = malloc (n);
|
||||
if (p == 0)
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Change the size of an allocated block of memory P to N bytes,
|
||||
with error checking. */
|
||||
|
||||
void *
|
||||
xrealloc (void *p, size_t n)
|
||||
{
|
||||
p = realloc (p, n);
|
||||
if (p == 0)
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Allocate memory for N elements of S bytes, with error checking. */
|
||||
|
||||
void *
|
||||
xcalloc (size_t n, size_t s)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = calloc (n, s);
|
||||
if (p == 0)
|
||||
xalloc_die ();
|
||||
return p;
|
||||
}
|
||||
288
lib/xstrtol.c
288
lib/xstrtol.c
@@ -1,288 +0,0 @@
|
||||
/* A more useful interface to strtol.
|
||||
Copyright (C) 1995, 1996, 1998-2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Jim Meyering. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef __strtol
|
||||
# define __strtol strtol
|
||||
# define __strtol_t long int
|
||||
# define __xstrtol xstrtol
|
||||
#endif
|
||||
|
||||
/* Some pre-ANSI implementations (e.g. SunOS 4)
|
||||
need stderr defined if assertion checking is enabled. */
|
||||
#include <stdio.h>
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
# ifndef strchr
|
||||
# define strchr index
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
/* The extra casts work around common compiler bugs. */
|
||||
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
|
||||
It is necessary at least when t == time_t. */
|
||||
#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
|
||||
? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
|
||||
#define TYPE_MAXIMUM(t) (~ (t) 0 - TYPE_MINIMUM (t))
|
||||
|
||||
#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
|
||||
# define IN_CTYPE_DOMAIN(c) 1
|
||||
#else
|
||||
# define IN_CTYPE_DOMAIN(c) isascii(c)
|
||||
#endif
|
||||
|
||||
#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
|
||||
|
||||
#include "xstrtol.h"
|
||||
|
||||
#if !HAVE_DECL_STRTOL && !defined strtol
|
||||
long int strtol ();
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_STRTOUL && !defined strtoul
|
||||
unsigned long int strtoul ();
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_STRTOIMAX && !defined strtoimax
|
||||
intmax_t strtoimax ();
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_STRTOUMAX && !defined strtoumax
|
||||
uintmax_t strtoumax ();
|
||||
#endif
|
||||
|
||||
static int
|
||||
bkm_scale (__strtol_t *x, int scale_factor)
|
||||
{
|
||||
__strtol_t product = *x * scale_factor;
|
||||
if (*x != product / scale_factor)
|
||||
return 1;
|
||||
*x = product;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bkm_scale_by_power (__strtol_t *x, int base, int power)
|
||||
{
|
||||
while (power--)
|
||||
if (bkm_scale (x, base))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: comment. */
|
||||
|
||||
strtol_error
|
||||
__xstrtol (const char *s, char **ptr, int strtol_base,
|
||||
__strtol_t *val, const char *valid_suffixes)
|
||||
{
|
||||
char *t_ptr;
|
||||
char **p;
|
||||
__strtol_t tmp;
|
||||
|
||||
assert (0 <= strtol_base && strtol_base <= 36);
|
||||
|
||||
p = (ptr ? ptr : &t_ptr);
|
||||
|
||||
if (! TYPE_SIGNED (__strtol_t))
|
||||
{
|
||||
const char *q = s;
|
||||
while (ISSPACE ((unsigned char) *q))
|
||||
++q;
|
||||
if (*q == '-')
|
||||
return LONGINT_INVALID;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
tmp = __strtol (s, p, strtol_base);
|
||||
if (errno != 0)
|
||||
return LONGINT_OVERFLOW;
|
||||
if (*p == s)
|
||||
return LONGINT_INVALID;
|
||||
|
||||
/* Let valid_suffixes == NULL mean `allow any suffix'. */
|
||||
/* FIXME: update all callers except the ones that allow suffixes
|
||||
after the number, changing last parameter NULL to `""'. */
|
||||
if (!valid_suffixes)
|
||||
{
|
||||
*val = tmp;
|
||||
return LONGINT_OK;
|
||||
}
|
||||
|
||||
if (**p != '\0')
|
||||
{
|
||||
int base = 1024;
|
||||
int suffixes = 1;
|
||||
int overflow;
|
||||
|
||||
if (!strchr (valid_suffixes, **p))
|
||||
{
|
||||
*val = tmp;
|
||||
return LONGINT_INVALID_SUFFIX_CHAR;
|
||||
}
|
||||
|
||||
if (strchr (valid_suffixes, '0'))
|
||||
{
|
||||
/* The ``valid suffix'' '0' is a special flag meaning that
|
||||
an optional second suffix is allowed, which can change
|
||||
the base, e.g. "100MD" for 100 megabytes decimal. */
|
||||
|
||||
switch (p[0][1])
|
||||
{
|
||||
case 'B':
|
||||
suffixes++;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
base = 1000;
|
||||
suffixes++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (**p)
|
||||
{
|
||||
case 'b':
|
||||
overflow = bkm_scale (&tmp, 512);
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
overflow = bkm_scale (&tmp, 1024);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
overflow = 0;
|
||||
break;
|
||||
|
||||
case 'E': /* Exa */
|
||||
overflow = bkm_scale_by_power (&tmp, base, 6);
|
||||
break;
|
||||
|
||||
case 'G': /* Giga */
|
||||
case 'g': /* 'g' is undocumented; for compatibility only */
|
||||
overflow = bkm_scale_by_power (&tmp, base, 3);
|
||||
break;
|
||||
|
||||
case 'k': /* kilo */
|
||||
overflow = bkm_scale_by_power (&tmp, base, 1);
|
||||
break;
|
||||
|
||||
case 'M': /* Mega */
|
||||
case 'm': /* 'm' is undocumented; for compatibility only */
|
||||
overflow = bkm_scale_by_power (&tmp, base, 2);
|
||||
break;
|
||||
|
||||
case 'P': /* Peta */
|
||||
overflow = bkm_scale_by_power (&tmp, base, 5);
|
||||
break;
|
||||
|
||||
case 'T': /* Tera */
|
||||
case 't': /* 't' is undocumented; for compatibility only */
|
||||
overflow = bkm_scale_by_power (&tmp, base, 4);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
overflow = bkm_scale (&tmp, 2);
|
||||
break;
|
||||
|
||||
case 'Y': /* Yotta */
|
||||
overflow = bkm_scale_by_power (&tmp, base, 8);
|
||||
break;
|
||||
|
||||
case 'Z': /* Zetta */
|
||||
overflow = bkm_scale_by_power (&tmp, base, 7);
|
||||
break;
|
||||
|
||||
default:
|
||||
*val = tmp;
|
||||
return LONGINT_INVALID_SUFFIX_CHAR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (overflow)
|
||||
return LONGINT_OVERFLOW;
|
||||
|
||||
(*p) += suffixes;
|
||||
}
|
||||
|
||||
*val = tmp;
|
||||
return LONGINT_OK;
|
||||
}
|
||||
|
||||
#ifdef TESTING_XSTRTO
|
||||
|
||||
# include <stdio.h>
|
||||
# include "error.h"
|
||||
|
||||
char *program_name;
|
||||
|
||||
int
|
||||
main (int argc, char** argv)
|
||||
{
|
||||
strtol_error s_err;
|
||||
int i;
|
||||
|
||||
program_name = argv[0];
|
||||
for (i=1; i<argc; i++)
|
||||
{
|
||||
char *p;
|
||||
__strtol_t val;
|
||||
|
||||
s_err = __xstrtol (argv[i], &p, 0, &val, "bckmw");
|
||||
if (s_err == LONGINT_OK)
|
||||
{
|
||||
printf ("%s->%lu (%s)\n", argv[i], val, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
STRTOL_FATAL_ERROR (argv[i], "arg", s_err);
|
||||
}
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TESTING_XSTRTO */
|
||||
@@ -1,82 +0,0 @@
|
||||
/* A more useful interface to strtol.
|
||||
Copyright 1995, 1996, 1998, 1999, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef XSTRTOL_H_
|
||||
# define XSTRTOL_H_ 1
|
||||
|
||||
# if HAVE_INTTYPES_H
|
||||
# include <inttypes.h> /* for uintmax_t */
|
||||
# endif
|
||||
|
||||
# ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef _STRTOL_ERROR
|
||||
enum strtol_error
|
||||
{
|
||||
LONGINT_OK, LONGINT_INVALID, LONGINT_INVALID_SUFFIX_CHAR, LONGINT_OVERFLOW
|
||||
};
|
||||
typedef enum strtol_error strtol_error;
|
||||
# endif
|
||||
|
||||
# define _DECLARE_XSTRTOL(name, type) \
|
||||
strtol_error \
|
||||
name PARAMS ((const char *s, char **ptr, int base, \
|
||||
type *val, const char *valid_suffixes));
|
||||
_DECLARE_XSTRTOL (xstrtol, long int)
|
||||
_DECLARE_XSTRTOL (xstrtoul, unsigned long int)
|
||||
_DECLARE_XSTRTOL (xstrtoimax, intmax_t)
|
||||
_DECLARE_XSTRTOL (xstrtoumax, uintmax_t)
|
||||
|
||||
# define _STRTOL_ERROR(Exit_code, Str, Argument_type_string, Err) \
|
||||
do \
|
||||
{ \
|
||||
switch ((Err)) \
|
||||
{ \
|
||||
case LONGINT_OK: \
|
||||
abort (); \
|
||||
\
|
||||
case LONGINT_INVALID: \
|
||||
error ((Exit_code), 0, "invalid %s `%s'", \
|
||||
(Argument_type_string), (Str)); \
|
||||
break; \
|
||||
\
|
||||
case LONGINT_INVALID_SUFFIX_CHAR: \
|
||||
error ((Exit_code), 0, "invalid character following %s in `%s'", \
|
||||
(Argument_type_string), (Str)); \
|
||||
break; \
|
||||
\
|
||||
case LONGINT_OVERFLOW: \
|
||||
error ((Exit_code), 0, "%s `%s' too large", \
|
||||
(Argument_type_string), (Str)); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
# define STRTOL_FATAL_ERROR(Str, Argument_type_string, Err) \
|
||||
_STRTOL_ERROR (2, Str, Argument_type_string, Err)
|
||||
|
||||
# define STRTOL_FAIL_WARN(Str, Argument_type_string, Err) \
|
||||
_STRTOL_ERROR (0, Str, Argument_type_string, Err)
|
||||
|
||||
#endif /* not XSTRTOL_H_ */
|
||||
23
m4/c-bs-a.m4
23
m4/c-bs-a.m4
@@ -1,23 +0,0 @@
|
||||
#serial 4
|
||||
|
||||
dnl From Paul Eggert.
|
||||
|
||||
AC_DEFUN([AC_C_BACKSLASH_A],
|
||||
[
|
||||
AC_CACHE_CHECK([whether backslash-a works in strings], ac_cv_c_backslash_a,
|
||||
[AC_TRY_COMPILE([],
|
||||
[
|
||||
#if '\a' == 'a'
|
||||
syntax error;
|
||||
#endif
|
||||
char buf['\a' == 'a' ? -1 : 1];
|
||||
buf[0] = '\a';
|
||||
return buf[0] != "\a"[0];
|
||||
],
|
||||
ac_cv_c_backslash_a=yes,
|
||||
ac_cv_c_backslash_a=no)])
|
||||
if test $ac_cv_c_backslash_a = yes; then
|
||||
AC_DEFINE(HAVE_C_BACKSLASH_A, 1,
|
||||
[Define if backslash-a works in C strings.])
|
||||
fi
|
||||
])
|
||||
95
m4/ccstdc.m4
95
m4/ccstdc.m4
@@ -1,95 +0,0 @@
|
||||
# The following is taken from automake 1.4,
|
||||
# except that it prefers the compiler option -Ae to "-Aa -D_HPUX_SOURCE"
|
||||
# because only the former supports 64-bit integral types on HP-UX 10.20.
|
||||
|
||||
## ----------------------------------------- ##
|
||||
## ANSIfy the C compiler whenever possible. ##
|
||||
## From Franc,ois Pinard ##
|
||||
## ----------------------------------------- ##
|
||||
|
||||
# serial 2
|
||||
|
||||
# @defmac AC_PROG_CC_STDC
|
||||
# @maindex PROG_CC_STDC
|
||||
# @ovindex CC
|
||||
# If the C compiler in not in ANSI C mode by default, try to add an option
|
||||
# to output variable @code{CC} to make it so. This macro tries various
|
||||
# options that select ANSI C on some system or another. It considers the
|
||||
# compiler to be in ANSI C mode if it handles function prototypes correctly.
|
||||
#
|
||||
# If you use this macro, you should check after calling it whether the C
|
||||
# compiler has been set to accept ANSI C; if not, the shell variable
|
||||
# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
|
||||
# code in ANSI C, you can make an un-ANSIfied copy of it by using the
|
||||
# program @code{ansi2knr}, which comes with Ghostscript.
|
||||
# @end defmac
|
||||
|
||||
AC_DEFUN(AM_PROG_CC_STDC,
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_BEFORE([$0], [AC_C_INLINE])
|
||||
AC_BEFORE([$0], [AC_C_CONST])
|
||||
dnl Force this before AC_PROG_CPP. Some cpp's, eg on HPUX, require
|
||||
dnl a magic option to avoid problems with ANSI preprocessor commands
|
||||
dnl like #elif.
|
||||
dnl FIXME: can't do this because then AC_AIX won't work due to a
|
||||
dnl circular dependency.
|
||||
dnl AC_BEFORE([$0], [AC_PROG_CPP])
|
||||
AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
|
||||
AC_CACHE_VAL(am_cv_prog_cc_stdc,
|
||||
[am_cv_prog_cc_stdc=no
|
||||
ac_save_CC="$CC"
|
||||
# Don't try gcc -ansi; that turns off useful extensions and
|
||||
# breaks some systems' header files.
|
||||
# AIX -qlanglvl=ansi
|
||||
# Ultrix and OSF/1 -std1
|
||||
# HP-UX -Aa -D_HPUX_SOURCE
|
||||
# SVR4 -Xc -D__EXTENSIONS__
|
||||
for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
|
||||
do
|
||||
CC="$ac_save_CC $ac_arg"
|
||||
AC_TRY_COMPILE(
|
||||
[#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
|
||||
struct buf { int x; };
|
||||
FILE * (*rcsopen) (struct buf *, struct stat *, int);
|
||||
static char *e (p, i)
|
||||
char **p;
|
||||
int i;
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
static char *f (char * (*g) (char **, int), char **p, ...)
|
||||
{
|
||||
char *s;
|
||||
va_list v;
|
||||
va_start (v,p);
|
||||
s = g (p, va_arg (v,int));
|
||||
va_end (v);
|
||||
return s;
|
||||
}
|
||||
int test (int i, double x);
|
||||
struct s1 {int (*f) (int a);};
|
||||
struct s2 {int (*f) (double a);};
|
||||
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
|
||||
int argc;
|
||||
char **argv;
|
||||
], [
|
||||
return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
|
||||
],
|
||||
[am_cv_prog_cc_stdc="$ac_arg"; break])
|
||||
done
|
||||
CC="$ac_save_CC"
|
||||
])
|
||||
if test -z "$am_cv_prog_cc_stdc"; then
|
||||
AC_MSG_RESULT([none needed])
|
||||
else
|
||||
AC_MSG_RESULT($am_cv_prog_cc_stdc)
|
||||
fi
|
||||
case "x$am_cv_prog_cc_stdc" in
|
||||
x|xno) ;;
|
||||
*) CC="$CC $am_cv_prog_cc_stdc" ;;
|
||||
esac
|
||||
])
|
||||
37
m4/decl.m4
37
m4/decl.m4
@@ -1,37 +0,0 @@
|
||||
#serial 5
|
||||
|
||||
AC_DEFUN(jm_CHECK_DECLARATION,
|
||||
[
|
||||
AC_MSG_CHECKING([whether $1 is declared])
|
||||
AC_CACHE_VAL(jm_cv_func_decl_$1,
|
||||
[AC_TRY_COMPILE($2,
|
||||
[
|
||||
#ifndef $1
|
||||
char *(*pfn) = (char *(*)) $1
|
||||
#endif
|
||||
],
|
||||
eval "jm_cv_func_decl_$1=yes",
|
||||
eval "jm_cv_func_decl_$1=no")])
|
||||
|
||||
if eval "test \"`echo '$jm_cv_func_decl_'$1`\" = yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$3], , :, [$3])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
ifelse([$4], , , [$4
|
||||
])dnl
|
||||
fi
|
||||
])dnl
|
||||
|
||||
dnl jm_CHECK_DECLARATIONS(INCLUDES, FUNCTION... [, ACTION-IF-DECLARED
|
||||
dnl [, ACTION-IF-NOT-DECLARED]])
|
||||
AC_DEFUN(jm_CHECK_DECLARATIONS,
|
||||
[
|
||||
for jm_func in $2
|
||||
do
|
||||
jm_CHECK_DECLARATION($jm_func, $1,
|
||||
[
|
||||
jm_tr_func=HAVE_DECL_`echo $jm_func | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
|
||||
AC_DEFINE_UNQUOTED($jm_tr_func) $3], $4)dnl
|
||||
done
|
||||
])
|
||||
12
m4/error.m4
12
m4/error.m4
@@ -1,12 +0,0 @@
|
||||
#serial 3
|
||||
|
||||
dnl FIXME: put these prerequisite-only *.m4 files in a separate
|
||||
dnl directory -- otherwise, they'll conflict with existing files.
|
||||
|
||||
dnl These are the prerequisite macros for GNU's error.c file.
|
||||
AC_DEFUN([jm_PREREQ_ERROR],
|
||||
[
|
||||
AC_CHECK_FUNCS(strerror strerror_r vprintf doprnt)
|
||||
AC_FUNC_STRERROR_R
|
||||
AC_HEADER_STDC
|
||||
])
|
||||
@@ -1,24 +0,0 @@
|
||||
dnl This is a copy of autoconf 2.13, except we also check that
|
||||
dnl FNM_FILE_NAME | FNM_LEADING_DIR works.
|
||||
dnl
|
||||
undefine([AC_FUNC_FNMATCH])
|
||||
AC_DEFUN(AC_FUNC_FNMATCH,
|
||||
[AC_CACHE_CHECK(for working GNU-style fnmatch, ac_cv_func_fnmatch_works,
|
||||
# Some versions of Solaris, SCO, and the GNU C Library
|
||||
# have a broken or incompatible fnmatch.
|
||||
# So we run a test program. If we are cross-compiling, take no chance.
|
||||
# Thanks to John Oleynick, Franc,ois Pinard, and Paul Eggert for this test.
|
||||
[AC_TRY_RUN([#include <fnmatch.h>
|
||||
main() {
|
||||
exit (fnmatch ("a*", "abc", 0) != 0
|
||||
|| fnmatch("d*/*1", "d/s/1", FNM_FILE_NAME) != FNM_NOMATCH
|
||||
|| fnmatch("*", "x", FNM_FILE_NAME | FNM_LEADING_DIR) != 0
|
||||
|| fnmatch("x*", "x/y/z", FNM_FILE_NAME | FNM_LEADING_DIR) != 0
|
||||
|| fnmatch("*c*", "c/x", FNM_FILE_NAME | FNM_LEADING_DIR) != 0);
|
||||
}],
|
||||
ac_cv_func_fnmatch_works=yes, ac_cv_func_fnmatch_works=no,
|
||||
ac_cv_func_fnmatch_works=no)])
|
||||
if test $ac_cv_func_fnmatch_works = yes; then
|
||||
AC_DEFINE(HAVE_FNMATCH)
|
||||
fi
|
||||
])
|
||||
53
m4/getcwd.m4
53
m4/getcwd.m4
@@ -1,53 +0,0 @@
|
||||
# getcwd.m4 - check whether getcwd (NULL, 0) allocates memory for result
|
||||
|
||||
# Copyright 2001 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
# Written by Paul Eggert.
|
||||
|
||||
AC_DEFUN([AC_FUNC_GETCWD_NULL],
|
||||
[AC_CHECK_HEADERS(stdlib.h unistd.h)
|
||||
AC_CACHE_CHECK([whether getcwd (NULL, 0) allocates memory for result],
|
||||
[ac_cv_func_getcwd_null],
|
||||
[AC_TRY_RUN(
|
||||
[
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
# ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# ifndef getcwd
|
||||
char *getcwd ();
|
||||
# endif
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (chdir ("/") != 0)
|
||||
exit (1);
|
||||
else
|
||||
{
|
||||
char *f = getcwd (NULL, 0);
|
||||
exit (! (f && f[0] == '/' && !f[1]));
|
||||
}
|
||||
}],
|
||||
[ac_cv_func_getcwd_null=yes],
|
||||
[ac_cv_func_getcwd_null=no],
|
||||
[ac_cv_func_getcwd_null=no])])
|
||||
if test $ac_cv_func_getcwd_null = yes; then
|
||||
AC_DEFINE(HAVE_GETCWD_NULL, 1,
|
||||
[Define if getcwd (NULL, 0) allocates memory for result.])
|
||||
fi])
|
||||
368
m4/gettext.m4
368
m4/gettext.m4
@@ -1,368 +0,0 @@
|
||||
# Macro to add for using GNU gettext.
|
||||
# Ulrich Drepper <drepper@cygnus.com>, 1995.
|
||||
#
|
||||
# This file can be copied and used freely without restrictions. It can
|
||||
# be used in projects which are not available under the GNU General Public
|
||||
# License but which still want to provide support for the GNU gettext
|
||||
# functionality.
|
||||
# Please note that the actual code of GNU gettext is covered by the GNU
|
||||
# General Public License and is *not* in the public domain.
|
||||
|
||||
# serial 10
|
||||
|
||||
dnl Usage: AM_WITH_NLS([TOOLSYMBOL], [NEEDSYMBOL], [LIBDIR]).
|
||||
dnl If TOOLSYMBOL is specified and is 'use-libtool', then a libtool library
|
||||
dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static,
|
||||
dnl depending on --{enable,disable}-{shared,static} and on the presence of
|
||||
dnl AM-DISABLE-SHARED). Otherwise, a static library
|
||||
dnl $(top_builddir)/intl/libintl.a will be created.
|
||||
dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext
|
||||
dnl implementations (in libc or libintl) without the ngettext() function
|
||||
dnl will be ignored.
|
||||
dnl LIBDIR is used to find the intl libraries. If empty,
|
||||
dnl the value `$(top_builddir)/intl/' is used.
|
||||
dnl
|
||||
dnl The result of the configuration is one of three cases:
|
||||
dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled
|
||||
dnl and used.
|
||||
dnl Catalog format: GNU --> install in $(datadir)
|
||||
dnl Catalog extension: .mo after installation, .gmo in source tree
|
||||
dnl 2) GNU gettext has been found in the system's C library.
|
||||
dnl Catalog format: GNU --> install in $(datadir)
|
||||
dnl Catalog extension: .mo after installation, .gmo in source tree
|
||||
dnl 3) No internationalization, always use English msgid.
|
||||
dnl Catalog format: none
|
||||
dnl Catalog extension: none
|
||||
dnl The use of .gmo is historical (it was needed to avoid overwriting the
|
||||
dnl GNU format catalogs when building on a platform with an X/Open gettext),
|
||||
dnl but we keep it in order not to force irrelevant filename changes on the
|
||||
dnl maintainers.
|
||||
dnl
|
||||
AC_DEFUN([AM_WITH_NLS],
|
||||
[AC_MSG_CHECKING([whether NLS is requested])
|
||||
dnl Default is enabled NLS
|
||||
AC_ARG_ENABLE(nls,
|
||||
[ --disable-nls do not use Native Language Support],
|
||||
USE_NLS=$enableval, USE_NLS=yes)
|
||||
AC_MSG_RESULT($USE_NLS)
|
||||
AC_SUBST(USE_NLS)
|
||||
|
||||
BUILD_INCLUDED_LIBINTL=no
|
||||
USE_INCLUDED_LIBINTL=no
|
||||
INTLLIBS=
|
||||
|
||||
dnl If we use NLS figure out what method
|
||||
if test "$USE_NLS" = "yes"; then
|
||||
AC_DEFINE(ENABLE_NLS, 1,
|
||||
[Define to 1 if translation of program messages to the user's native language
|
||||
is requested.])
|
||||
AC_MSG_CHECKING([whether included gettext is requested])
|
||||
AC_ARG_WITH(included-gettext,
|
||||
[ --with-included-gettext use the GNU gettext library included here],
|
||||
nls_cv_force_use_gnu_gettext=$withval,
|
||||
nls_cv_force_use_gnu_gettext=no)
|
||||
AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
|
||||
|
||||
nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
|
||||
if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
|
||||
dnl User does not insist on using GNU NLS library. Figure out what
|
||||
dnl to use. If GNU gettext is available we use this. Else we have
|
||||
dnl to fall back to GNU NLS library.
|
||||
CATOBJEXT=NONE
|
||||
|
||||
dnl Add a version number to the cache macros.
|
||||
define(gt_cv_func_gnugettext_libc, [gt_cv_func_gnugettext]ifelse([$2], need-ngettext, 2, 1)[_libc])
|
||||
define(gt_cv_func_gnugettext_libintl, [gt_cv_func_gnugettext]ifelse([$2], need-ngettext, 2, 1)[_libintl])
|
||||
|
||||
AC_CHECK_HEADER(libintl.h,
|
||||
[AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc,
|
||||
[AC_TRY_LINK([#include <libintl.h>
|
||||
extern int _nl_msg_cat_cntr;],
|
||||
[bindtextdomain ("", "");
|
||||
return (int) gettext ("")]ifelse([$2], need-ngettext, [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr],
|
||||
gt_cv_func_gnugettext_libc=yes,
|
||||
gt_cv_func_gnugettext_libc=no)])
|
||||
|
||||
if test "$gt_cv_func_gnugettext_libc" != "yes"; then
|
||||
AC_CACHE_CHECK([for GNU gettext in libintl],
|
||||
gt_cv_func_gnugettext_libintl,
|
||||
[gt_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS -lintl $LIBICONV"
|
||||
AC_TRY_LINK([#include <libintl.h>
|
||||
extern int _nl_msg_cat_cntr;],
|
||||
[bindtextdomain ("", "");
|
||||
return (int) gettext ("")]ifelse([$2], need-ngettext, [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr],
|
||||
gt_cv_func_gnugettext_libintl=yes,
|
||||
gt_cv_func_gnugettext_libintl=no)
|
||||
LIBS="$gt_save_LIBS"])
|
||||
fi
|
||||
|
||||
dnl If an already present or preinstalled GNU gettext() is found,
|
||||
dnl use it. But if this macro is used in GNU gettext, and GNU
|
||||
dnl gettext is already preinstalled in libintl, we update this
|
||||
dnl libintl. (Cf. the install rule in intl/Makefile.in.)
|
||||
if test "$gt_cv_func_gnugettext_libc" = "yes" \
|
||||
|| { test "$gt_cv_func_gnugettext_libintl" = "yes" \
|
||||
&& test "$PACKAGE" != gettext; }; then
|
||||
AC_DEFINE(HAVE_GETTEXT, 1,
|
||||
[Define if the GNU gettext() function is already present or preinstalled.])
|
||||
|
||||
if test "$gt_cv_func_gnugettext_libintl" = "yes"; then
|
||||
dnl If iconv() is in a separate libiconv library, then anyone
|
||||
dnl linking with libintl{.a,.so} also needs to link with
|
||||
dnl libiconv.
|
||||
INTLLIBS="-lintl $LIBICONV"
|
||||
fi
|
||||
|
||||
gt_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS $INTLLIBS"
|
||||
AC_CHECK_FUNCS(dcgettext)
|
||||
LIBS="$gt_save_LIBS"
|
||||
|
||||
dnl Search for GNU msgfmt in the PATH.
|
||||
AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
|
||||
[$ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1], :)
|
||||
AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
|
||||
|
||||
dnl Search for GNU xgettext in the PATH.
|
||||
AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
|
||||
[$ac_dir/$ac_word --omit-header /dev/null >/dev/null 2>&1], :)
|
||||
|
||||
CATOBJEXT=.gmo
|
||||
fi
|
||||
])
|
||||
|
||||
if test "$CATOBJEXT" = "NONE"; then
|
||||
dnl GNU gettext is not found in the C library.
|
||||
dnl Fall back on GNU gettext library.
|
||||
nls_cv_use_gnu_gettext=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||
dnl Mark actions used to generate GNU NLS library.
|
||||
INTLOBJS="\$(GETTOBJS)"
|
||||
AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
|
||||
[$ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1], :)
|
||||
AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
|
||||
AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
|
||||
[$ac_dir/$ac_word --omit-header /dev/null >/dev/null 2>&1], :)
|
||||
AC_SUBST(MSGFMT)
|
||||
BUILD_INCLUDED_LIBINTL=yes
|
||||
USE_INCLUDED_LIBINTL=yes
|
||||
CATOBJEXT=.gmo
|
||||
INTLLIBS="ifelse([$3],[],\$(top_builddir)/intl,[$3])/libintl.ifelse([$1], use-libtool, [l], [])a $LIBICONV"
|
||||
LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'`
|
||||
fi
|
||||
|
||||
dnl This could go away some day; the PATH_PROG_WITH_TEST already does it.
|
||||
dnl Test whether we really found GNU msgfmt.
|
||||
if test "$GMSGFMT" != ":"; then
|
||||
dnl If it is no GNU msgfmt we define it as : so that the
|
||||
dnl Makefiles still can work.
|
||||
if $GMSGFMT --statistics /dev/null >/dev/null 2>&1; then
|
||||
: ;
|
||||
else
|
||||
AC_MSG_RESULT(
|
||||
[found msgfmt program is not GNU msgfmt; ignore it])
|
||||
GMSGFMT=":"
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl This could go away some day; the PATH_PROG_WITH_TEST already does it.
|
||||
dnl Test whether we really found GNU xgettext.
|
||||
if test "$XGETTEXT" != ":"; then
|
||||
dnl If it is no GNU xgettext we define it as : so that the
|
||||
dnl Makefiles still can work.
|
||||
if $XGETTEXT --omit-header /dev/null >/dev/null 2>&1; then
|
||||
: ;
|
||||
else
|
||||
AC_MSG_RESULT(
|
||||
[found xgettext program is not GNU xgettext; ignore it])
|
||||
XGETTEXT=":"
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl We need to process the po/ directory.
|
||||
POSUB=po
|
||||
fi
|
||||
AC_OUTPUT_COMMANDS(
|
||||
[for ac_file in $CONFIG_FILES; do
|
||||
# Support "outfile[:infile[:infile...]]"
|
||||
case "$ac_file" in
|
||||
*:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
|
||||
esac
|
||||
# PO directories have a Makefile.in generated from Makefile.in.in.
|
||||
case "$ac_file" in */Makefile.in)
|
||||
# Adjust a relative srcdir.
|
||||
ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
|
||||
ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`"
|
||||
ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
|
||||
# In autoconf-2.13 it is called $ac_given_srcdir.
|
||||
# In autoconf-2.50 it is called $srcdir.
|
||||
test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
|
||||
case "$ac_given_srcdir" in
|
||||
.) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
|
||||
/*) top_srcdir="$ac_given_srcdir" ;;
|
||||
*) top_srcdir="$ac_dots$ac_given_srcdir" ;;
|
||||
esac
|
||||
if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then
|
||||
rm -f "$ac_dir/POTFILES"
|
||||
test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES"
|
||||
sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," -e "\$s/\(.*\) \\\\/\1/" < "$ac_given_srcdir/$ac_dir/POTFILES.in" > "$ac_dir/POTFILES"
|
||||
test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile"
|
||||
sed -e "/POTFILES =/r $ac_dir/POTFILES" "$ac_dir/Makefile.in" > "$ac_dir/Makefile"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done])
|
||||
|
||||
|
||||
dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL
|
||||
dnl to 'yes' because some of the testsuite requires it.
|
||||
if test "$PACKAGE" = gettext; then
|
||||
BUILD_INCLUDED_LIBINTL=yes
|
||||
fi
|
||||
|
||||
dnl intl/plural.c is generated from intl/plural.y. It requires bison,
|
||||
dnl because plural.y uses bison specific features. It requires at least
|
||||
dnl bison-1.26 because earlier versions generate a plural.c that doesn't
|
||||
dnl compile.
|
||||
dnl bison is only needed for the maintainer (who touches plural.y). But in
|
||||
dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put
|
||||
dnl the rule in general Makefile. Now, some people carelessly touch the
|
||||
dnl files or have a broken "make" program, hence the plural.c rule will
|
||||
dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not
|
||||
dnl present or too old.
|
||||
AC_CHECK_PROGS([INTLBISON], [bison])
|
||||
if test -z "$INTLBISON"; then
|
||||
ac_verc_fail=yes
|
||||
else
|
||||
dnl Found it, now check the version.
|
||||
AC_MSG_CHECKING([version of bison])
|
||||
changequote(<<,>>)dnl
|
||||
ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison .* \([0-9]*\.[0-9.]*\).*$/\1/p'`
|
||||
case $ac_prog_version in
|
||||
'') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
|
||||
1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*)
|
||||
changequote([,])dnl
|
||||
ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
|
||||
*) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
|
||||
esac
|
||||
AC_MSG_RESULT([$ac_prog_version])
|
||||
fi
|
||||
if test $ac_verc_fail = yes; then
|
||||
INTLBISON=:
|
||||
fi
|
||||
|
||||
dnl These rules are solely for the distribution goal. While doing this
|
||||
dnl we only have to keep exactly one list of the available catalogs
|
||||
dnl in configure.in.
|
||||
for lang in $ALL_LINGUAS; do
|
||||
GMOFILES="$GMOFILES $lang.gmo"
|
||||
POFILES="$POFILES $lang.po"
|
||||
done
|
||||
|
||||
dnl Make all variables we use known to autoconf.
|
||||
AC_SUBST(BUILD_INCLUDED_LIBINTL)
|
||||
AC_SUBST(USE_INCLUDED_LIBINTL)
|
||||
AC_SUBST(CATALOGS)
|
||||
AC_SUBST(CATOBJEXT)
|
||||
AC_SUBST(GMOFILES)
|
||||
AC_SUBST(INTLLIBS)
|
||||
AC_SUBST(INTLOBJS)
|
||||
AC_SUBST(POFILES)
|
||||
AC_SUBST(POSUB)
|
||||
|
||||
dnl For backward compatibility. Some configure.ins may be using this.
|
||||
nls_cv_header_intl=
|
||||
nls_cv_header_libgt=
|
||||
|
||||
dnl For backward compatibility. Some Makefiles may be using this.
|
||||
DATADIRNAME=share
|
||||
AC_SUBST(DATADIRNAME)
|
||||
|
||||
dnl For backward compatibility. Some Makefiles may be using this.
|
||||
INSTOBJEXT=.mo
|
||||
AC_SUBST(INSTOBJEXT)
|
||||
|
||||
dnl For backward compatibility. Some Makefiles may be using this.
|
||||
GENCAT=gencat
|
||||
AC_SUBST(GENCAT)
|
||||
])
|
||||
|
||||
dnl Usage: Just like AM_WITH_NLS, which see.
|
||||
AC_DEFUN([AM_GNU_GETTEXT],
|
||||
[AC_REQUIRE([AC_PROG_MAKE_SET])dnl
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
AC_REQUIRE([AC_PROG_RANLIB])dnl
|
||||
AC_REQUIRE([AC_ISC_POSIX])dnl
|
||||
AC_REQUIRE([AC_HEADER_STDC])dnl
|
||||
AC_REQUIRE([AC_C_CONST])dnl
|
||||
AC_REQUIRE([AC_C_INLINE])dnl
|
||||
AC_REQUIRE([AC_TYPE_OFF_T])dnl
|
||||
AC_REQUIRE([AC_TYPE_SIZE_T])dnl
|
||||
AC_REQUIRE([AC_FUNC_ALLOCA])dnl
|
||||
AC_REQUIRE([AC_FUNC_MMAP])dnl
|
||||
AC_REQUIRE([jm_GLIBC21])dnl
|
||||
|
||||
AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \
|
||||
stdlib.h string.h unistd.h sys/param.h])
|
||||
AC_CHECK_FUNCS([feof_unlocked fgets_unlocked getcwd getegid geteuid \
|
||||
getgid getuid mempcpy munmap putenv setenv setlocale stpcpy strchr strcasecmp \
|
||||
strdup strtoul tsearch __argz_count __argz_stringify __argz_next])
|
||||
|
||||
AM_ICONV
|
||||
AM_LANGINFO_CODESET
|
||||
AM_LC_MESSAGES
|
||||
AM_WITH_NLS([$1],[$2],[$3])
|
||||
|
||||
if test "x$CATOBJEXT" != "x"; then
|
||||
if test "x$ALL_LINGUAS" = "x"; then
|
||||
LINGUAS=
|
||||
else
|
||||
AC_MSG_CHECKING(for catalogs to be installed)
|
||||
NEW_LINGUAS=
|
||||
for presentlang in $ALL_LINGUAS; do
|
||||
useit=no
|
||||
for desiredlang in ${LINGUAS-$ALL_LINGUAS}; do
|
||||
# Use the presentlang catalog if desiredlang is
|
||||
# a. equal to presentlang, or
|
||||
# b. a variant of presentlang (because in this case,
|
||||
# presentlang can be used as a fallback for messages
|
||||
# which are not translated in the desiredlang catalog).
|
||||
case "$desiredlang" in
|
||||
"$presentlang"*) useit=yes;;
|
||||
esac
|
||||
done
|
||||
if test $useit = yes; then
|
||||
NEW_LINGUAS="$NEW_LINGUAS $presentlang"
|
||||
fi
|
||||
done
|
||||
LINGUAS=$NEW_LINGUAS
|
||||
AC_MSG_RESULT($LINGUAS)
|
||||
fi
|
||||
|
||||
dnl Construct list of names of catalog files to be constructed.
|
||||
if test -n "$LINGUAS"; then
|
||||
for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly
|
||||
dnl find the mkinstalldirs script in another subdir but $(top_srcdir).
|
||||
dnl Try to locate is.
|
||||
MKINSTALLDIRS=
|
||||
if test -n "$ac_aux_dir"; then
|
||||
MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs"
|
||||
fi
|
||||
if test -z "$MKINSTALLDIRS"; then
|
||||
MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
|
||||
fi
|
||||
AC_SUBST(MKINSTALLDIRS)
|
||||
|
||||
dnl Enable libtool support if the surrounding package wishes it.
|
||||
INTL_LIBTOOL_SUFFIX_PREFIX=ifelse([$1], use-libtool, [l], [])
|
||||
AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX)
|
||||
])
|
||||
@@ -1,32 +0,0 @@
|
||||
#serial 6
|
||||
|
||||
dnl From Paul Eggert.
|
||||
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
# Define intmax_t to long or long long if <inttypes.h> doesn't define.
|
||||
|
||||
AC_DEFUN([jm_AC_TYPE_INTMAX_T],
|
||||
[
|
||||
AC_REQUIRE([jm_AC_TYPE_LONG_LONG])
|
||||
AC_CHECK_TYPE(intmax_t, ,
|
||||
[test $ac_cv_type_long_long = yes \
|
||||
&& ac_type='long long' \
|
||||
|| ac_type='long'
|
||||
AC_DEFINE_UNQUOTED(intmax_t, $ac_type,
|
||||
[Define to widest signed type if <inttypes.h> doesn't define.])])
|
||||
])
|
||||
|
||||
# Define uintmax_t to unsigned long or unsigned long long
|
||||
# if <inttypes.h> doesn't define.
|
||||
|
||||
AC_DEFUN([jm_AC_TYPE_UINTMAX_T],
|
||||
[
|
||||
AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG])
|
||||
AC_CHECK_TYPE(uintmax_t, ,
|
||||
[test $ac_cv_type_unsigned_long_long = yes \
|
||||
&& ac_type='unsigned long long' \
|
||||
|| ac_type='unsigned long'
|
||||
AC_DEFINE_UNQUOTED(uintmax_t, $ac_type,
|
||||
[Define to widest unsigned type if <inttypes.h> doesn't define.])])
|
||||
])
|
||||
@@ -1,19 +0,0 @@
|
||||
#serial 1
|
||||
|
||||
dnl From Paul Eggert
|
||||
|
||||
AC_DEFUN(jm_FUNC_MBRTOWC,
|
||||
[
|
||||
AC_MSG_CHECKING([whether mbrtowc and mbstate_t are properly declared])
|
||||
AC_CACHE_VAL(jm_cv_func_mbrtowc,
|
||||
[AC_TRY_LINK(
|
||||
[#include <wchar.h>],
|
||||
[mbstate_t state; return ! (sizeof state && mbrtowc);],
|
||||
[jm_cv_func_mbrtowc=yes],
|
||||
[jm_cv_func_mbrtowc=no])])
|
||||
if test $jm_cv_func_mbrtowc = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_MBRTOWC, 1,
|
||||
[Define to 1 if mbrtowc and mbstate_t are properly declared.])
|
||||
fi
|
||||
])
|
||||
@@ -1,29 +0,0 @@
|
||||
# serial 9
|
||||
|
||||
# From Paul Eggert.
|
||||
|
||||
# BeOS 5 has <wchar.h> but does not define mbstate_t,
|
||||
# so you can't declare an object of that type.
|
||||
# Check for this incompatibility with Standard C.
|
||||
|
||||
# Include stdlib.h first, because otherwise this test would fail on Linux
|
||||
# (at least glibc-2.1.3) because the "_XOPEN_SOURCE 500" definition elicits
|
||||
# a syntax error in wchar.h due to the use of undefined __int32_t.
|
||||
|
||||
AC_DEFUN([AC_MBSTATE_T],
|
||||
[
|
||||
AC_CHECK_HEADERS(stdlib.h)
|
||||
|
||||
AC_CACHE_CHECK([for mbstate_t], ac_cv_type_mbstate_t,
|
||||
[AC_TRY_COMPILE([
|
||||
#if HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#include <wchar.h>],
|
||||
[mbstate_t x; return sizeof x;],
|
||||
ac_cv_type_mbstate_t=yes,
|
||||
ac_cv_type_mbstate_t=no)])
|
||||
if test $ac_cv_type_mbstate_t = no; then
|
||||
AC_DEFINE(mbstate_t, int,
|
||||
[Define to a type if <wchar.h> does not define.])
|
||||
fi])
|
||||
141
m4/prereq.m4
141
m4/prereq.m4
@@ -1,141 +0,0 @@
|
||||
#serial 21
|
||||
|
||||
dnl These are the prerequisite macros for files in the lib/
|
||||
dnl directories of the fileutils, sh-utils, and textutils packages.
|
||||
|
||||
AC_DEFUN([jm_PREREQ],
|
||||
[
|
||||
jm_PREREQ_ADDEXT
|
||||
jm_PREREQ_CANON_HOST
|
||||
jm_PREREQ_DIRNAME
|
||||
jm_PREREQ_ERROR
|
||||
jm_PREREQ_EXCLUDE
|
||||
jm_PREREQ_GETPAGESIZE
|
||||
jm_PREREQ_HASH
|
||||
jm_PREREQ_HUMAN
|
||||
jm_PREREQ_MBSWIDTH
|
||||
jm_PREREQ_MEMCHR
|
||||
jm_PREREQ_QUOTEARG
|
||||
jm_PREREQ_READUTMP
|
||||
jm_PREREQ_REGEX
|
||||
jm_PREREQ_TEMPNAME # called by mkstemp
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_ADDEXT],
|
||||
[
|
||||
dnl For addext.c.
|
||||
AC_SYS_LONG_FILE_NAMES
|
||||
AC_CHECK_FUNCS(pathconf)
|
||||
AC_CHECK_HEADERS(limits.h string.h unistd.h)
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_CANON_HOST],
|
||||
[
|
||||
dnl Add any libraries as early as possible.
|
||||
dnl In particular, inet_ntoa needs -lnsl at least on Solaris5.5.1,
|
||||
dnl so we have to add -lnsl to LIBS before checking for that function.
|
||||
AC_SEARCH_LIBS(gethostbyname, [inet nsl])
|
||||
|
||||
dnl These come from -lnsl on Solaris5.5.1.
|
||||
AC_CHECK_FUNCS(gethostbyname gethostbyaddr inet_ntoa)
|
||||
|
||||
AC_CHECK_FUNCS(gethostbyname gethostbyaddr inet_ntoa)
|
||||
AC_CHECK_HEADERS(unistd.h string.h netdb.h sys/socket.h \
|
||||
netinet/in.h arpa/inet.h)
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_DIRNAME],
|
||||
[
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(string.h)
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_EXCLUDE],
|
||||
[
|
||||
jm_FUNC_FNMATCH
|
||||
AC_CHECK_HEADERS(stdbool.h)
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_GETPAGESIZE],
|
||||
[
|
||||
AC_CHECK_FUNCS(getpagesize)
|
||||
AC_CHECK_HEADERS(OS.h unistd.h)
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_HASH],
|
||||
[
|
||||
AC_CHECK_HEADERS(stdlib.h stdbool.h)
|
||||
AC_REQUIRE([jm_CHECK_DECLS])
|
||||
])
|
||||
|
||||
# If you use human.c, you need the following files:
|
||||
# inttypes.m4 ulonglong.m4
|
||||
AC_DEFUN([jm_PREREQ_HUMAN],
|
||||
[
|
||||
AC_CHECK_HEADERS(limits.h stdlib.h string.h)
|
||||
AC_CHECK_DECLS([getenv])
|
||||
AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_MEMCHR],
|
||||
[
|
||||
AC_CHECK_HEADERS(limits.h stdlib.h bp-sym.h)
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_QUOTEARG],
|
||||
[
|
||||
AC_CHECK_FUNCS(isascii iswprint)
|
||||
jm_FUNC_MBRTOWC
|
||||
AC_CHECK_HEADERS(limits.h stddef.h stdlib.h string.h wchar.h wctype.h)
|
||||
AC_HEADER_STDC
|
||||
AC_C_BACKSLASH_A
|
||||
AC_MBSTATE_T
|
||||
AM_C_PROTOTYPES
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_READUTMP],
|
||||
[
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(string.h utmp.h utmpx.h sys/param.h)
|
||||
AC_CHECK_FUNCS(utmpname)
|
||||
AC_CHECK_FUNCS(utmpxname)
|
||||
AM_C_PROTOTYPES
|
||||
|
||||
if test $ac_cv_header_utmp_h = yes || test $ac_cv_header_utmpx_h = yes; then
|
||||
utmp_includes="\
|
||||
$ac_includes_default
|
||||
#ifdef HAVE_UTMPX_H
|
||||
# include <utmpx.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTMP_H
|
||||
# include <utmp.h>
|
||||
#endif
|
||||
"
|
||||
AC_CHECK_MEMBERS([struct utmpx.ut_user],,,[$utmp_includes])
|
||||
AC_CHECK_MEMBERS([struct utmp.ut_user],,,[$utmp_includes])
|
||||
AC_CHECK_MEMBERS([struct utmpx.ut_name],,,[$utmp_includes])
|
||||
AC_CHECK_MEMBERS([struct utmp.ut_name],,,[$utmp_includes])
|
||||
AC_CHECK_MEMBERS([struct utmpx.ut_type],,,[$utmp_includes])
|
||||
AC_CHECK_MEMBERS([struct utmp.ut_type],,,[$utmp_includes])
|
||||
AC_LIBOBJ(readutmp)
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_REGEX],
|
||||
[
|
||||
dnl FIXME: Maybe provide a btowc replacement someday: solaris-2.5.1 lacks it.
|
||||
dnl FIXME: Check for wctype and iswctype, and and add -lw if necessary
|
||||
dnl to get them.
|
||||
AC_CHECK_FUNCS(bzero bcopy isascii btowc)
|
||||
AC_CHECK_HEADERS(alloca.h libintl.h wctype.h wchar.h)
|
||||
AC_HEADER_STDC
|
||||
AC_FUNC_ALLOCA
|
||||
])
|
||||
|
||||
AC_DEFUN([jm_PREREQ_TEMPNAME],
|
||||
[
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_STAT
|
||||
AC_CHECK_HEADERS(fcntl.h sys/time.h stdint.h unistd.h)
|
||||
AC_CHECK_FUNCS(__secure_getenv gettimeofday)
|
||||
])
|
||||
@@ -1,66 +0,0 @@
|
||||
#serial 1002
|
||||
# Experimental replacement for the function in the latest CVS autoconf.
|
||||
# If the compile-test says strerror_r doesn't work, then resort to a
|
||||
# `run'-test that works on BeOS and segfaults on DEC Unix.
|
||||
# Use with the error.c file in ../lib.
|
||||
|
||||
undefine([AC_FUNC_STRERROR_R])
|
||||
|
||||
# AC_FUNC_STRERROR_R
|
||||
# ------------------
|
||||
AC_DEFUN([AC_FUNC_STRERROR_R],
|
||||
[AC_CHECK_DECLS([strerror_r])
|
||||
AC_CHECK_FUNCS([strerror_r])
|
||||
if test $ac_cv_func_strerror_r = yes; then
|
||||
AC_CHECK_HEADERS(string.h)
|
||||
AC_CACHE_CHECK([for working strerror_r],
|
||||
ac_cv_func_strerror_r_works,
|
||||
[
|
||||
AC_TRY_COMPILE(
|
||||
[
|
||||
# include <stdio.h>
|
||||
# if HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# endif
|
||||
],
|
||||
[
|
||||
char buf[100];
|
||||
char x = *strerror_r (0, buf, sizeof buf);
|
||||
],
|
||||
ac_cv_func_strerror_r_works=yes,
|
||||
ac_cv_func_strerror_r_works=no
|
||||
)
|
||||
if test $ac_cv_func_strerror_r_works = no; then
|
||||
# strerror_r seems not to work, but now we have to choose between
|
||||
# systems that have relatively inaccessible declarations for the
|
||||
# function. BeOS and DEC UNIX 4.0 fall in this category, but the
|
||||
# former has a strerror_r that returns char*, while the latter
|
||||
# has a strerror_r that returns `int'.
|
||||
# This test should segfault on the DEC system.
|
||||
AC_TRY_RUN(
|
||||
[
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
# include <ctype.h>
|
||||
|
||||
extern char *strerror_r ();
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
char buf[100];
|
||||
char x = *strerror_r (0, buf, sizeof buf);
|
||||
exit (!isalpha (x));
|
||||
}
|
||||
],
|
||||
ac_cv_func_strerror_r_works=yes,
|
||||
ac_cv_func_strerror_r_works=no,
|
||||
ac_cv_func_strerror_r_works=no)
|
||||
fi
|
||||
])
|
||||
if test $ac_cv_func_strerror_r_works = yes; then
|
||||
AC_DEFINE(HAVE_WORKING_STRERROR_R, 1,
|
||||
[Define to 1 if `strerror_r' returns a string.])
|
||||
fi
|
||||
fi
|
||||
])# AC_FUNC_STRERROR_R
|
||||
@@ -1,19 +0,0 @@
|
||||
#serial 6
|
||||
|
||||
dnl From Paul Eggert.
|
||||
|
||||
AC_PREREQ(2.50)
|
||||
|
||||
# Define uintmax_t to `unsigned long' or `unsigned long long'
|
||||
# if <inttypes.h> does not exist.
|
||||
|
||||
AC_DEFUN([jm_AC_TYPE_UINTMAX_T],
|
||||
[
|
||||
AC_CHECK_TYPE(uintmax_t, ,
|
||||
[AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG])
|
||||
test $ac_cv_type_unsigned_long_long = yes \
|
||||
&& ac_type='unsigned long long' \
|
||||
|| ac_type='unsigned long'
|
||||
AC_DEFINE_UNQUOTED(uintmax_t, $ac_type,
|
||||
[Define to the widest unsigned type if standard headers do not declare.])])
|
||||
])
|
||||
@@ -1,41 +0,0 @@
|
||||
#serial 2
|
||||
dnl Cloned from xstrtoumax.m4. Keep these files in sync.
|
||||
|
||||
# autoconf tests required for use of xstrtoimax.c
|
||||
|
||||
AC_DEFUN([jm_AC_PREREQ_XSTRTOIMAX],
|
||||
[
|
||||
AC_REQUIRE([jm_AC_TYPE_INTMAX_T])
|
||||
AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])
|
||||
AC_REQUIRE([jm_AC_TYPE_LONG_LONG])
|
||||
AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG])
|
||||
AC_CHECK_DECLS([strtol, strtoul, strtoll, strtoimax, strtoumax])
|
||||
AC_CHECK_HEADERS(limits.h stdlib.h inttypes.h)
|
||||
|
||||
AC_CACHE_CHECK([whether <inttypes.h> defines strtoimax as a macro],
|
||||
jm_cv_func_strtoimax_macro,
|
||||
AC_EGREP_CPP([inttypes_h_defines_strtoimax], [#include <inttypes.h>
|
||||
#ifdef strtoimax
|
||||
inttypes_h_defines_strtoimax
|
||||
#endif],
|
||||
jm_cv_func_strtoimax_macro=yes,
|
||||
jm_cv_func_strtoimax_macro=no))
|
||||
|
||||
if test "$jm_cv_func_strtoimax_macro" != yes; then
|
||||
AC_REPLACE_FUNCS(strtoimax)
|
||||
fi
|
||||
|
||||
dnl Only the replacement strtoimax invokes strtol and strtoll,
|
||||
dnl so we need the replacements only if strtoimax does not exist.
|
||||
case "$jm_cv_func_strtoimax_macro,$ac_cv_func_strtoimax" in
|
||||
no,no)
|
||||
AC_REPLACE_FUNCS(strtol)
|
||||
|
||||
dnl We don't need (and can't compile) the replacement strtoll
|
||||
dnl unless the type `long long' exists.
|
||||
if test "$ac_cv_type_long_long" = yes; then
|
||||
AC_REPLACE_FUNCS(strtoll)
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
])
|
||||
@@ -1,40 +0,0 @@
|
||||
#serial 4
|
||||
|
||||
# autoconf tests required for use of xstrtoumax.c
|
||||
|
||||
AC_DEFUN([jm_AC_PREREQ_XSTRTOUMAX],
|
||||
[
|
||||
AC_REQUIRE([jm_AC_TYPE_INTMAX_T])
|
||||
AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])
|
||||
AC_REQUIRE([jm_AC_TYPE_LONG_LONG])
|
||||
AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG])
|
||||
AC_CHECK_DECLS([strtol, strtoul, strtoull, strtoimax, strtoumax])
|
||||
AC_CHECK_HEADERS(limits.h stdlib.h inttypes.h)
|
||||
|
||||
AC_CACHE_CHECK([whether <inttypes.h> defines strtoumax as a macro],
|
||||
jm_cv_func_strtoumax_macro,
|
||||
AC_EGREP_CPP([inttypes_h_defines_strtoumax], [#include <inttypes.h>
|
||||
#ifdef strtoumax
|
||||
inttypes_h_defines_strtoumax
|
||||
#endif],
|
||||
jm_cv_func_strtoumax_macro=yes,
|
||||
jm_cv_func_strtoumax_macro=no))
|
||||
|
||||
if test "$jm_cv_func_strtoumax_macro" != yes; then
|
||||
AC_REPLACE_FUNCS(strtoumax)
|
||||
fi
|
||||
|
||||
dnl Only the replacement strtoumax invokes strtoul and strtoull,
|
||||
dnl so we need the replacements only if strtoumax does not exist.
|
||||
case "$jm_cv_func_strtoumax_macro,$ac_cv_func_strtoumax" in
|
||||
no,no)
|
||||
AC_REPLACE_FUNCS(strtoul)
|
||||
|
||||
dnl We don't need (and can't compile) the replacement strtoull
|
||||
dnl unless the type `unsigned long long' exists.
|
||||
if test "$ac_cv_type_unsigned_long_long" = yes; then
|
||||
AC_REPLACE_FUNCS(strtoull)
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
])
|
||||
22
po/.gitignore
vendored
Normal file
22
po/.gitignore
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
*.gmo
|
||||
*.mo
|
||||
*.po
|
||||
.reference
|
||||
LINGUAS
|
||||
Makefile
|
||||
Makefile.in
|
||||
Makefile.in.in
|
||||
Makevars
|
||||
Makevars.template
|
||||
POTFILES
|
||||
Rules-quot
|
||||
boldquot.sed
|
||||
en@boldquot.header
|
||||
en@quot.header
|
||||
insert-header.sed
|
||||
insert-header.sin
|
||||
quot.sed
|
||||
remove-potcdate.sed
|
||||
remove-potcdate.sin
|
||||
stamp-po
|
||||
tar.pot
|
||||
@@ -1,196 +0,0 @@
|
||||
# Makefile for program source directory in GNU NLS utilities package.
|
||||
# Copyright (C) 1995-1997, 2000, 2001 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
||||
#
|
||||
# This file can be copied and used freely without restrictions. It can
|
||||
# be used in projects which are not available under the GNU Public License
|
||||
# but which still want to provide support for the GNU gettext functionality.
|
||||
# Please note that the actual code is *not* freely available.
|
||||
|
||||
PACKAGE = @PACKAGE@
|
||||
VERSION = @VERSION@
|
||||
|
||||
# These two variables depend on the location of this directory.
|
||||
subdir = po
|
||||
top_builddir = ..
|
||||
|
||||
SHELL = /bin/sh
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
datadir = @datadir@
|
||||
localedir = $(datadir)/locale
|
||||
gettextsrcdir = $(datadir)/gettext/po
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
MKINSTALLDIRS = @MKINSTALLDIRS@
|
||||
mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac`
|
||||
|
||||
CC = @CC@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
MSGFMT = @MSGFMT@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
MSGMERGE = msgmerge
|
||||
|
||||
DEFS = @DEFS@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
|
||||
INCLUDES = -I.. -I$(top_srcdir)/intl
|
||||
|
||||
COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
|
||||
|
||||
POFILES = @POFILES@
|
||||
GMOFILES = @GMOFILES@
|
||||
DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \
|
||||
$(POFILES) $(GMOFILES)
|
||||
|
||||
POTFILES = \
|
||||
|
||||
CATALOGS = @CATALOGS@
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .po .pox .gmo .mo
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) $<
|
||||
|
||||
.po.pox:
|
||||
$(MAKE) $(PACKAGE).pot
|
||||
$(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox
|
||||
|
||||
.po.mo:
|
||||
$(MSGFMT) -o $@ $<
|
||||
|
||||
.po.gmo:
|
||||
file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \
|
||||
&& rm -f $$file && $(GMSGFMT) --statistics -o $$file $<
|
||||
|
||||
|
||||
all: all-@USE_NLS@
|
||||
|
||||
all-yes: $(CATALOGS)
|
||||
all-no:
|
||||
|
||||
# Note: Target 'all' must not depend on target '$(srcdir)/$(PACKAGE).pot',
|
||||
# otherwise packages like GCC can not be built if only parts of the source
|
||||
# have been downloaded.
|
||||
|
||||
$(srcdir)/$(PACKAGE).pot: $(POTFILES) $(srcdir)/POTFILES.in
|
||||
$(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
|
||||
--add-comments --keyword=_ --keyword=N_ \
|
||||
--files-from=$(srcdir)/POTFILES.in \
|
||||
&& test ! -f $(PACKAGE).po \
|
||||
|| ( rm -f $(srcdir)/$(PACKAGE).pot \
|
||||
&& mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot )
|
||||
|
||||
|
||||
install: install-exec install-data
|
||||
install-exec:
|
||||
install-data: install-data-@USE_NLS@
|
||||
if test "$(PACKAGE)" = "gettext"; then \
|
||||
$(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
|
||||
$(INSTALL_DATA) $(srcdir)/Makefile.in.in \
|
||||
$(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \
|
||||
else \
|
||||
: ; \
|
||||
fi
|
||||
install-data-no: all
|
||||
install-data-yes: all
|
||||
$(mkinstalldirs) $(DESTDIR)$(datadir)
|
||||
@catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed 's/\.gmo$$//'`; \
|
||||
dir=$(localedir)/$$lang/LC_MESSAGES; \
|
||||
$(mkinstalldirs) $(DESTDIR)$$dir; \
|
||||
if test -r $$cat; then \
|
||||
$(INSTALL_DATA) $$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \
|
||||
echo "installing $$cat as $(DESTDIR)$$dir/$(PACKAGE).mo"; \
|
||||
else \
|
||||
$(INSTALL_DATA) $(srcdir)/$$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \
|
||||
echo "installing $(srcdir)/$$cat as" \
|
||||
"$(DESTDIR)$$dir/$(PACKAGE).mo"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
# Define this as empty until I found a useful application.
|
||||
installcheck:
|
||||
|
||||
uninstall:
|
||||
catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed 's/\.gmo$$//'`; \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(PACKAGE).mo; \
|
||||
done
|
||||
if test "$(PACKAGE)" = "gettext"; then \
|
||||
rm -f $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \
|
||||
else \
|
||||
: ; \
|
||||
fi
|
||||
|
||||
check: all
|
||||
|
||||
dvi info tags TAGS ID:
|
||||
|
||||
mostlyclean:
|
||||
rm -f core core.* *.pox $(PACKAGE).po *.new.po
|
||||
rm -fr *.o
|
||||
|
||||
clean: mostlyclean
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile Makefile.in POTFILES *.mo
|
||||
|
||||
maintainer-clean: distclean
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
rm -f $(GMOFILES)
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
dist distdir:
|
||||
$(MAKE) update-po
|
||||
@$(MAKE) dist2
|
||||
# This is a separate target because 'update-po' must be executed before.
|
||||
dist2: $(DISTFILES)
|
||||
dists="$(DISTFILES)"; \
|
||||
for file in $$dists; do \
|
||||
if test -f $$file; then dir=.; else dir=$(srcdir); fi; \
|
||||
cp -p $$dir/$$file $(distdir); \
|
||||
done
|
||||
|
||||
update-po: Makefile
|
||||
$(MAKE) $(PACKAGE).pot
|
||||
if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; fi; \
|
||||
cd $(srcdir); \
|
||||
catalogs='$(GMOFILES)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed 's/\.gmo$$//'`; \
|
||||
echo "$$lang:"; \
|
||||
if $(MSGMERGE) $$lang.po $(PACKAGE).pot -o $$lang.new.po; then \
|
||||
mv -f $$lang.new.po $$lang.po; \
|
||||
else \
|
||||
echo "msgmerge for $$cat failed!"; \
|
||||
rm -f $$lang.new.po; \
|
||||
fi; \
|
||||
done
|
||||
$(MAKE) update-gmo
|
||||
|
||||
update-gmo: Makefile $(GMOFILES)
|
||||
@:
|
||||
|
||||
Makefile: Makefile.in.in $(top_builddir)/config.status POTFILES.in
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \
|
||||
$(SHELL) ./config.status
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make not to export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
@@ -19,26 +19,27 @@
|
||||
# 02110-1301, USA.
|
||||
|
||||
# Library files
|
||||
lib/argmatch.c
|
||||
lib/argp-help.c
|
||||
lib/argp-parse.c
|
||||
lib/closeout.c
|
||||
lib/error.c
|
||||
lib/getopt.c
|
||||
lib/obstack.c
|
||||
lib/human.c
|
||||
lib/obstack.c
|
||||
lib/openat-die.c
|
||||
gnu/argmatch.c
|
||||
gnu/argp-help.c
|
||||
gnu/argp-parse.c
|
||||
gnu/closeout.c
|
||||
gnu/error.c
|
||||
gnu/getopt.c
|
||||
gnu/obstack.c
|
||||
gnu/human.c
|
||||
gnu/obstack.c
|
||||
gnu/openat-die.c
|
||||
gnu/quotearg.c
|
||||
gnu/rpmatch.c
|
||||
gnu/xalloc-die.c
|
||||
gnu/xmalloc.c
|
||||
gnu/version-etc.c
|
||||
gnu/xalloc-die.c
|
||||
|
||||
lib/paxerror.c
|
||||
lib/paxexit.c
|
||||
lib/paxnames.c
|
||||
lib/quotearg.c
|
||||
lib/rpmatch.c
|
||||
lib/rtapelib.c
|
||||
lib/xalloc-die.c
|
||||
lib/xmalloc.c
|
||||
lib/version-etc.c
|
||||
lib/xalloc-die.c
|
||||
|
||||
rmt/rmt.c
|
||||
|
||||
|
||||
852
rebox.el
852
rebox.el
@@ -1,852 +0,0 @@
|
||||
;;; Handling of comment boxes.
|
||||
;;; Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
|
||||
;;; Fran<61>ois Pinard <pinard@iro.umontreal.ca>, April 1991.
|
||||
|
||||
;;; I first observed rounded corners, as in style 223 boxes, in code from
|
||||
;;; Warren Tucker <wht@n4hgf.mt-park.ga.us>, a previous shar maintainer.
|
||||
|
||||
;;; Refilling paragraphs inside comments, stretching or shrinking the
|
||||
;;; surrounding box as needed, is a pain to do "by hand". This GNU Emacs
|
||||
;;; LISP code eases my life on this and I find it fair, giving all sources
|
||||
;;; for a package, to also give the means for nicely modifying comments.
|
||||
|
||||
;;; The function rebox-comment discovers the extent of the boxed comments
|
||||
;;; near the cursor, possibly refills the text, then adjusts the comment
|
||||
;;; box style. The function rebox-region does the same, except that it
|
||||
;;; takes the current region as a boxed comment. Numeric prefixes are
|
||||
;;; used to add or remove a box, change its style (language, quality or
|
||||
;;; type), or to prevent refilling of its text. A minus sign alone as
|
||||
;;; prefix asks for interactive style selection.
|
||||
|
||||
;;; For most Emacs language editing modes, refilling does not make sense
|
||||
;;; outside comments, so you may redefine the M-q command and link it to
|
||||
;;; this file. For example, I use this in my .emacs file:
|
||||
|
||||
;;; (setq c-mode-hook
|
||||
;;; '(lambda ()
|
||||
;;; (define-key c-mode-map "\M-q" 'rebox-comment)))
|
||||
;;; (autoload 'rebox-comment "rebox" nil t)
|
||||
;;; (autoload 'rebox-region "rebox" nil t)
|
||||
|
||||
;;; The cursor should be within a comment before any of these commands,
|
||||
;;; or else it should be between two comments, in which case the command
|
||||
;;; applies to the next comment. When the command is given without prefix,
|
||||
;;; the current comment box style is recognized from the comment itself
|
||||
;;; as far as possible, and preserved. A prefix may be used to force
|
||||
;;; a particular box style. A style is made up of three attributes: a
|
||||
;;; language (the hundreds digit), a quality (the tens digit) and a type
|
||||
;;; (the units digit). A zero or negative flag value changes the default
|
||||
;;; box style to its absolute value. Zero digits in default style,
|
||||
;;; when not overriden in flag, asks for recognition of corresponding
|
||||
;;; attributes from the current box. `C-u' avoids refilling the text,
|
||||
;;; using the default box style. `C-u -' defines the style interactively.
|
||||
|
||||
;;; Box language is associated with comment delimiters. Values are 100
|
||||
;;; for none or unknown, 200 for `/*' and `*/' as in plain C, 300 for
|
||||
;;; '//' as in C++, 400 for `#' as in most scripting languages, 500 for
|
||||
;;; `;' as in LISP or assembler and 600 for `%' as in TeX or PostScript.
|
||||
|
||||
;;; Box quality differs according to language. For unknown languages (100)
|
||||
;;; or for the C language (200), values are 10 for simple, 20 or 30 for
|
||||
;;; rounded, and 40 for starred. For all others, box quality indicates
|
||||
;;; the thickness in characters of the left and right sides of the box:
|
||||
;;; values are 10, 20, 30 or 40 for 1, 2, 3 or 4 characters wide. C++
|
||||
;;; quality 10 is always promoted to 20. Roughly said, simple quality
|
||||
;;; boxes (10) use comment delimiters to left and right of each comment
|
||||
;;; line, and also for the top or bottom line when applicable. Rounded
|
||||
;;; quality boxes (20 or 30) try to suggest rounded corners in boxes.
|
||||
;;; Starred quality boxes (40) mostly use a left margin of asterisks or
|
||||
;;; X'es, and use them also in box surroundings. Experiment a little to
|
||||
;;; see what happens.
|
||||
|
||||
;;; Box type values are 1 for fully opened boxes for which boxing is done
|
||||
;;; only for the left and right but not for top or bottom, 2 for half
|
||||
;;; single lined boxes for which boxing is done on all sides except top,
|
||||
;;; 3 for fully single lined boxes for which boxing is done on all sides,
|
||||
;;; 4 for half double lined boxes which is like type 2 but more bold,
|
||||
;;; or 5 for fully double lined boxes which is like type 3 but more bold.
|
||||
|
||||
;;; The special style 221 or 231 is worth a note, because it is fairly
|
||||
;;; common: the whole C comment stays between a single opening `/*'
|
||||
;;; and a single closing `*/'. The special style 111 deletes a box.
|
||||
;;; The initial default style is 023 so, unless overriden, comments are
|
||||
;;; put in single lined boxes, C comments are of rounded quality.
|
||||
|
||||
(defvar rebox-default-style 0 "*Preferred style for box comments.")
|
||||
|
||||
;;; Help strings for prompting or error messages.
|
||||
|
||||
(defconst REBOX_HELP_FOR_LANGUAGE
|
||||
"Box language is 100-none, 200-/*, 300-//, 400-#, 500-;, 600-%%")
|
||||
(defconst REBOX_LANGUAGE_NONE 100)
|
||||
(defconst REBOX_LANGUAGE_C 200)
|
||||
(defconst REBOX_LANGUAGE_C++ 300)
|
||||
(defconst REBOX_LANGUAGE_AWK 400)
|
||||
(defconst REBOX_LANGUAGE_LISP 500)
|
||||
(defconst REBOX_LANGUAGE_TEX 600)
|
||||
|
||||
(defun rebox-help-string-for-language (language)
|
||||
(cond ((= language 0) "default language")
|
||||
((= language REBOX_LANGUAGE_NONE) "no language")
|
||||
((= language REBOX_LANGUAGE_C) "plain C")
|
||||
((= language REBOX_LANGUAGE_C++) "C++")
|
||||
((= language REBOX_LANGUAGE_AWK) "sh/Perl/make")
|
||||
((= language REBOX_LANGUAGE_LISP) "LISP/assembler")
|
||||
((= language REBOX_LANGUAGE_TEX) "TeX/PostScript")
|
||||
(t "<Unknown Language>")))
|
||||
|
||||
(defconst REBOX_HELP_FOR_QUALITY
|
||||
"Box quality/width is 10-simple, 20-rounded, 30-rounded or 40-starred")
|
||||
(defconst REBOX_QUALITY_SIMPLE_ONE 10)
|
||||
(defconst REBOX_QUALITY_ROUNDED_TWO 20)
|
||||
(defconst REBOX_QUALITY_ROUNDED_THREE 30)
|
||||
(defconst REBOX_QUALITY_STARRED_FOUR 40)
|
||||
|
||||
(defun rebox-help-string-for-quality (quality)
|
||||
(cond ((= quality 0) "default quality")
|
||||
((= quality REBOX_QUALITY_SIMPLE_ONE) "square or 1-wide")
|
||||
((= quality REBOX_QUALITY_ROUNDED_TWO) "rounded or 2-wide")
|
||||
((= quality REBOX_QUALITY_ROUNDED_THREE) "rounded or 3-wide")
|
||||
((= quality REBOX_QUALITY_STARRED_FOUR) "starred or 4-wide")
|
||||
(t "<Unknown Quality>")))
|
||||
|
||||
(defconst REBOX_HELP_FOR_TYPE
|
||||
"Box type is 1-open, 2-half-single, 3-single, 4-half-double or 5-double")
|
||||
(defconst REBOX_TYPE_OPEN 1)
|
||||
(defconst REBOX_TYPE_HALF_SINGLE 2)
|
||||
(defconst REBOX_TYPE_SINGLE 3)
|
||||
(defconst REBOX_TYPE_HALF_DOUBLE 4)
|
||||
(defconst REBOX_TYPE_DOUBLE 5)
|
||||
|
||||
(defun rebox-help-string-for-type (type)
|
||||
(cond ((= type 0) "default type")
|
||||
((= type REBOX_TYPE_OPEN) "opened box")
|
||||
((= type REBOX_TYPE_HALF_SINGLE) "half normal")
|
||||
((= type REBOX_TYPE_SINGLE) "full normal")
|
||||
((= type REBOX_TYPE_HALF_DOUBLE) "half bold")
|
||||
((= type REBOX_TYPE_DOUBLE) "full bold")
|
||||
(t "<Unknown Type>")))
|
||||
|
||||
(defconst REBOX_MAX_LANGUAGE 6)
|
||||
(defconst REBOX_MAX_QUALITY 4)
|
||||
(defconst REBOX_MAX_TYPE 5)
|
||||
|
||||
;;; Request the style interactively, using the minibuffer.
|
||||
|
||||
(defun rebox-ask-for-style ()
|
||||
(let (key language quality type)
|
||||
(while (not language)
|
||||
(message REBOX_HELP_FOR_LANGUAGE)
|
||||
(setq key (read-char))
|
||||
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_LANGUAGE)))
|
||||
(setq language (- key ?0))))
|
||||
(while (not quality)
|
||||
(message REBOX_HELP_FOR_QUALITY)
|
||||
(setq key (read-char))
|
||||
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_QUALITY)))
|
||||
(setq quality (- key ?0))))
|
||||
(while (not type)
|
||||
(message REBOX_HELP_FOR_TYPE)
|
||||
(setq key (read-char))
|
||||
(if (and (>= key ?0) (<= key (+ ?0 REBOX_MAX_TYPE)))
|
||||
(setq type (- key ?0))))
|
||||
(+ (* 100 language) (* 10 quality) type)))
|
||||
|
||||
;;; Write some TEXT followed by an edited STYLE value into the minibuffer.
|
||||
|
||||
(defun rebox-show-style (text style)
|
||||
(message
|
||||
(concat text (format " (%03d)" style)
|
||||
": " (rebox-help-string-for-language (* (/ style 100) 100))
|
||||
", " (rebox-help-string-for-quality (* (% (/ style 10) 10) 10))
|
||||
", " (rebox-help-string-for-type (% style 10)))))
|
||||
|
||||
;;; Validate FLAG and usually return t if not interrupted by errors.
|
||||
;;; But if FLAG is zero or negative, then change default box style and
|
||||
;;; return nil.
|
||||
|
||||
(defun rebox-validate-flag (flag)
|
||||
|
||||
;; Validate flag.
|
||||
|
||||
(if (numberp flag)
|
||||
(let ((value (if (< flag 0) (- flag) flag)))
|
||||
(if (> (/ value 100) REBOX_MAX_LANGUAGE)
|
||||
(error REBOX_HELP_FOR_LANGUAGE))
|
||||
(if (> (% (/ value 10) 10) REBOX_MAX_QUALITY)
|
||||
(error REBOX_HELP_FOR_QUALITY))
|
||||
(if (> (% value 10) REBOX_MAX_TYPE)
|
||||
(error REBOX_HELP_FOR_TYPE))))
|
||||
|
||||
;; Change default box style if requested.
|
||||
|
||||
(if (and (numberp flag) (<= flag 0))
|
||||
(progn
|
||||
(setq flag (- flag))
|
||||
(if (not (zerop (/ flag 100)))
|
||||
(setq rebox-default-style
|
||||
(+ (* (/ flag 100) 100)
|
||||
(% rebox-default-style 100))))
|
||||
(if (not (zerop (% (/ flag 10) 10)))
|
||||
(setq rebox-default-style
|
||||
(+ (* (/ rebox-default-style 100) 100)
|
||||
(* (% (/ flag 10) 10) 10)
|
||||
(% rebox-default-style 10))))
|
||||
(if (not (zerop (% flag 10)))
|
||||
(setq rebox-default-style
|
||||
(+ (* (/ rebox-default-style 10) 10)
|
||||
(% flag 10))))
|
||||
(rebox-show-style "Default style" rebox-default-style)
|
||||
nil)
|
||||
t))
|
||||
|
||||
;;; Return the minimum value of the left margin of all lines, or -1 if
|
||||
;;; all lines are empty.
|
||||
|
||||
(defun rebox-left-margin ()
|
||||
(let ((margin -1))
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(skip-chars-forward " \t")
|
||||
(if (not (looking-at "\n"))
|
||||
(setq margin
|
||||
(if (< margin 0)
|
||||
(current-column)
|
||||
(min margin (current-column)))))
|
||||
(forward-line 1))
|
||||
margin))
|
||||
|
||||
;;; Return the maximum value of the right margin of all lines. Any
|
||||
;;; sentence ending a line has a space guaranteed before the margin.
|
||||
|
||||
(defun rebox-right-margin ()
|
||||
(let ((margin 0) period)
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(end-of-line)
|
||||
(if (bobp)
|
||||
(setq period 0)
|
||||
(backward-char 1)
|
||||
(setq period (if (looking-at "[.?!]") 1 0))
|
||||
(forward-char 1))
|
||||
(setq margin (max margin (+ (current-column) period)))
|
||||
(forward-char 1))
|
||||
margin))
|
||||
|
||||
;;; Return a regexp to match the start or end of a comment for some
|
||||
;;; LANGUAGE, leaving the comment marks themselves available in \1.
|
||||
|
||||
;; FIXME: Recognize style 1** boxes.
|
||||
|
||||
(defun rebox-regexp-start (language)
|
||||
(cond ((= language 0) "^[ \t]*\\(/\\*\\|//+\\|#+\\|;+\\|%+\\)")
|
||||
((= language REBOX_LANGUAGE_NONE) "^\\(\\)")
|
||||
((= language REBOX_LANGUAGE_C) "^[ \t]*\\(/\\*\\)")
|
||||
((= language REBOX_LANGUAGE_C++) "^[ \t]*\\(//+\\)")
|
||||
((= language REBOX_LANGUAGE_AWK) "^[ \t]*\\(#+\\)")
|
||||
((= language REBOX_LANGUAGE_LISP) "^[ \t]*\\(;+\\)")
|
||||
((= language REBOX_LANGUAGE_TEX) "^[ \t]*\\(%+\\)")))
|
||||
|
||||
(defun rebox-regexp-end (language)
|
||||
(cond ((= language 0) "\\(\\*/\\|//+\\|#+\\|;+\\|%+\\)[ \t]*$")
|
||||
((= language REBOX_LANGUAGE_NONE) "\\(\\)$")
|
||||
((= language REBOX_LANGUAGE_C) "\\(\\*/\\)[ \t]*$")
|
||||
((= language REBOX_LANGUAGE_C++) "\\(//+\\)[ \t]*$")
|
||||
((= language REBOX_LANGUAGE_AWK) "\\(#+\\)[ \t]*$")
|
||||
((= language REBOX_LANGUAGE_LISP) "\\(;+\\)[ \t]*$")
|
||||
((= language REBOX_LANGUAGE_TEX) "\\(%+\\)[ \t]*$")))
|
||||
|
||||
;;; By looking at the text starting at the cursor position, guess the
|
||||
;;; language in use, and return it.
|
||||
|
||||
(defun rebox-guess-language ()
|
||||
(let ((language REBOX_LANGUAGE_NONE)
|
||||
(value (* 100 REBOX_MAX_LANGUAGE)))
|
||||
(while (not (zerop value))
|
||||
(if (looking-at (rebox-regexp-start value))
|
||||
(progn
|
||||
(setq language value)
|
||||
(setq value 0))
|
||||
(setq value (- value 100))))
|
||||
language))
|
||||
|
||||
;;; Find the limits of the block of comments following or enclosing
|
||||
;;; the cursor, or return an error if the cursor is not within such a
|
||||
;;; block of comments. Extend it as far as possible in both
|
||||
;;; directions, then narrow the buffer around it.
|
||||
|
||||
(defun rebox-find-and-narrow ()
|
||||
(save-excursion
|
||||
(let (start end temp language)
|
||||
|
||||
;; Find the start of the current or immediately following comment.
|
||||
|
||||
(beginning-of-line)
|
||||
(skip-chars-forward " \t\n")
|
||||
(beginning-of-line)
|
||||
(if (not (looking-at (rebox-regexp-start 0)))
|
||||
(progn
|
||||
(setq temp (point))
|
||||
(if (re-search-forward "\\*/" nil t)
|
||||
(progn
|
||||
(re-search-backward "/\\*")
|
||||
(if (> (point) temp)
|
||||
(error "outside any comment block"))
|
||||
(setq temp (point))
|
||||
(beginning-of-line)
|
||||
(skip-chars-forward " \t")
|
||||
(if (not (= (point) temp))
|
||||
(error "text before start of comment"))
|
||||
(beginning-of-line))
|
||||
(error "outside any comment block"))))
|
||||
|
||||
(setq start (point))
|
||||
(setq language (rebox-guess-language))
|
||||
|
||||
;; - find the end of this comment
|
||||
|
||||
(if (= language REBOX_LANGUAGE_C)
|
||||
(progn
|
||||
(search-forward "*/")
|
||||
(if (not (looking-at "[ \t]*$"))
|
||||
(error "text after end of comment"))))
|
||||
(end-of-line)
|
||||
(if (eobp)
|
||||
(insert "\n")
|
||||
(forward-char 1))
|
||||
(setq end (point))
|
||||
|
||||
;; - try to extend the comment block backwards
|
||||
|
||||
(goto-char start)
|
||||
(while (and (not (bobp))
|
||||
(if (= language REBOX_LANGUAGE_C)
|
||||
(progn
|
||||
(skip-chars-backward " \t\n")
|
||||
(if (and (looking-at "[ \t]*\n[ \t]*/\\*")
|
||||
(> (point) 2))
|
||||
(progn
|
||||
(backward-char 2)
|
||||
(if (looking-at "\\*/")
|
||||
(progn
|
||||
(re-search-backward "/\\*")
|
||||
(setq temp (point))
|
||||
(beginning-of-line)
|
||||
(skip-chars-forward " \t")
|
||||
(if (= (point) temp)
|
||||
(progn (beginning-of-line) t)))))))
|
||||
(previous-line 1)
|
||||
(looking-at (rebox-regexp-start language))))
|
||||
(setq start (point)))
|
||||
|
||||
;; - try to extend the comment block forward
|
||||
|
||||
(goto-char end)
|
||||
(while (looking-at (rebox-regexp-start language))
|
||||
(if (= language REBOX_LANGUAGE_C)
|
||||
(progn
|
||||
(re-search-forward "[ \t]*/\\*")
|
||||
(re-search-forward "\\*/")
|
||||
(if (looking-at "[ \t]*$")
|
||||
(progn
|
||||
(beginning-of-line)
|
||||
(forward-line 1)
|
||||
(setq end (point)))))
|
||||
(forward-line 1)
|
||||
(setq end (point))))
|
||||
|
||||
;; - narrow to the whole block of comments
|
||||
|
||||
(narrow-to-region start end))))
|
||||
|
||||
;;; After refilling it if REFILL is not nil, while respecting a left
|
||||
;;; MARGIN, put the narrowed buffer back into a boxed LANGUAGE comment
|
||||
;;; box of a given QUALITY and TYPE.
|
||||
|
||||
(defun rebox-reconstruct (refill margin language quality type)
|
||||
(rebox-show-style "Style" (+ language quality type))
|
||||
|
||||
(let (right-margin nw nn ne ww ee sw ss se x xx)
|
||||
|
||||
;; - decide the elements of the box being produced
|
||||
|
||||
(cond ((= language REBOX_LANGUAGE_NONE)
|
||||
;; - planify a comment for no language in particular
|
||||
|
||||
(cond ((= quality REBOX_QUALITY_SIMPLE_ONE)
|
||||
;; - planify a simple box
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "") (setq sw "")
|
||||
(setq ww "") (setq ee ""))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "+-") (setq ss ?-) (setq se "-+"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw "+-") (setq nn ?-) (setq ne "-+")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "+-") (setq ss ?-) (setq se "-+"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "*=") (setq ss ?=) (setq se "=*"))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "*=") (setq nn ?=) (setq ne "=*")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "*=") (setq ss ?=) (setq se "=*"))))
|
||||
|
||||
((or (= quality REBOX_QUALITY_ROUNDED_TWO)
|
||||
(= quality REBOX_QUALITY_ROUNDED_THREE))
|
||||
;; - planify a rounded box
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "") (setq sw "")
|
||||
(setq ww "| ") (setq ee " |"))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "`-") (setq ss ?-) (setq se "-'"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw ".-") (setq nn ?-) (setq ne "-.")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "`-") (setq ss ?-) (setq se "-'"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "")
|
||||
(setq ww "| " ) (setq ee " |" )
|
||||
(setq sw "\\=") (setq ss ?=) (setq se "=/" ))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "/=" ) (setq nn ?=) (setq ne "=\\")
|
||||
(setq ww "| " ) (setq ee " |" )
|
||||
(setq sw "\\=") (setq ss ?=) (setq se "=/" ))))
|
||||
|
||||
((= quality REBOX_QUALITY_STARRED_FOUR)
|
||||
;; - planify a starred box
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "") (setq sw "")
|
||||
(setq ww "| ") (setq ee ""))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "")
|
||||
(setq ww "* ") (setq ee " *")
|
||||
(setq sw "**") (setq ss ?*) (setq se "**"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw "**") (setq nn ?*) (setq ne "**")
|
||||
(setq ww "* ") (setq ee " *")
|
||||
(setq sw "**") (setq ss ?*) (setq se "**"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "")
|
||||
(setq ww "X ") (setq ee " X")
|
||||
(setq sw "XX") (setq ss ?X) (setq se "XX"))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "XX") (setq nn ?X) (setq ne "XX")
|
||||
(setq ww "X ") (setq ee " X")
|
||||
(setq sw "XX") (setq ss ?X) (setq se "XX"))))))
|
||||
|
||||
((= language REBOX_LANGUAGE_C)
|
||||
;; - planify a comment for C
|
||||
|
||||
(cond ((= quality REBOX_QUALITY_SIMPLE_ONE)
|
||||
;; - planify a simple C comment
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "") (setq sw "")
|
||||
(setq ww "/* ") (setq ee " */"))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "")
|
||||
(setq ww "/* ") (setq ee " */")
|
||||
(setq sw "/* ") (setq ss ?-) (setq se " */"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw "/* ") (setq nn ?-) (setq ne " */")
|
||||
(setq ww "/* ") (setq ee " */")
|
||||
(setq sw "/* ") (setq ss ?-) (setq se " */"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "")
|
||||
(setq ww "/* ") (setq ee " */")
|
||||
(setq sw "/* ") (setq ss ?=) (setq se " */"))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "/* ") (setq nn ?=) (setq ne " */")
|
||||
(setq ww "/* ") (setq ee " */")
|
||||
(setq sw "/* ") (setq ss ?=) (setq se " */"))))
|
||||
|
||||
((or (= quality REBOX_QUALITY_ROUNDED_TWO)
|
||||
(= quality REBOX_QUALITY_ROUNDED_THREE))
|
||||
;; - planify a rounded C comment
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
;; ``open rounded'' is a special case
|
||||
(setq nw "") (setq sw "")
|
||||
(setq ww " ") (setq ee ""))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "/*") (setq nn ? ) (setq ne " .")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "`-") (setq ss ?-) (setq se "*/"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw "/*") (setq nn ?-) (setq ne "-.")
|
||||
(setq ww "| ") (setq ee " |")
|
||||
(setq sw "`-") (setq ss ?-) (setq se "*/"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "/*" ) (setq nn ? ) (setq ne " \\")
|
||||
(setq ww "| " ) (setq ee " |" )
|
||||
(setq sw "\\=") (setq ss ?=) (setq se "*/" ))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "/*" ) (setq nn ?=) (setq ne "=\\")
|
||||
(setq ww "| " ) (setq ee " |" )
|
||||
(setq sw "\\=") (setq ss ?=) (setq se "*/" ))))
|
||||
|
||||
((= quality REBOX_QUALITY_STARRED_FOUR)
|
||||
;; - planify a starred C comment
|
||||
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "/* ") (setq nn ? ) (setq ne "")
|
||||
(setq ww " * ") (setq ee "")
|
||||
(setq sw " */") (setq ss ? ) (setq se ""))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq nw "/* ") (setq nn ? ) (setq ne " *")
|
||||
(setq ww " * ") (setq ee " *")
|
||||
(setq sw " **") (setq ss ?*) (setq se "**/"))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq nw "/**") (setq nn ?*) (setq ne "**")
|
||||
(setq ww " * ") (setq ee " *")
|
||||
(setq sw " **") (setq ss ?*) (setq se "**/"))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq nw "/* " ) (setq nn ? ) (setq ne " *\\")
|
||||
(setq ww "|* " ) (setq ee " *|" )
|
||||
(setq sw "\\**") (setq ss ?*) (setq se "**/" ))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq nw "/**" ) (setq nn ?*) (setq ne "**\\")
|
||||
(setq ww "|* " ) (setq ee " *|" )
|
||||
(setq sw "\\**") (setq ss ?*) (setq se "**/" ))))))
|
||||
|
||||
(t
|
||||
;; - planify a comment for all other things
|
||||
|
||||
(if (and (= language REBOX_LANGUAGE_C++)
|
||||
(= quality REBOX_QUALITY_SIMPLE_ONE))
|
||||
(setq quality REBOX_QUALITY_ROUNDED_TWO))
|
||||
(setq x (cond ((= language REBOX_LANGUAGE_C++) ?/)
|
||||
((= language REBOX_LANGUAGE_AWK) ?#)
|
||||
((= language REBOX_LANGUAGE_LISP) ?\;)
|
||||
((= language REBOX_LANGUAGE_TEX) ?%)))
|
||||
(setq xx (make-string (/ quality 10) x))
|
||||
(setq ww (concat xx " "))
|
||||
(cond ((= type REBOX_TYPE_OPEN)
|
||||
(setq nw "") (setq sw "") (setq ee ""))
|
||||
((= type REBOX_TYPE_HALF_SINGLE)
|
||||
(setq ee (concat " " xx))
|
||||
(setq nw "")
|
||||
(setq sw ww) (setq ss ?-) (setq se ee))
|
||||
((= type REBOX_TYPE_SINGLE)
|
||||
(setq ee (concat " " xx))
|
||||
(setq nw ww) (setq nn ?-) (setq ne ee)
|
||||
(setq sw ww) (setq ss ?-) (setq se ee))
|
||||
((= type REBOX_TYPE_HALF_DOUBLE)
|
||||
(setq ee (concat " " xx))
|
||||
(setq xx (make-string (1+ (/ quality 10)) x))
|
||||
(setq nw "")
|
||||
(setq sw xx) (setq ss x) (setq se xx))
|
||||
((= type REBOX_TYPE_DOUBLE)
|
||||
(setq ee (concat " " xx))
|
||||
(setq xx (make-string (1+ (/ quality 10)) x))
|
||||
(setq nw xx) (setq nn x) (setq ne xx)
|
||||
(setq sw xx) (setq ss x) (setq se xx)))))
|
||||
|
||||
;; - possibly refill, and adjust margins to account for left inserts
|
||||
|
||||
(if (not (and flag (listp flag)))
|
||||
(let ((fill-prefix (make-string margin ? ))
|
||||
(fill-column (- fill-column (+ (length ww) (length ee)))))
|
||||
(fill-region (point-min) (point-max))))
|
||||
|
||||
(setq right-margin (+ (rebox-right-margin) (length ww)))
|
||||
|
||||
;; - construct the box comment, from top to bottom
|
||||
|
||||
(goto-char (point-min))
|
||||
(if (and (= language REBOX_LANGUAGE_C)
|
||||
(or (= quality REBOX_QUALITY_ROUNDED_TWO)
|
||||
(= quality REBOX_QUALITY_ROUNDED_THREE))
|
||||
(= type REBOX_TYPE_OPEN))
|
||||
(progn
|
||||
;; - construct an 33 style comment
|
||||
|
||||
(skip-chars-forward " " (+ (point) margin))
|
||||
(insert (make-string (- margin (current-column)) ? )
|
||||
"/* ")
|
||||
(end-of-line)
|
||||
(forward-char 1)
|
||||
(while (not (eobp))
|
||||
(skip-chars-forward " " (+ (point) margin))
|
||||
(insert (make-string (- margin (current-column)) ? )
|
||||
ww)
|
||||
(beginning-of-line)
|
||||
(forward-line 1))
|
||||
(backward-char 1)
|
||||
(insert " */"))
|
||||
|
||||
;; - construct all other comment styles
|
||||
|
||||
;; construct one top line
|
||||
(if (not (zerop (length nw)))
|
||||
(progn
|
||||
(indent-to margin)
|
||||
(insert nw)
|
||||
(if (or (not (eq nn ? )) (not (zerop (length ne))))
|
||||
(insert (make-string (- right-margin (current-column)) nn)
|
||||
ne))
|
||||
(insert "\n")))
|
||||
|
||||
;; construct one middle line
|
||||
(while (not (eobp))
|
||||
(skip-chars-forward " " (+ (point) margin))
|
||||
(insert (make-string (- margin (current-column)) ? )
|
||||
ww)
|
||||
(end-of-line)
|
||||
(if (not (zerop (length ee)))
|
||||
(progn
|
||||
(indent-to right-margin)
|
||||
(insert ee)))
|
||||
(beginning-of-line)
|
||||
(forward-line 1))
|
||||
|
||||
;; construct one bottom line
|
||||
(if (not (zerop (length sw)))
|
||||
(progn
|
||||
(indent-to margin)
|
||||
(insert sw)
|
||||
(if (or (not (eq ss ? )) (not (zerop (length se))))
|
||||
(insert (make-string (- right-margin (current-column)) ss)
|
||||
se "\n")))))))
|
||||
|
||||
;;; Add, delete or adjust a comment box in the narrowed buffer.
|
||||
;;; Various FLAG values are explained at beginning of this file.
|
||||
|
||||
(defun rebox-engine (flag)
|
||||
(let ((undo-list buffer-undo-list)
|
||||
(marked-point (point-marker))
|
||||
(language (progn (goto-char (point-min)) (rebox-guess-language)))
|
||||
(quality 0)
|
||||
(type 0))
|
||||
|
||||
(untabify (point-min) (point-max))
|
||||
|
||||
;; Remove all the comment marks, and move all the text rigidly to the
|
||||
;; left for insuring that the left margin stays at the same place.
|
||||
;; At the same time, try recognizing the box style, saving its quality
|
||||
;; in QUALITY and its type in TYPE. (LANGUAGE is already guessed.)
|
||||
|
||||
(let ((indent-tabs-mode nil)
|
||||
(previous-margin (rebox-left-margin))
|
||||
actual-margin)
|
||||
|
||||
;; FIXME: Cleanup style 1** boxes.
|
||||
;; FIXME: Recognize really all cases of type and quality.
|
||||
|
||||
;; - remove all comment marks
|
||||
|
||||
(if (= language REBOX_LANGUAGE_NONE)
|
||||
nil
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward (rebox-regexp-start language) nil t)
|
||||
(goto-char (match-beginning 1))
|
||||
(delete-region (point) (match-end 1))
|
||||
(insert (make-string (- (match-end 1) (point)) ? )))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward (rebox-regexp-end language) nil t)
|
||||
(replace-match "" t t)))
|
||||
|
||||
(if (= language REBOX_LANGUAGE_C)
|
||||
(progn
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\\*/ */\\*" nil t)
|
||||
(replace-match " " t t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^\\( *\\)|\\*\\(.*\\)\\*| *$" nil t)
|
||||
(setq quality REBOX_QUALITY_STARRED_FOUR)
|
||||
(setq type REBOX_TYPE_DOUBLE)
|
||||
(replace-match "\\1 \\2" t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^\\( *\\)\\*\\(.*\\)\\* *$" nil t)
|
||||
(setq quality REBOX_QUALITY_STARRED_FOUR)
|
||||
(setq type REBOX_TYPE_SINGLE)
|
||||
(replace-match "\\1 \\2" t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^\\( *\\)|\\(.*\\)| *$" nil t)
|
||||
(setq quality REBOX_QUALITY_ROUNDED_TWO)
|
||||
(replace-match "\\1 \\2" t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(if (zerop quality)
|
||||
(while (re-search-forward "^\\( +\\)\\* " nil t)
|
||||
(setq quality REBOX_QUALITY_STARRED_FOUR)
|
||||
(setq type REBOX_TYPE_OPEN)
|
||||
(replace-match "\\1 " t)))))
|
||||
|
||||
;; - remove the first dashed or starred line
|
||||
|
||||
(goto-char (point-min))
|
||||
(if (looking-at "^ *\\(--+\\|\\*\\*+\\)[.\+\\]? *\n")
|
||||
(progn
|
||||
(setq type REBOX_TYPE_SINGLE)
|
||||
(replace-match "" t t))
|
||||
(if (looking-at "^ *\\(==\\|XX+\\|##+\\|;;+\\)[.\+\\]? *\n")
|
||||
(progn
|
||||
(setq type REBOX_TYPE_DOUBLE)
|
||||
(replace-match "" t t))))
|
||||
|
||||
;; - remove the last dashed or starred line
|
||||
|
||||
(goto-char (point-max))
|
||||
(previous-line 1)
|
||||
(if (looking-at "^ *[`\+\\]?*--+ *\n")
|
||||
(progn
|
||||
(if (= type REBOX_TYPE_OPEN)
|
||||
(setq type REBOX_TYPE_HALF_SINGLE))
|
||||
(replace-match "" t t))
|
||||
(if (looking-at "^ *[`\+\\]?*\\(==+\\|##+\\|;;+\\) *\n")
|
||||
(progn
|
||||
(if (= type REBOX_TYPE_OPEN)
|
||||
(setq type REBOX_TYPE_HALF_DOUBLE))
|
||||
(replace-match "" t t))
|
||||
(if (looking-at "^ *\\*\\*+[.\+\\]? *\n")
|
||||
(progn
|
||||
(setq quality REBOX_QUALITY_STARRED_FOUR)
|
||||
(setq type REBOX_TYPE_HALF_SINGLE)
|
||||
(replace-match "" t t))
|
||||
(if (looking-at "^ *XX+[.\+\\]? *\n")
|
||||
(progn
|
||||
(setq quality REBOX_QUALITY_STARRED_FOUR)
|
||||
(setq type REBOX_TYPE_HALF_DOUBLE)
|
||||
(replace-match "" t t))))))
|
||||
|
||||
;; - remove all spurious whitespace
|
||||
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward " +$" nil t)
|
||||
(replace-match "" t t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(if (looking-at "\n+")
|
||||
(replace-match "" t t))
|
||||
|
||||
(goto-char (point-max))
|
||||
(skip-chars-backward "\n")
|
||||
(if (looking-at "\n\n+")
|
||||
(replace-match "\n" t t))
|
||||
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\n\n\n+" nil t)
|
||||
(replace-match "\n\n" t t))
|
||||
|
||||
;; - move the text left is adequate
|
||||
|
||||
(setq actual-margin (rebox-left-margin))
|
||||
(if (not (= previous-margin actual-margin))
|
||||
(indent-rigidly (point-min) (point-max)
|
||||
(- previous-margin actual-margin))))
|
||||
|
||||
;; Override box style according to FLAG or chosen default style.
|
||||
;; Else, use either recognized style elements or built-in defaults.
|
||||
|
||||
(cond ((and (numberp flag) (not (zerop (/ flag 100))))
|
||||
(setq language (* (/ flag 100) 100)))
|
||||
((not (zerop (/ rebox-default-style 100)))
|
||||
(setq language (* (/ rebox-default-style 100) 100))))
|
||||
|
||||
(cond ((and (numberp flag) (not (zerop (% (/ flag 10) 10))))
|
||||
(setq quality (* (% (/ flag 10) 10) 10)))
|
||||
((not (zerop (% (/ rebox-default-style 10) 10)))
|
||||
(setq quality (* (% (/ rebox-default-style 10) 10) 10)))
|
||||
((zerop quality)
|
||||
(setq quality REBOX_QUALITY_ROUNDED_TWO)))
|
||||
|
||||
(cond ((and (numberp flag) (not (zerop (% flag 10))))
|
||||
(setq type (% flag 10)))
|
||||
((not (zerop (% rebox-default-style 10)))
|
||||
(setq type (% rebox-default-style 10)))
|
||||
((zerop type)
|
||||
(setq type 1)))
|
||||
|
||||
;; Possibly refill, then reconstruct the comment box.
|
||||
|
||||
(let ((indent-tabs-mode nil))
|
||||
(rebox-reconstruct (not (and flag (listp flag)))
|
||||
(rebox-left-margin)
|
||||
language quality type))
|
||||
|
||||
;; Retabify to the left only (adapted from tabify.el).
|
||||
|
||||
(if indent-tabs-mode
|
||||
(progn
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^[ \t][ \t]+" nil t)
|
||||
(let ((column (current-column)))
|
||||
(delete-region (match-beginning 0) (point))
|
||||
(indent-to column)))))
|
||||
|
||||
;; Restore the point position.
|
||||
|
||||
(goto-char (marker-position marked-point))
|
||||
|
||||
;; Remove all intermediate boundaries from the undo list.
|
||||
|
||||
(if (not (eq buffer-undo-list undo-list))
|
||||
(let ((cursor buffer-undo-list))
|
||||
(while (not (eq (cdr cursor) undo-list))
|
||||
(if (car (cdr cursor))
|
||||
(setq cursor (cdr cursor))
|
||||
(rplacd cursor (cdr (cdr cursor)))))))))
|
||||
|
||||
;;; Set or reset the Taarna team's own way for a C style. You do not
|
||||
;;; really want to know about this.
|
||||
|
||||
(defvar c-mode-taarna-style nil "*Non-nil for Taarna team C-style.")
|
||||
|
||||
(defun taarna-mode ()
|
||||
(interactive)
|
||||
(if c-mode-taarna-style
|
||||
(progn
|
||||
|
||||
(setq c-mode-taarna-style nil)
|
||||
(setq c-indent-level 2)
|
||||
(setq c-continued-statement-offset 2)
|
||||
(setq c-brace-offset 0)
|
||||
(setq c-argdecl-indent 5)
|
||||
(setq c-label-offset -2)
|
||||
(setq c-tab-always-indent t)
|
||||
(setq rebox-default-style REBOX_QUALITY_ROUNDED_TWO)
|
||||
(message "C mode: GNU style"))
|
||||
|
||||
(setq c-mode-taarna-style t)
|
||||
(setq c-indent-level 4)
|
||||
(setq c-continued-statement-offset 4)
|
||||
(setq c-brace-offset -4)
|
||||
(setq c-argdecl-indent 4)
|
||||
(setq c-label-offset -4)
|
||||
(setq c-tab-always-indent t)
|
||||
(setq rebox-default-style
|
||||
(+ REBOX_QUALITY_SIMPLE_ONE REBOX_TYPE_HALF_SINGLE))
|
||||
(message "C mode: Taarna style")))
|
||||
|
||||
;;; Rebox the current region.
|
||||
|
||||
(defun rebox-region (flag)
|
||||
(interactive "P")
|
||||
(if (eq flag '-) (setq flag (rebox-ask-for-style)))
|
||||
(if (rebox-validate-flag flag)
|
||||
(save-restriction
|
||||
(narrow-to-region (region-beginning) (region-end))
|
||||
(rebox-engine flag))))
|
||||
|
||||
;;; Rebox the surrounding comment.
|
||||
|
||||
(defun rebox-comment (flag)
|
||||
(interactive "P")
|
||||
(if (eq flag '-) (setq flag (rebox-ask-for-style)))
|
||||
(if (rebox-validate-flag flag)
|
||||
(save-restriction
|
||||
(rebox-find-and-narrow)
|
||||
(rebox-engine flag))))
|
||||
@@ -1,6 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
backup.sh
|
||||
backup
|
||||
restore
|
||||
dump-remind
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -279,8 +280,8 @@ read_map (FILE *ifp)
|
||||
sparse_map[i].numbytes = string_to_size (nbuf, NULL);
|
||||
}
|
||||
|
||||
fseek (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
|
||||
SEEK_SET);
|
||||
fseeko (ifp, ((ftell (ifp) + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE,
|
||||
SEEK_SET);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
.deps
|
||||
.gdbinit
|
||||
Makefile
|
||||
Makefile.in
|
||||
rmt
|
||||
tar
|
||||
1
src/.gitignore
vendored
Normal file
1
src/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
tar
|
||||
@@ -1,7 +1,7 @@
|
||||
# Makefile for GNU tar sources.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2006,
|
||||
# 2007 Free Software Foundation, Inc.
|
||||
# 2007, 2009 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
|
||||
@@ -27,6 +27,7 @@ tar_SOURCES = \
|
||||
compare.c\
|
||||
create.c\
|
||||
delete.c\
|
||||
exit.c\
|
||||
extract.c\
|
||||
xheader.c\
|
||||
incremen.c\
|
||||
@@ -38,11 +39,13 @@ tar_SOURCES = \
|
||||
system.c\
|
||||
tar.c\
|
||||
transform.c\
|
||||
unlink.c\
|
||||
update.c\
|
||||
utf8.c
|
||||
utf8.c\
|
||||
warning.c
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
|
||||
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
|
||||
|
||||
LDADD = ../lib/libtar.a $(LIBINTL) $(LIBICONV)
|
||||
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
|
||||
|
||||
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
|
||||
|
||||
201
src/Makefile.in
201
src/Makefile.in
@@ -1,201 +0,0 @@
|
||||
# Un*x Makefile for GNU tar program.
|
||||
# Copyright (C) 1991, 1992, 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#### Start of system configuration section. ####
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
# If you use gcc, you should either run the fixincludes script that
|
||||
# comes with it or else use gcc with the -traditional option. Otherwise
|
||||
# ioctl calls will be compiled incorrectly on some systems.
|
||||
CC = @CC@
|
||||
YACC = @YACC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
# Things you might add to DEFS:
|
||||
# -DSTDC_HEADERS If you have ANSI C headers and libraries.
|
||||
# -DHAVE_UNISTD_H If you have unistd.h.
|
||||
# -DHAVE_STRING_H If you don't have ANSI C headers but have string.h.
|
||||
# -DHAVE_LIMITS_H If you have limits.h.
|
||||
# -DBSD42 If you have sys/dir.h (unless you use -DPOSIX),
|
||||
# sys/file.h, and st_blocks in `struct stat'.
|
||||
# -DDIRENT If you have dirent.h.
|
||||
# -DSYSNDIR Old Xenix systems (sys/ndir.h).
|
||||
# -DSYSDIR Old BSD systems (sys/dir.h).
|
||||
# -DNDIR Old System V systems (ndir.h).
|
||||
# -DMAJOR_IN_MKDEV If major, minor, makedev defined in sys/mkdev.h.
|
||||
# -DMAJOR_IN_SYSMACROS If major, minor, makedev defined in sys/sysmacros.h.
|
||||
# -DRETSIGTYPE=int If your signal handlers return int, not void.
|
||||
# -DHAVE_SYS_MTIO_H If you have sys/mtio.h (magtape ioctls).
|
||||
# -DHAVE_SYS_GENTAPE_H If you have sys/gentape.h (ISC magtape ioctls).
|
||||
# -DHAVE_NETDB_H To use rexec for remote tape operations
|
||||
# instead of forking rsh or remsh.
|
||||
# -DNO_REMOTE If you have neither a remote shell nor rexec.
|
||||
# -DHAVE_VPRINTF If you have vprintf function.
|
||||
# -DHAVE_DOPRNT If you have _doprnt function (but lack vprintf).
|
||||
# -DHAVE_FTIME If you have ftime system call.
|
||||
# -DHAVE_STRSTR If you have strstr function.
|
||||
# -DHAVE_VALLOC If you have valloc function.
|
||||
# -DHAVE_MKDIR If you have mkdir and rmdir system calls.
|
||||
# -DHAVE_MKNOD If you have mknod system call.
|
||||
# -DHAVE_RENAME If you have rename system call.
|
||||
# -DHAVE_GETCWD If not POSIX.1 but have getcwd function.
|
||||
# -DHAVE_FTRUNCATE If you have ftruncate system call.
|
||||
# -DV7 On Version 7 Unix (not tested in a long time).
|
||||
# -DEMUL_OPEN3 If you lack a 3-argument version of open, and want
|
||||
# to emulate it with system calls you do have.
|
||||
# -DNO_OPEN3 If you lack the 3-argument open and want to
|
||||
# disable the tar -k option instead of emulating open.
|
||||
# -DXENIX If you have sys/inode.h and need it to be included.
|
||||
|
||||
DEF_AR_FILE = @DEF_AR_FILE@
|
||||
DEFBLOCKING = 20
|
||||
DEFS = @DEFS@ -DDEF_AR_FILE=\"$(DEF_AR_FILE)\" -DDEFBLOCKING=$(DEFBLOCKING)
|
||||
|
||||
# Set this to rtapelib.o unless you defined NO_REMOTE, in which case
|
||||
# make it empty.
|
||||
RTAPELIB = @RTAPELIB@
|
||||
LIBS = @LIBS@
|
||||
|
||||
CFLAGS = -g
|
||||
LDFLAGS = -g
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = $(prefix)
|
||||
|
||||
# Prefix for each installed program, normally empty or `g'.
|
||||
binprefix =
|
||||
|
||||
# The directory to install tar in.
|
||||
bindir = $(exec_prefix)/bin
|
||||
|
||||
# Where to put the rmt executable.
|
||||
libdir = $(exec_prefix)/lib
|
||||
|
||||
# The directory to install the info files in.
|
||||
infodir = $(prefix)/info
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
SRC1 = tar.c create.c extract.c buffer.c getoldopt.c update.c gnu.c mangle.c
|
||||
SRC2 = version.c list.c names.c diffarch.c port.c fnmatch.c getopt.c malloc.c
|
||||
SRC3 = getopt1.c regex.c getdate.y getdate.c alloca.c
|
||||
SRCS = $(SRC1) $(SRC2) $(SRC3)
|
||||
OBJ1 = tar.o create.o extract.o buffer.o getoldopt.o update.o gnu.o mangle.o
|
||||
OBJ2 = version.o list.o names.o diffarch.o port.o fnmatch.o getopt.o @MALLOC@
|
||||
OBJ3 = getopt1.o regex.o getdate.o $(RTAPELIB) @ALLOCA@
|
||||
OBJS = $(OBJ1) $(OBJ2) $(OBJ3)
|
||||
AUX = README INSTALL NEWS COPYING ChangeLog Makefile.in makefile.pc \
|
||||
configure configure.in mkinstalldirs \
|
||||
tar.h fnmatch.h pathmax.h port.h open3.h getopt.h regex.h \
|
||||
rmt.h rmt.c rtapelib.c \
|
||||
msd_dir.h msd_dir.c tcexparg.c \
|
||||
level-0 level-1 backup-specs dump-remind testpad.c getpagesize.h
|
||||
# tar.texinfo tar.info* texinfo.tex
|
||||
|
||||
all: @PROGS@
|
||||
# tar.info
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) $(CFLAGS) $<
|
||||
|
||||
tar: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
rmt: rmt.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(srcdir)/rmt.c $(LIBS)
|
||||
|
||||
tar.info: tar.texinfo
|
||||
makeinfo $(srcdir)/tar.texinfo
|
||||
|
||||
install: all installdirs
|
||||
$(INSTALL_PROGRAM) tar $(bindir)/$(binprefix)tar
|
||||
-test ! -f rmt || $(INSTALL_PROGRAM) rmt $(libdir)/rmt
|
||||
# for file in $(srcdir)/tar.info*; \
|
||||
# do $(INSTALL_DATA) $$file $(infodir)/$$file; \
|
||||
# done
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/$(binprefix)tar $(infodir)/tar.info*
|
||||
-rm -f $(libdir)/rmt
|
||||
|
||||
installdirs:
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(bindir) $(libdir) $(infodir)
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
$(SHELL) config.status
|
||||
config.status: configure
|
||||
$(SHELL) config.status --recheck
|
||||
configure: configure.in
|
||||
cd $(srcdir); autoconf
|
||||
|
||||
$(OBJS): tar.h pathmax.h port.h testpad.h
|
||||
regex.o buffer.o tar.o: regex.h
|
||||
tar.o fnmatch.o: fnmatch.h
|
||||
|
||||
getdate.c: getdate.y
|
||||
$(YACC) $(srcdir)/getdate.y
|
||||
mv y.tab.c getdate.c
|
||||
# getdate.y has 8 shift/reduce conflicts.
|
||||
|
||||
testpad.h: testpad
|
||||
./testpad
|
||||
|
||||
testpad: testpad.o
|
||||
$(CC) -o $@ testpad.o
|
||||
|
||||
TAGS: $(SRCS)
|
||||
etags $(SRCS)
|
||||
|
||||
clean:
|
||||
rm -f *.o tar rmt testpad testpad.h core
|
||||
|
||||
mostlyclean: clean
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status
|
||||
|
||||
realclean: distclean
|
||||
rm -f TAGS *.info* getdate.c y.tab.c
|
||||
|
||||
shar: $(SRCS) $(AUX)
|
||||
shar $(SRCS) $(AUX) | gzip > tar-`sed -e '/version_string/!d' -e 's/[^0-9.]*\([0-9.]*\).*/\1/' -e q version.c`.shar.z
|
||||
|
||||
dist: $(SRCS) $(AUX)
|
||||
echo tar-`sed -e '/version_string/!d' -e 's/[^0-9.]*\([0-9.]*\).*/\1/' -e q version.c` > .fname
|
||||
-rm -rf `cat .fname`
|
||||
mkdir `cat .fname`
|
||||
for file in $(SRCS) $(AUX); do \
|
||||
ln $$file `cat .fname` || cp $$file `cat .fname`; done
|
||||
tar chzf `cat .fname`.tar.z `cat .fname`
|
||||
-rm -rf `cat .fname` .fname
|
||||
|
||||
tar.zoo: $(SRCS) $(AUX)
|
||||
-rm -rf tmp.dir
|
||||
-mkdir tmp.dir
|
||||
-rm tar.zoo
|
||||
for X in $(SRCS) $(AUX) ; do echo $$X ; sed 's/$$/
|
||||
/' $$X > tmp.dir/$$X ; done
|
||||
cd tmp.dir ; zoo aM ../tar.zoo *
|
||||
-rm -rf tmp.dir
|
||||
|
||||
# Prevent GNU make v3 from overflowing arg limit on SysV.
|
||||
@@ -1,42 +0,0 @@
|
||||
.\" $Id: ansi2knr.1 $
|
||||
.TH ANSI2KNR 1 "9 September 1998" \" -*- nroff -*-
|
||||
.SH NAME
|
||||
ansi2knr \- convert ANSI C to Kernighan & Ritchie C
|
||||
.SH SYNOPSIS
|
||||
\fBansi2knr\fR [\fB--filename\fR \fIfilename\fR] [\fIinput_file\fR [\fIoutput_file\fR]]
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
\fB--filename\fR provides the file name for the #line directive in the output,
|
||||
overriding \fIinput_file\fR (if present).
|
||||
.sp
|
||||
If no \fIinput_file\fR is supplied, input is read from stdin.
|
||||
.sp
|
||||
If no \fIoutput_file\fR is supplied, output goes to stdout.
|
||||
.sp
|
||||
There are no error messages.
|
||||
.sp
|
||||
\fBansi2knr\fR
|
||||
recognizes function definitions by seeing a non-keyword identifier at the left
|
||||
margin, followed by a left parenthesis, with a right parenthesis as the last
|
||||
character on the line, and with a left brace as the first token on the
|
||||
following line (ignoring possible intervening comments). It will recognize a
|
||||
multi-line header provided that no intervening line ends with a left or right
|
||||
brace or a semicolon. These algorithms ignore whitespace and comments, except
|
||||
that the function name must be the first thing on the line.
|
||||
.sp
|
||||
The following constructs will confuse it:
|
||||
.br
|
||||
- Any other construct that starts at the left margin and follows the
|
||||
above syntax (such as a macro or function call).
|
||||
.br
|
||||
- Some macros that tinker with the syntax of the function header.
|
||||
.sp
|
||||
The --varargs switch is obsolete, and is recognized only for
|
||||
backwards compatibility. The present version of
|
||||
\fBansi2knr\fR
|
||||
will always attempt to convert a ... argument to va_alist and va_dcl.
|
||||
.SH AUTHOR
|
||||
L. Peter Deutsch <ghost@aladdin.com> wrote the original ansi2knr and
|
||||
continues to maintain the current version; most of the code in the current
|
||||
version is his work. ansi2knr also includes contributions by Francois
|
||||
Pinard <pinard@iro.umontreal.ca> and Jim Avera <jima@netcom.com>.
|
||||
720
src/ansi2knr.c
720
src/ansi2knr.c
@@ -1,720 +0,0 @@
|
||||
/* Copyright (C) 1989, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved. */
|
||||
|
||||
/*$Id: ansi2knr.c $*/
|
||||
/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
|
||||
|
||||
/*
|
||||
ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone for the
|
||||
consequences of using it or for whether it serves any particular purpose or
|
||||
works at all, unless he says so in writing. Refer to the GNU General Public
|
||||
License (the "GPL") for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute ansi2knr,
|
||||
but only under the conditions described in the GPL. A copy of this license
|
||||
is supposed to have been given to you along with ansi2knr so you can know
|
||||
your rights and responsibilities. It should be in a file named COPYLEFT,
|
||||
or, if there is no file named COPYLEFT, a file named COPYING. Among other
|
||||
things, the copyright notice and this notice must be preserved on all
|
||||
copies.
|
||||
|
||||
We explicitly state here what we believe is already implied by the GPL: if
|
||||
the ansi2knr program is distributed as a separate set of sources and a
|
||||
separate executable file which are aggregated on a storage medium together
|
||||
with another program, this in itself does not bring the other program under
|
||||
the GPL, nor does the mere fact that such a program or the procedures for
|
||||
constructing it invoke the ansi2knr executable bring any other part of the
|
||||
program under the GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]
|
||||
* --filename provides the file name for the #line directive in the output,
|
||||
* overriding input_file (if present).
|
||||
* If no input_file is supplied, input is read from stdin.
|
||||
* If no output_file is supplied, output goes to stdout.
|
||||
* There are no error messages.
|
||||
*
|
||||
* ansi2knr recognizes function definitions by seeing a non-keyword
|
||||
* identifier at the left margin, followed by a left parenthesis, with a
|
||||
* right parenthesis as the last character on the line, and with a left
|
||||
* brace as the first token on the following line (ignoring possible
|
||||
* intervening comments and/or preprocessor directives), except that a line
|
||||
* consisting of only
|
||||
* identifier1(identifier2)
|
||||
* will not be considered a function definition unless identifier2 is
|
||||
* the word "void", and a line consisting of
|
||||
* identifier1(identifier2, <<arbitrary>>)
|
||||
* will not be considered a function definition.
|
||||
* ansi2knr will recognize a multi-line header provided that no intervening
|
||||
* line ends with a left or right brace or a semicolon. These algorithms
|
||||
* ignore whitespace, comments, and preprocessor directives, except that
|
||||
* the function name must be the first thing on the line. The following
|
||||
* constructs will confuse it:
|
||||
* - Any other construct that starts at the left margin and
|
||||
* follows the above syntax (such as a macro or function call).
|
||||
* - Some macros that tinker with the syntax of function headers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The original and principal author of ansi2knr is L. Peter Deutsch
|
||||
* <ghost@aladdin.com>. Other authors are noted in the change history
|
||||
* that follows (in reverse chronological order):
|
||||
lpd 1999-08-17 added code to allow preprocessor directives
|
||||
wherever comments are allowed
|
||||
lpd 1999-04-12 added minor fixes from Pavel Roskin
|
||||
<pavel_roskin@geocities.com> for clean compilation with
|
||||
gcc -W -Wall
|
||||
lpd 1999-03-22 added hack to recognize lines consisting of
|
||||
identifier1(identifier2, xxx) as *not* being procedures
|
||||
lpd 1999-02-03 made indentation of preprocessor commands consistent
|
||||
lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an
|
||||
endless loop; quoted strings within an argument list
|
||||
confused the parser
|
||||
lpd 1999-01-24 added a check for write errors on the output,
|
||||
suggested by Jim Meyering <meyering@ascend.com>
|
||||
lpd 1998-11-09 added further hack to recognize identifier(void)
|
||||
as being a procedure
|
||||
lpd 1998-10-23 added hack to recognize lines consisting of
|
||||
identifier1(identifier2) as *not* being procedures
|
||||
lpd 1997-12-08 made input_file optional; only closes input and/or
|
||||
output file if not stdin or stdout respectively; prints
|
||||
usage message on stderr rather than stdout; adds
|
||||
--filename switch (changes suggested by
|
||||
<ceder@lysator.liu.se>)
|
||||
lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
|
||||
compilers that don't understand void, as suggested by
|
||||
Tom Lane
|
||||
lpd 1996-01-15 changed to require that the first non-comment token
|
||||
on the line following a function header be a left brace,
|
||||
to reduce sensitivity to macros, as suggested by Tom Lane
|
||||
<tgl@sss.pgh.pa.us>
|
||||
lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
|
||||
undefined preprocessor symbols as 0; changed all #ifdefs
|
||||
for configuration symbols to #ifs
|
||||
lpd 1995-04-05 changed copyright notice to make it clear that
|
||||
including ansi2knr in a program does not bring the entire
|
||||
program under the GPL
|
||||
lpd 1994-12-18 added conditionals for systems where ctype macros
|
||||
don't handle 8-bit characters properly, suggested by
|
||||
Francois Pinard <pinard@iro.umontreal.ca>;
|
||||
removed --varargs switch (this is now the default)
|
||||
lpd 1994-10-10 removed CONFIG_BROKETS conditional
|
||||
lpd 1994-07-16 added some conditionals to help GNU `configure',
|
||||
suggested by Francois Pinard <pinard@iro.umontreal.ca>;
|
||||
properly erase prototype args in function parameters,
|
||||
contributed by Jim Avera <jima@netcom.com>;
|
||||
correct error in writeblanks (it shouldn't erase EOLs)
|
||||
lpd 1989-xx-xx original version
|
||||
*/
|
||||
|
||||
/* Most of the conditionals here are to make ansi2knr work with */
|
||||
/* or without the GNU configure machinery. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
|
||||
/*
|
||||
For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
|
||||
This will define HAVE_CONFIG_H and so, activate the following lines.
|
||||
*/
|
||||
|
||||
# if STDC_HEADERS || HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# else
|
||||
# include <strings.h>
|
||||
# endif
|
||||
|
||||
#else /* not HAVE_CONFIG_H */
|
||||
|
||||
/* Otherwise do it the hard way */
|
||||
|
||||
# ifdef BSD
|
||||
# include <strings.h>
|
||||
# else
|
||||
# ifdef VMS
|
||||
extern int strlen(), strncmp();
|
||||
# else
|
||||
# include <string.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* not HAVE_CONFIG_H */
|
||||
|
||||
#if STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
/*
|
||||
malloc and free should be declared in stdlib.h,
|
||||
but if you've got a K&R compiler, they probably aren't.
|
||||
*/
|
||||
# ifdef MSDOS
|
||||
# include <malloc.h>
|
||||
# else
|
||||
# ifdef VMS
|
||||
extern char *malloc();
|
||||
extern void free();
|
||||
# else
|
||||
extern char *malloc();
|
||||
extern int free();
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Define NULL (for *very* old compilers). */
|
||||
#ifndef NULL
|
||||
# define NULL (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The ctype macros don't always handle 8-bit characters correctly.
|
||||
* Compensate for this here.
|
||||
*/
|
||||
#ifdef isascii
|
||||
# undef HAVE_ISASCII /* just in case */
|
||||
# define HAVE_ISASCII 1
|
||||
#else
|
||||
#endif
|
||||
#if STDC_HEADERS || !HAVE_ISASCII
|
||||
# define is_ascii(c) 1
|
||||
#else
|
||||
# define is_ascii(c) isascii(c)
|
||||
#endif
|
||||
|
||||
#define is_space(c) (is_ascii(c) && isspace(c))
|
||||
#define is_alpha(c) (is_ascii(c) && isalpha(c))
|
||||
#define is_alnum(c) (is_ascii(c) && isalnum(c))
|
||||
|
||||
/* Scanning macros */
|
||||
#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
|
||||
#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
|
||||
|
||||
/* Forward references */
|
||||
char *ppdirforward();
|
||||
char *ppdirbackward();
|
||||
char *skipspace();
|
||||
char *scanstring();
|
||||
int writeblanks();
|
||||
int test1();
|
||||
int convert1();
|
||||
|
||||
/* The main program */
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{ FILE *in = stdin;
|
||||
FILE *out = stdout;
|
||||
char *filename = 0;
|
||||
char *program_name = argv[0];
|
||||
char *output_name = 0;
|
||||
#define bufsize 5000 /* arbitrary size */
|
||||
char *buf;
|
||||
char *line;
|
||||
char *more;
|
||||
char *usage =
|
||||
"Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
|
||||
/*
|
||||
* In previous versions, ansi2knr recognized a --varargs switch.
|
||||
* If this switch was supplied, ansi2knr would attempt to convert
|
||||
* a ... argument to va_alist and va_dcl; if this switch was not
|
||||
* supplied, ansi2knr would simply drop any such arguments.
|
||||
* Now, ansi2knr always does this conversion, and we only
|
||||
* check for this switch for backward compatibility.
|
||||
*/
|
||||
int convert_varargs = 1;
|
||||
int output_error;
|
||||
|
||||
while ( argc > 1 && argv[1][0] == '-' ) {
|
||||
if ( !strcmp(argv[1], "--varargs") ) {
|
||||
convert_varargs = 1;
|
||||
argc--;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
|
||||
filename = argv[2];
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
|
||||
argv[1]);
|
||||
fprintf(stderr, usage);
|
||||
exit(1);
|
||||
}
|
||||
switch ( argc )
|
||||
{
|
||||
default:
|
||||
fprintf(stderr, usage);
|
||||
exit(0);
|
||||
case 3:
|
||||
output_name = argv[2];
|
||||
out = fopen(output_name, "w");
|
||||
if ( out == NULL ) {
|
||||
fprintf(stderr, "%s: Cannot open output file %s\n",
|
||||
program_name, output_name);
|
||||
exit(1);
|
||||
}
|
||||
/* falls through */
|
||||
case 2:
|
||||
in = fopen(argv[1], "r");
|
||||
if ( in == NULL ) {
|
||||
fprintf(stderr, "%s: Cannot open input file %s\n",
|
||||
program_name, argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
if ( filename == 0 )
|
||||
filename = argv[1];
|
||||
/* falls through */
|
||||
case 1:
|
||||
break;
|
||||
}
|
||||
if ( filename )
|
||||
fprintf(out, "#line 1 \"%s\"\n", filename);
|
||||
buf = malloc(bufsize);
|
||||
if ( buf == NULL )
|
||||
{
|
||||
fprintf(stderr, "Unable to allocate read buffer!\n");
|
||||
exit(1);
|
||||
}
|
||||
line = buf;
|
||||
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
|
||||
{
|
||||
test: line += strlen(line);
|
||||
switch ( test1(buf) )
|
||||
{
|
||||
case 2: /* a function header */
|
||||
convert1(buf, out, 1, convert_varargs);
|
||||
break;
|
||||
case 1: /* a function */
|
||||
/* Check for a { at the start of the next line. */
|
||||
more = ++line;
|
||||
f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
|
||||
goto wl;
|
||||
if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
|
||||
goto wl;
|
||||
switch ( *skipspace(ppdirforward(more), 1) )
|
||||
{
|
||||
case '{':
|
||||
/* Definitely a function header. */
|
||||
convert1(buf, out, 0, convert_varargs);
|
||||
fputs(more, out);
|
||||
break;
|
||||
case 0:
|
||||
/* The next line was blank or a comment: */
|
||||
/* keep scanning for a non-comment. */
|
||||
line += strlen(line);
|
||||
goto f;
|
||||
default:
|
||||
/* buf isn't a function header, but */
|
||||
/* more might be. */
|
||||
fputs(buf, out);
|
||||
strcpy(buf, more);
|
||||
line = buf;
|
||||
goto test;
|
||||
}
|
||||
break;
|
||||
case -1: /* maybe the start of a function */
|
||||
if ( line != buf + (bufsize - 1) ) /* overflow check */
|
||||
continue;
|
||||
/* falls through */
|
||||
default: /* not a function */
|
||||
wl: fputs(buf, out);
|
||||
break;
|
||||
}
|
||||
line = buf;
|
||||
}
|
||||
if ( line != buf )
|
||||
fputs(buf, out);
|
||||
free(buf);
|
||||
if ( output_name ) {
|
||||
output_error = ferror(out);
|
||||
output_error |= fclose(out);
|
||||
} else { /* out == stdout */
|
||||
fflush(out);
|
||||
output_error = ferror(out);
|
||||
}
|
||||
if ( output_error ) {
|
||||
fprintf(stderr, "%s: error writing to %s\n", program_name,
|
||||
(output_name ? output_name : "stdout"));
|
||||
exit(1);
|
||||
}
|
||||
if ( in != stdin )
|
||||
fclose(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip forward or backward over one or more preprocessor directives.
|
||||
*/
|
||||
char *
|
||||
ppdirforward(p)
|
||||
char *p;
|
||||
{
|
||||
for (; *p == '#'; ++p) {
|
||||
for (; *p != '\r' && *p != '\n'; ++p)
|
||||
if (*p == 0)
|
||||
return p;
|
||||
if (*p == '\r' && p[1] == '\n')
|
||||
++p;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
char *
|
||||
ppdirbackward(p, limit)
|
||||
char *p;
|
||||
char *limit;
|
||||
{
|
||||
char *np = p;
|
||||
|
||||
for (;; p = --np) {
|
||||
if (*np == '\n' && np[-1] == '\r')
|
||||
--np;
|
||||
for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
|
||||
if (np[-1] == 0)
|
||||
return np;
|
||||
if (*np != '#')
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip over whitespace, comments, and preprocessor directives,
|
||||
* in either direction.
|
||||
*/
|
||||
char *
|
||||
skipspace(p, dir)
|
||||
char *p;
|
||||
int dir; /* 1 for forward, -1 for backward */
|
||||
{
|
||||
for ( ; ; ) {
|
||||
while ( is_space(*p) )
|
||||
p += dir;
|
||||
if ( !(*p == '/' && p[dir] == '*') )
|
||||
break;
|
||||
p += dir; p += dir;
|
||||
while ( !(*p == '*' && p[dir] == '/') ) {
|
||||
if ( *p == 0 )
|
||||
return p; /* multi-line comment?? */
|
||||
p += dir;
|
||||
}
|
||||
p += dir; p += dir;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Scan over a quoted string, in either direction. */
|
||||
char *
|
||||
scanstring(p, dir)
|
||||
char *p;
|
||||
int dir;
|
||||
{
|
||||
for (p += dir; ; p += dir)
|
||||
if (*p == '"' && p[-dir] != '\\')
|
||||
return p + dir;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write blanks over part of a string.
|
||||
* Don't overwrite end-of-line characters.
|
||||
*/
|
||||
int
|
||||
writeblanks(start, end)
|
||||
char *start;
|
||||
char *end;
|
||||
{ char *p;
|
||||
for ( p = start; p < end; p++ )
|
||||
if ( *p != '\r' && *p != '\n' )
|
||||
*p = ' ';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether the string in buf is a function definition.
|
||||
* The string may contain and/or end with a newline.
|
||||
* Return as follows:
|
||||
* 0 - definitely not a function definition;
|
||||
* 1 - definitely a function definition;
|
||||
* 2 - definitely a function prototype (NOT USED);
|
||||
* -1 - may be the beginning of a function definition,
|
||||
* append another line and look again.
|
||||
* The reason we don't attempt to convert function prototypes is that
|
||||
* Ghostscript's declaration-generating macros look too much like
|
||||
* prototypes, and confuse the algorithms.
|
||||
*/
|
||||
int
|
||||
test1(buf)
|
||||
char *buf;
|
||||
{ char *p = buf;
|
||||
char *bend;
|
||||
char *endfn;
|
||||
int contin;
|
||||
|
||||
if ( !isidfirstchar(*p) )
|
||||
return 0; /* no name at left margin */
|
||||
bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
|
||||
switch ( *bend )
|
||||
{
|
||||
case ';': contin = 0 /*2*/; break;
|
||||
case ')': contin = 1; break;
|
||||
case '{': return 0; /* not a function */
|
||||
case '}': return 0; /* not a function */
|
||||
default: contin = -1;
|
||||
}
|
||||
while ( isidchar(*p) )
|
||||
p++;
|
||||
endfn = p;
|
||||
p = skipspace(p, 1);
|
||||
if ( *p++ != '(' )
|
||||
return 0; /* not a function */
|
||||
p = skipspace(p, 1);
|
||||
if ( *p == ')' )
|
||||
return 0; /* no parameters */
|
||||
/* Check that the apparent function name isn't a keyword. */
|
||||
/* We only need to check for keywords that could be followed */
|
||||
/* by a left parenthesis (which, unfortunately, is most of them). */
|
||||
{ static char *words[] =
|
||||
{ "asm", "auto", "case", "char", "const", "double",
|
||||
"extern", "float", "for", "if", "int", "long",
|
||||
"register", "return", "short", "signed", "sizeof",
|
||||
"static", "switch", "typedef", "unsigned",
|
||||
"void", "volatile", "while", 0
|
||||
};
|
||||
char **key = words;
|
||||
char *kp;
|
||||
unsigned len = endfn - buf;
|
||||
|
||||
while ( (kp = *key) != 0 )
|
||||
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
|
||||
return 0; /* name is a keyword */
|
||||
key++;
|
||||
}
|
||||
}
|
||||
{
|
||||
char *id = p;
|
||||
int len;
|
||||
/*
|
||||
* Check for identifier1(identifier2) and not
|
||||
* identifier1(void), or identifier1(identifier2, xxxx).
|
||||
*/
|
||||
|
||||
while ( isidchar(*p) )
|
||||
p++;
|
||||
len = p - id;
|
||||
p = skipspace(p, 1);
|
||||
if (*p == ',' ||
|
||||
(*p == ')' && (len != 4 || strncmp(id, "void", 4)))
|
||||
)
|
||||
return 0; /* not a function */
|
||||
}
|
||||
/*
|
||||
* If the last significant character was a ), we need to count
|
||||
* parentheses, because it might be part of a formal parameter
|
||||
* that is a procedure.
|
||||
*/
|
||||
if (contin > 0) {
|
||||
int level = 0;
|
||||
|
||||
for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1))
|
||||
level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
|
||||
if (level > 0)
|
||||
contin = -1;
|
||||
}
|
||||
return contin;
|
||||
}
|
||||
|
||||
/* Convert a recognized function definition or header to K&R syntax. */
|
||||
int
|
||||
convert1(buf, out, header, convert_varargs)
|
||||
char *buf;
|
||||
FILE *out;
|
||||
int header; /* Boolean */
|
||||
int convert_varargs; /* Boolean */
|
||||
{ char *endfn;
|
||||
char *p;
|
||||
/*
|
||||
* The breaks table contains pointers to the beginning and end
|
||||
* of each argument.
|
||||
*/
|
||||
char **breaks;
|
||||
unsigned num_breaks = 2; /* for testing */
|
||||
char **btop;
|
||||
char **bp;
|
||||
char **ap;
|
||||
char *vararg = 0;
|
||||
|
||||
/* Pre-ANSI implementations don't agree on whether strchr */
|
||||
/* is called strchr or index, so we open-code it here. */
|
||||
for ( endfn = buf; *(endfn++) != '('; )
|
||||
;
|
||||
top: p = endfn;
|
||||
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
|
||||
if ( breaks == NULL )
|
||||
{ /* Couldn't allocate break table, give up */
|
||||
fprintf(stderr, "Unable to allocate break table!\n");
|
||||
fputs(buf, out);
|
||||
return -1;
|
||||
}
|
||||
btop = breaks + num_breaks * 2 - 2;
|
||||
bp = breaks;
|
||||
/* Parse the argument list */
|
||||
do
|
||||
{ int level = 0;
|
||||
char *lp = NULL;
|
||||
char *rp = NULL;
|
||||
char *end = NULL;
|
||||
|
||||
if ( bp >= btop )
|
||||
{ /* Filled up break table. */
|
||||
/* Allocate a bigger one and start over. */
|
||||
free((char *)breaks);
|
||||
num_breaks <<= 1;
|
||||
goto top;
|
||||
}
|
||||
*bp++ = p;
|
||||
/* Find the end of the argument */
|
||||
for ( ; end == NULL; p++ )
|
||||
{ switch(*p)
|
||||
{
|
||||
case ',':
|
||||
if ( !level ) end = p;
|
||||
break;
|
||||
case '(':
|
||||
if ( !level ) lp = p;
|
||||
level++;
|
||||
break;
|
||||
case ')':
|
||||
if ( --level < 0 ) end = p;
|
||||
else rp = p;
|
||||
break;
|
||||
case '/':
|
||||
if (p[1] == '*')
|
||||
p = skipspace(p, 1) - 1;
|
||||
break;
|
||||
case '"':
|
||||
p = scanstring(p, 1) - 1;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
/* Erase any embedded prototype parameters. */
|
||||
if ( lp && rp )
|
||||
writeblanks(lp + 1, rp);
|
||||
p--; /* back up over terminator */
|
||||
/* Find the name being declared. */
|
||||
/* This is complicated because of procedure and */
|
||||
/* array modifiers. */
|
||||
for ( ; ; )
|
||||
{ p = skipspace(p - 1, -1);
|
||||
switch ( *p )
|
||||
{
|
||||
case ']': /* skip array dimension(s) */
|
||||
case ')': /* skip procedure args OR name */
|
||||
{ int level = 1;
|
||||
while ( level )
|
||||
switch ( *--p )
|
||||
{
|
||||
case ']': case ')':
|
||||
level++;
|
||||
break;
|
||||
case '[': case '(':
|
||||
level--;
|
||||
break;
|
||||
case '/':
|
||||
if (p > buf && p[-1] == '*')
|
||||
p = skipspace(p, -1) + 1;
|
||||
break;
|
||||
case '"':
|
||||
p = scanstring(p, -1) + 1;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
|
||||
{ /* We found the name being declared */
|
||||
while ( !isidfirstchar(*p) )
|
||||
p = skipspace(p, 1) + 1;
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
|
||||
{ if ( convert_varargs )
|
||||
{ *bp++ = "va_alist";
|
||||
vararg = p-2;
|
||||
}
|
||||
else
|
||||
{ p++;
|
||||
if ( bp == breaks + 1 ) /* sole argument */
|
||||
writeblanks(breaks[0], p);
|
||||
else
|
||||
writeblanks(bp[-1] - 1, p);
|
||||
bp--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ while ( isidchar(*p) ) p--;
|
||||
*bp++ = p+1;
|
||||
}
|
||||
p = end;
|
||||
}
|
||||
while ( *p++ == ',' );
|
||||
*bp = p;
|
||||
/* Make a special check for 'void' arglist */
|
||||
if ( bp == breaks+2 )
|
||||
{ p = skipspace(breaks[0], 1);
|
||||
if ( !strncmp(p, "void", 4) )
|
||||
{ p = skipspace(p+4, 1);
|
||||
if ( p == breaks[2] - 1 )
|
||||
{ bp = breaks; /* yup, pretend arglist is empty */
|
||||
writeblanks(breaks[0], p + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Put out the function name and left parenthesis. */
|
||||
p = buf;
|
||||
while ( p != endfn ) putc(*p, out), p++;
|
||||
/* Put out the declaration. */
|
||||
if ( header )
|
||||
{ fputs(");", out);
|
||||
for ( p = breaks[0]; *p; p++ )
|
||||
if ( *p == '\r' || *p == '\n' )
|
||||
putc(*p, out);
|
||||
}
|
||||
else
|
||||
{ for ( ap = breaks+1; ap < bp; ap += 2 )
|
||||
{ p = *ap;
|
||||
while ( isidchar(*p) )
|
||||
putc(*p, out), p++;
|
||||
if ( ap < bp - 1 )
|
||||
fputs(", ", out);
|
||||
}
|
||||
fputs(") ", out);
|
||||
/* Put out the argument declarations */
|
||||
for ( ap = breaks+2; ap <= bp; ap += 2 )
|
||||
(*ap)[-1] = ';';
|
||||
if ( vararg != 0 )
|
||||
{ *vararg = 0;
|
||||
fputs(breaks[0], out); /* any prior args */
|
||||
fputs("va_dcl", out); /* the final arg */
|
||||
fputs(bp[0], out);
|
||||
}
|
||||
else
|
||||
fputs(breaks[0], out);
|
||||
}
|
||||
free((char *)breaks);
|
||||
return 0;
|
||||
}
|
||||
163
src/arith.c
163
src/arith.c
@@ -1,163 +0,0 @@
|
||||
/* Arithmetic for numbers greater than a long int, for GNU tar.
|
||||
Copyright (C) 1996, 1997 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 Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "system.h"
|
||||
|
||||
/* common.h is needed to define FATAL_ERROR. It also includes arith.h. */
|
||||
#include "common.h"
|
||||
|
||||
/* GNU tar needs handling numbers exceeding 32 bits, which is the size of
|
||||
unsigned long ints for many C compilers. This module should provide
|
||||
machinery for handling at least BITS_PER_TARLONG bits per number. If
|
||||
`long long' ints are available and are sufficient for the task, they will
|
||||
be used preferrably.
|
||||
|
||||
Russell Cattelan reports 165 Gb single tapes (digital video D2 tapes on
|
||||
Ampex drives), so requiring 38 bits for the tape length in bytes. He
|
||||
also reports breaking the terabyte limit with a single file (using SGI
|
||||
xFS file system over 37 28GB disk arrays attached to a Power Challenge
|
||||
XL; check out http://www.lcse.umn.edu/ for a picture), so requiring a
|
||||
little more than 40 bits for the file size in bytes. The POSIX header
|
||||
structure allows for 12 octal digits to represent file lengths, that is,
|
||||
up to 36 bits for the byte size of files.
|
||||
|
||||
If `long long' is not supported by the compiler, SIZEOF_LONG_LONG will be
|
||||
set to zero by configure. In this case, or if `long long' ints does not
|
||||
have enough bits, then huge numbers are rather represented by an array of
|
||||
longs, with the least significant super-digit at position 0. For making
|
||||
multiplication and decimal input/output easy, the base of a super-digit
|
||||
is an exact exponent of 10, and is such that base*base fits in a long. */
|
||||
|
||||
#if SUPERDIGIT
|
||||
|
||||
/*-------------------------------.
|
||||
| Check if ACCUMULATOR is zero. |
|
||||
`-------------------------------*/
|
||||
|
||||
int
|
||||
zerop_tarlong_helper (unsigned long *accumulator)
|
||||
{
|
||||
int counter;
|
||||
|
||||
for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
|
||||
if (accumulator[counter])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------.
|
||||
| Check if FIRST is strictly less than SECOND. |
|
||||
`----------------------------------------------*/
|
||||
|
||||
int
|
||||
lessp_tarlong_helper (unsigned long *first, unsigned long *second)
|
||||
{
|
||||
int counter;
|
||||
|
||||
for (counter = LONGS_PER_TARLONG - 1; counter >= 0; counter--)
|
||||
if (first[counter] != second[counter])
|
||||
return first[counter] < second[counter];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------.
|
||||
| Reset ACCUMULATOR to zero. |
|
||||
`----------------------------*/
|
||||
|
||||
void
|
||||
clear_tarlong_helper (unsigned long *accumulator)
|
||||
{
|
||||
int counter;
|
||||
|
||||
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
|
||||
accumulator[counter] = 0;
|
||||
}
|
||||
|
||||
/*----------------------------.
|
||||
| To ACCUMULATOR, add VALUE. |
|
||||
`----------------------------*/
|
||||
|
||||
void
|
||||
add_to_tarlong_helper (unsigned long *accumulator, int value)
|
||||
{
|
||||
int counter;
|
||||
|
||||
if (value < 0)
|
||||
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
|
||||
{
|
||||
if (accumulator[counter] >= -value)
|
||||
{
|
||||
accumulator[counter] += value;
|
||||
return;
|
||||
}
|
||||
accumulator[counter] += value + SUPERDIGIT;
|
||||
value = -1;
|
||||
}
|
||||
else
|
||||
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
|
||||
{
|
||||
if (accumulator[counter] + value < SUPERDIGIT)
|
||||
{
|
||||
accumulator[counter] += value;
|
||||
return;
|
||||
}
|
||||
accumulator[counter] += value - SUPERDIGIT;
|
||||
value = 1;
|
||||
}
|
||||
FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
|
||||
}
|
||||
|
||||
/*--------------------------------.
|
||||
| Multiply ACCUMULATOR by VALUE. |
|
||||
`--------------------------------*/
|
||||
|
||||
void
|
||||
mult_tarlong_helper (unsigned long *accumulator, int value)
|
||||
{
|
||||
int carry = 0;
|
||||
int counter;
|
||||
|
||||
for (counter = 0; counter < LONGS_PER_TARLONG; counter++)
|
||||
{
|
||||
carry += accumulator[counter] * value;
|
||||
accumulator[counter] = carry % SUPERDIGIT;
|
||||
carry /= SUPERDIGIT;
|
||||
}
|
||||
if (carry)
|
||||
FATAL_ERROR ((0, 0, _("Arithmetic overflow")));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------.
|
||||
| Print the decimal representation of ACCUMULATOR on FILE. |
|
||||
`----------------------------------------------------------*/
|
||||
|
||||
void
|
||||
print_tarlong_helper (unsigned long *accumulator, FILE *file)
|
||||
{
|
||||
int counter = LONGS_PER_TARLONG - 1;
|
||||
|
||||
while (counter > 0 && accumulator[counter] == 0)
|
||||
counter--;
|
||||
|
||||
fprintf (file, "%uld", accumulator[counter]);
|
||||
while (counter > 0)
|
||||
fprintf (file, TARLONG_FORMAT, accumulator[--counter]);
|
||||
}
|
||||
|
||||
#endif /* SUPERDIGIT */
|
||||
224
src/buffer.c
224
src/buffer.c
@@ -1,7 +1,8 @@
|
||||
/* Buffer management for tar.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-08-25.
|
||||
|
||||
@@ -35,9 +36,6 @@
|
||||
/* Number of retries before giving up on read. */
|
||||
#define READ_ERROR_MAX 10
|
||||
|
||||
/* Globbing pattern to append to volume label if initial match failed. */
|
||||
#define VOLUME_LABEL_APPEND " Volume [1-9]*"
|
||||
|
||||
/* Variables. */
|
||||
|
||||
static tarlong prev_written; /* bytes written on previous volumes */
|
||||
@@ -203,8 +201,10 @@ enum compress_type {
|
||||
ct_compress,
|
||||
ct_gzip,
|
||||
ct_bzip2,
|
||||
ct_lzip,
|
||||
ct_lzma,
|
||||
ct_lzop
|
||||
ct_lzop,
|
||||
ct_xz
|
||||
};
|
||||
|
||||
struct zip_magic
|
||||
@@ -219,11 +219,13 @@ struct zip_magic
|
||||
static struct zip_magic const magic[] = {
|
||||
{ ct_tar },
|
||||
{ ct_none, },
|
||||
{ ct_compress, 2, "\037\235", "compress", "-Z" },
|
||||
{ ct_gzip, 2, "\037\213", "gzip", "-z" },
|
||||
{ ct_bzip2, 3, "BZh", "bzip2", "-j" },
|
||||
{ ct_lzma, 6, "\xFFLZMA", "lzma", "-J" }, /* FIXME: ???? */
|
||||
{ ct_lzop, 4, "\211LZO", "lzop", "--lzop" },
|
||||
{ ct_compress, 2, "\037\235", COMPRESS_PROGRAM, "-Z" },
|
||||
{ ct_gzip, 2, "\037\213", GZIP_PROGRAM, "-z" },
|
||||
{ ct_bzip2, 3, "BZh", BZIP2_PROGRAM, "-j" },
|
||||
{ ct_lzip, 4, "LZIP", LZIP_PROGRAM, "--lzip" },
|
||||
{ ct_lzma, 6, "\xFFLZMA", LZMA_PROGRAM, "--lzma" },
|
||||
{ ct_lzop, 4, "\211LZO", LZOP_PROGRAM, "--lzop" },
|
||||
{ ct_xz, 6, "\0xFD7zXZ", XZ_PROGRAM, "-J" },
|
||||
};
|
||||
|
||||
#define NMAGIC (sizeof(magic)/sizeof(magic[0]))
|
||||
@@ -263,6 +265,37 @@ check_compressed_archive (bool *pshort)
|
||||
return ct_none;
|
||||
}
|
||||
|
||||
/* Guess if the archive is seekable. */
|
||||
static void
|
||||
guess_seekable_archive ()
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (subcommand_option == DELETE_SUBCOMMAND)
|
||||
{
|
||||
/* The current code in delete.c is based on the assumption that
|
||||
skip_member() reads all data from the archive. So, we should
|
||||
make sure it won't use seeks. On the other hand, the same code
|
||||
depends on the ability to backspace a record in the archive,
|
||||
so setting seekable_archive to false is technically incorrect.
|
||||
However, it is tested only in skip_member(), so it's not a
|
||||
problem. */
|
||||
seekable_archive = false;
|
||||
}
|
||||
|
||||
if (seek_option != -1)
|
||||
{
|
||||
seekable_archive = !!seek_option;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!multi_volume_option && !use_compress_program_option
|
||||
&& fstat (archive, &st) == 0)
|
||||
seekable_archive = S_ISREG (st.st_mode);
|
||||
else
|
||||
seekable_archive = false;
|
||||
}
|
||||
|
||||
/* Open an archive named archive_name_array[0]. Detect if it is
|
||||
a compressed archive of known type and use corresponding decompression
|
||||
program if so */
|
||||
@@ -293,7 +326,7 @@ open_compressed_archive ()
|
||||
ERROR ((0, 0, _("This does not look like a tar archive")));
|
||||
set_comression_program_by_suffix (archive_name_array[0], NULL);
|
||||
if (!use_compress_program_option)
|
||||
return archive;
|
||||
return archive;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -304,7 +337,7 @@ open_compressed_archive ()
|
||||
|
||||
/* FD is not needed any more */
|
||||
rmtclose (archive);
|
||||
|
||||
|
||||
hit_eof = false; /* It might have been set by find_next_block in
|
||||
check_compressed_archive */
|
||||
|
||||
@@ -563,6 +596,8 @@ _open_archive (enum access_mode wanted_access)
|
||||
{
|
||||
case ACCESS_READ:
|
||||
archive = open_compressed_archive ();
|
||||
if (archive >= 0)
|
||||
guess_seekable_archive ();
|
||||
break;
|
||||
|
||||
case ACCESS_WRITE:
|
||||
@@ -677,6 +712,19 @@ archive_read_error (void)
|
||||
return;
|
||||
}
|
||||
|
||||
static bool
|
||||
archive_is_dev ()
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (fstat (archive, &st))
|
||||
{
|
||||
stat_diag (*archive_name_cursor);
|
||||
return false;
|
||||
}
|
||||
return S_ISBLK (st.st_mode) || S_ISCHR (st.st_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
short_read (size_t status)
|
||||
{
|
||||
@@ -688,7 +736,8 @@ short_read (size_t status)
|
||||
|
||||
if (left && left % BLOCKSIZE == 0
|
||||
&& verbose_option
|
||||
&& record_start_block == 0 && status != 0)
|
||||
&& record_start_block == 0 && status != 0
|
||||
&& archive_is_dev ())
|
||||
{
|
||||
unsigned long rsize = status / BLOCKSIZE;
|
||||
WARN ((0, 0,
|
||||
@@ -807,16 +856,16 @@ seek_archive (off_t size)
|
||||
off_t start = current_block_ordinal ();
|
||||
off_t offset;
|
||||
off_t nrec, nblk;
|
||||
off_t skipped = (blocking_factor - (current_block - record_start));
|
||||
off_t skipped = (blocking_factor - (current_block - record_start))
|
||||
* BLOCKSIZE;
|
||||
|
||||
size -= skipped * BLOCKSIZE;
|
||||
|
||||
if (size < record_size)
|
||||
if (size <= skipped)
|
||||
return 0;
|
||||
/* FIXME: flush? */
|
||||
|
||||
|
||||
/* Compute number of records to skip */
|
||||
nrec = size / record_size;
|
||||
nrec = (size - skipped) / record_size;
|
||||
if (nrec == 0)
|
||||
return 0;
|
||||
offset = rmtlseek (archive, nrec * record_size, SEEK_CUR);
|
||||
if (offset < 0)
|
||||
return offset;
|
||||
@@ -1082,6 +1131,7 @@ new_volume (enum access_mode mode)
|
||||
case ACCESS_READ:
|
||||
archive = rmtopen (*archive_name_cursor, O_RDONLY, MODE_RW,
|
||||
rsh_command_option);
|
||||
guess_seekable_archive ();
|
||||
break;
|
||||
|
||||
case ACCESS_WRITE:
|
||||
@@ -1117,7 +1167,7 @@ read_header0 (struct tar_stat_info *info)
|
||||
enum read_header rc;
|
||||
|
||||
tar_stat_init (info);
|
||||
rc = read_header_primitive (false, info);
|
||||
rc = read_header (¤t_header, info, read_header_auto);
|
||||
if (rc == HEADER_SUCCESS)
|
||||
{
|
||||
set_next_block_after (current_header);
|
||||
@@ -1165,17 +1215,42 @@ try_new_volume ()
|
||||
{
|
||||
case XGLTYPE:
|
||||
{
|
||||
if (!read_header0 (&dummy))
|
||||
return false;
|
||||
tar_stat_init (&dummy);
|
||||
if (read_header (&header, &dummy, read_header_x_global)
|
||||
!= HEADER_SUCCESS_EXTENDED)
|
||||
{
|
||||
ERROR ((0, 0, _("This does not look like a tar archive")));
|
||||
return false;
|
||||
}
|
||||
|
||||
xheader_decode (&dummy); /* decodes values from the global header */
|
||||
tar_stat_destroy (&dummy);
|
||||
if (!real_s_name)
|
||||
{
|
||||
/* We have read the extended header of the first member in
|
||||
this volume. Put it back, so next read_header works as
|
||||
expected. */
|
||||
current_block = record_start;
|
||||
}
|
||||
|
||||
/* The initial global header must be immediately followed by
|
||||
an extended PAX header for the first member in this volume.
|
||||
However, in some cases tar may split volumes in the middle
|
||||
of a PAX header. This is incorrect, and should be fixed
|
||||
in the future versions. In the meantime we must be
|
||||
prepared to correctly list and extract such archives.
|
||||
|
||||
If this happens, the following call to read_header returns
|
||||
HEADER_FAILURE, which is ignored.
|
||||
|
||||
See also tests/multiv07.at */
|
||||
|
||||
switch (read_header (&header, &dummy, read_header_auto))
|
||||
{
|
||||
case HEADER_SUCCESS:
|
||||
set_next_block_after (header);
|
||||
break;
|
||||
|
||||
case HEADER_FAILURE:
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR ((0, 0, _("This does not look like a tar archive")));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1262,31 +1337,57 @@ try_new_volume ()
|
||||
}
|
||||
|
||||
|
||||
/* Check the LABEL block against the volume label, seen as a globbing
|
||||
#define VOLUME_TEXT " Volume "
|
||||
#define VOLUME_TEXT_LEN (sizeof VOLUME_TEXT - 1)
|
||||
|
||||
char *
|
||||
drop_volume_label_suffix (const char *label)
|
||||
{
|
||||
const char *p;
|
||||
size_t len = strlen (label);
|
||||
|
||||
if (len < 1)
|
||||
return NULL;
|
||||
|
||||
for (p = label + len - 1; p > label && isdigit ((unsigned char) *p); p--)
|
||||
;
|
||||
if (p > label && p - (VOLUME_TEXT_LEN - 1) > label)
|
||||
{
|
||||
p -= VOLUME_TEXT_LEN - 1;
|
||||
if (memcmp (p, VOLUME_TEXT, VOLUME_TEXT_LEN) == 0)
|
||||
{
|
||||
char *s = xmalloc ((len = p - label) + 1);
|
||||
memcpy (s, label, len);
|
||||
s[len] = 0;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check LABEL against the volume label, seen as a globbing
|
||||
pattern. Return true if the pattern matches. In case of failure,
|
||||
retry matching a volume sequence number before giving up in
|
||||
multi-volume mode. */
|
||||
static bool
|
||||
check_label_pattern (union block *label)
|
||||
check_label_pattern (const char *label)
|
||||
{
|
||||
char *string;
|
||||
bool result;
|
||||
|
||||
if (! memchr (label->header.name, '\0', sizeof label->header.name))
|
||||
return false;
|
||||
|
||||
if (fnmatch (volume_label_option, label->header.name, 0) == 0)
|
||||
if (fnmatch (volume_label_option, label, 0) == 0)
|
||||
return true;
|
||||
|
||||
if (!multi_volume_option)
|
||||
return false;
|
||||
|
||||
string = xmalloc (strlen (volume_label_option)
|
||||
+ sizeof VOLUME_LABEL_APPEND + 1);
|
||||
strcpy (string, volume_label_option);
|
||||
strcat (string, VOLUME_LABEL_APPEND);
|
||||
result = fnmatch (string, label->header.name, 0) == 0;
|
||||
free (string);
|
||||
string = drop_volume_label_suffix (label);
|
||||
if (string)
|
||||
{
|
||||
result = fnmatch (string, volume_label_option, 0) == 0;
|
||||
free (string);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1295,14 +1396,43 @@ check_label_pattern (union block *label)
|
||||
static void
|
||||
match_volume_label (void)
|
||||
{
|
||||
union block *label = find_next_block ();
|
||||
|
||||
if (!label)
|
||||
if (!volume_label)
|
||||
{
|
||||
union block *label = find_next_block ();
|
||||
|
||||
if (!label)
|
||||
FATAL_ERROR ((0, 0, _("Archive not labeled to match %s"),
|
||||
quote (volume_label_option)));
|
||||
if (label->header.typeflag == GNUTYPE_VOLHDR)
|
||||
{
|
||||
if (memchr (label->header.name, '\0', sizeof label->header.name))
|
||||
assign_string (&volume_label, label->header.name);
|
||||
else
|
||||
{
|
||||
volume_label = xmalloc (sizeof (label->header.name) + 1);
|
||||
memcpy (volume_label, label->header.name,
|
||||
sizeof (label->header.name));
|
||||
volume_label[sizeof (label->header.name)] = 0;
|
||||
}
|
||||
}
|
||||
else if (label->header.typeflag == XGLTYPE)
|
||||
{
|
||||
struct tar_stat_info st;
|
||||
tar_stat_init (&st);
|
||||
xheader_read (&st.xhdr, label,
|
||||
OFF_FROM_HEADER (label->header.size));
|
||||
xheader_decode (&st);
|
||||
tar_stat_destroy (&st);
|
||||
}
|
||||
}
|
||||
|
||||
if (!volume_label)
|
||||
FATAL_ERROR ((0, 0, _("Archive not labeled to match %s"),
|
||||
quote (volume_label_option)));
|
||||
if (!check_label_pattern (label))
|
||||
|
||||
if (!check_label_pattern (volume_label))
|
||||
FATAL_ERROR ((0, 0, _("Volume %s does not match %s"),
|
||||
quote_n (0, label->header.name),
|
||||
quote_n (0, volume_label),
|
||||
quote_n (1, volume_label_option)));
|
||||
}
|
||||
|
||||
|
||||
159
src/common.h
159
src/common.h
@@ -1,7 +1,8 @@
|
||||
/* Common declarations for the tar program.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
|
||||
@@ -60,6 +61,8 @@
|
||||
#define obstack_chunk_alloc xmalloc
|
||||
#define obstack_chunk_free free
|
||||
#include <obstack.h>
|
||||
#include <progname.h>
|
||||
#include <xvasprintf.h>
|
||||
|
||||
#include <paxlib.h>
|
||||
|
||||
@@ -70,9 +73,6 @@
|
||||
|
||||
/* Information gleaned from the command line. */
|
||||
|
||||
/* Name of this program. */
|
||||
GLOBAL const char *program_name;
|
||||
|
||||
/* Main command option. */
|
||||
|
||||
enum subcommand
|
||||
@@ -85,7 +85,8 @@ enum subcommand
|
||||
DIFF_SUBCOMMAND, /* -d */
|
||||
EXTRACT_SUBCOMMAND, /* -x */
|
||||
LIST_SUBCOMMAND, /* -t */
|
||||
UPDATE_SUBCOMMAND /* -u */
|
||||
UPDATE_SUBCOMMAND, /* -u */
|
||||
TEST_LABEL_SUBCOMMAND, /* --test-label */
|
||||
};
|
||||
|
||||
GLOBAL enum subcommand subcommand_option;
|
||||
@@ -185,6 +186,8 @@ GLOBAL enum old_files old_files_option;
|
||||
|
||||
/* Specified file name for incremental list. */
|
||||
GLOBAL const char *listed_incremental_option;
|
||||
/* Incremental dump level */
|
||||
GLOBAL int incremental_level;
|
||||
/* Check device numbers when doing incremental dumps. */
|
||||
GLOBAL bool check_device_option;
|
||||
|
||||
@@ -318,25 +321,41 @@ GLOBAL const char **archive_name_cursor;
|
||||
/* Output index file name. */
|
||||
GLOBAL char const *index_file_name;
|
||||
|
||||
/* Opaque structure for keeping directory meta-data */
|
||||
struct directory;
|
||||
|
||||
/* Structure for keeping track of filenames and lists thereof. */
|
||||
struct name
|
||||
{
|
||||
struct name *next; /* Link to the next element */
|
||||
struct name *prev; /* Link to the previous element */
|
||||
|
||||
char *name; /* File name or globbing pattern */
|
||||
size_t length; /* cached strlen (name) */
|
||||
int matching_flags; /* wildcard flags if name is a pattern */
|
||||
bool cmdline; /* true if this name was given in the
|
||||
command line */
|
||||
|
||||
int change_dir; /* Number of the directory to change to.
|
||||
Set with the -C option. */
|
||||
uintmax_t found_count; /* number of times a matching file has
|
||||
been found */
|
||||
int matching_flags; /* this name is a regexp, not literal */
|
||||
char const *dir_contents; /* for incremental_option */
|
||||
|
||||
size_t length; /* cached strlen(name) */
|
||||
char name[1];
|
||||
|
||||
/* The following members are used for incremental dumps only,
|
||||
if this struct name represents a directory;
|
||||
see incremen.c */
|
||||
struct directory *directory;/* directory meta-data and contents */
|
||||
struct name *parent; /* pointer to the parent hierarchy */
|
||||
struct name *child; /* pointer to the first child */
|
||||
struct name *sibling; /* pointer to the next sibling */
|
||||
char *caname; /* canonical name */
|
||||
};
|
||||
|
||||
/* Obnoxious test to see if dimwit is trying to dump the archive. */
|
||||
GLOBAL dev_t ar_dev;
|
||||
GLOBAL ino_t ar_ino;
|
||||
|
||||
GLOBAL int seek_option;
|
||||
GLOBAL bool seekable_archive;
|
||||
|
||||
GLOBAL dev_t root_device;
|
||||
@@ -344,8 +363,6 @@ GLOBAL dev_t root_device;
|
||||
/* Unquote filenames */
|
||||
GLOBAL bool unquote_option;
|
||||
|
||||
GLOBAL bool test_label_option; /* Test archive volume label and exit */
|
||||
|
||||
/* Show file or archive names after transformation.
|
||||
In particular, when creating archive in verbose mode, list member names
|
||||
as stored in the archive */
|
||||
@@ -379,9 +396,13 @@ extern enum access_mode access_mode;
|
||||
extern FILE *stdlis;
|
||||
extern bool write_archive_to_stdout;
|
||||
extern char *volume_label;
|
||||
extern size_t volume_label_count;
|
||||
extern char *continued_file_name;
|
||||
extern uintmax_t continued_file_size;
|
||||
extern uintmax_t continued_file_offset;
|
||||
extern off_t records_written;
|
||||
|
||||
char *drop_volume_label_suffix (const char *label);
|
||||
|
||||
size_t available_space_after (union block *pointer);
|
||||
off_t current_block_ordinal (void);
|
||||
@@ -428,19 +449,19 @@ bool cachedir_file_p (const char *name);
|
||||
bool file_dumpable_p (struct tar_stat_info *st);
|
||||
void create_archive (void);
|
||||
void pad_archive (off_t size_left);
|
||||
void dump_file (const char *st, int top_level, dev_t parent_device);
|
||||
void dump_file (const char *st, bool top_level, dev_t parent_device);
|
||||
union block *start_header (struct tar_stat_info *st);
|
||||
void finish_header (struct tar_stat_info *st, union block *header,
|
||||
off_t block_ordinal);
|
||||
void simple_finish_header (union block *header);
|
||||
union block * write_extended (bool global, struct tar_stat_info *st,
|
||||
union block *old_header);
|
||||
union block *start_private_header (const char *name, size_t size);
|
||||
union block *start_private_header (const char *name, size_t size, time_t t);
|
||||
void write_eot (void);
|
||||
void check_links (void);
|
||||
void exclusion_tag_warning (const char *dirname, const char *tagname,
|
||||
const char *message);
|
||||
enum exclusion_tag_type check_exclusion_tags (char *dirname,
|
||||
enum exclusion_tag_type check_exclusion_tags (const char *dirname,
|
||||
const char **tag_file_name);
|
||||
|
||||
#define GID_TO_CHARS(val, where) gid_to_chars (val, where, sizeof (where))
|
||||
@@ -496,9 +517,16 @@ char *dumpdir_locate (dumpdir_t dump, const char *name);
|
||||
char *dumpdir_next (dumpdir_iter_t itr);
|
||||
char *dumpdir_first (dumpdir_t dump, int all, dumpdir_iter_t *pitr);
|
||||
|
||||
struct directory *scan_directory (char *dir, dev_t device, bool cmdline);
|
||||
void name_fill_directory (struct name *name, dev_t device, bool cmdline);
|
||||
const char *directory_contents (struct directory *dir);
|
||||
const char *safe_directory_contents (struct directory *dir);
|
||||
|
||||
const char *get_directory_contents (char *dir_name, dev_t device);
|
||||
const char *append_incremental_renames (const char *dump);
|
||||
void rebase_directory (struct directory *dir,
|
||||
const char *samp, size_t slen,
|
||||
const char *repl, size_t rlen);
|
||||
|
||||
void append_incremental_renames (struct directory *dir);
|
||||
void read_directory_file (void);
|
||||
void write_directory_file (void);
|
||||
void purge_directory (char const *directory_name);
|
||||
@@ -520,6 +548,17 @@ enum read_header
|
||||
HEADER_FAILURE /* ill-formed header, or bad checksum */
|
||||
};
|
||||
|
||||
/* Operation mode for read_header: */
|
||||
|
||||
enum read_header_mode
|
||||
{
|
||||
read_header_auto, /* process extended headers automatically */
|
||||
read_header_x_raw, /* return raw extended headers (return
|
||||
HEADER_SUCCESS_EXTENDED) */
|
||||
read_header_x_global /* when POSIX global extended header is read,
|
||||
decode it and return
|
||||
HEADER_SUCCESS_EXTENDED */
|
||||
};
|
||||
extern union block *current_header;
|
||||
extern enum archive_format current_format;
|
||||
extern size_t recent_long_name_blocks;
|
||||
@@ -532,7 +571,8 @@ char const *tartime (struct timespec t, bool full_time);
|
||||
#define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
|
||||
#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
|
||||
#define MINOR_FROM_HEADER(where) minor_from_header (where, sizeof (where))
|
||||
#define MODE_FROM_HEADER(where) mode_from_header (where, sizeof (where))
|
||||
#define MODE_FROM_HEADER(where, hbits) \
|
||||
mode_from_header (where, sizeof (where), hbits)
|
||||
#define OFF_FROM_HEADER(where) off_from_header (where, sizeof (where))
|
||||
#define SIZE_FROM_HEADER(where) size_from_header (where, sizeof (where))
|
||||
#define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
|
||||
@@ -542,20 +582,22 @@ char const *tartime (struct timespec t, bool full_time);
|
||||
gid_t gid_from_header (const char *buf, size_t size);
|
||||
major_t major_from_header (const char *buf, size_t size);
|
||||
minor_t minor_from_header (const char *buf, size_t size);
|
||||
mode_t mode_from_header (const char *buf, size_t size);
|
||||
mode_t mode_from_header (const char *buf, size_t size, unsigned *hbits);
|
||||
off_t off_from_header (const char *buf, size_t size);
|
||||
size_t size_from_header (const char *buf, size_t size);
|
||||
time_t time_from_header (const char *buf, size_t size);
|
||||
uid_t uid_from_header (const char *buf, size_t size);
|
||||
uintmax_t uintmax_from_header (const char * buf, size_t size);
|
||||
uintmax_t uintmax_from_header (const char *buf, size_t size);
|
||||
|
||||
void list_archive (void);
|
||||
void test_archive_label (void);
|
||||
void print_for_mkdir (char *dirname, int length, mode_t mode);
|
||||
void print_header (struct tar_stat_info *st, off_t block_ordinal);
|
||||
void print_header (struct tar_stat_info *st, union block *blk,
|
||||
off_t block_ordinal);
|
||||
void read_and (void (*do_something) (void));
|
||||
enum read_header read_header_primitive (bool raw_extended_headers,
|
||||
struct tar_stat_info *info);
|
||||
enum read_header read_header (bool raw_extended_headers);
|
||||
enum read_header read_header (union block **return_block,
|
||||
struct tar_stat_info *info,
|
||||
enum read_header_mode m);
|
||||
enum read_header tar_checksum (union block *header, bool silent);
|
||||
void skip_file (off_t size);
|
||||
void skip_member (void);
|
||||
@@ -565,6 +607,15 @@ void skip_member (void);
|
||||
void assign_string (char **dest, const char *src);
|
||||
char *quote_copy_string (const char *str);
|
||||
int unquote_string (char *str);
|
||||
char *zap_slashes (char *name);
|
||||
char *normalize_filename (const char *name);
|
||||
void replace_prefix (char **pname, const char *samp, size_t slen,
|
||||
const char *repl, size_t rlen);
|
||||
|
||||
typedef struct namebuf *namebuf_t;
|
||||
namebuf_t namebuf_create (const char *dir);
|
||||
void namebuf_free (namebuf_t buf);
|
||||
char *namebuf_name (namebuf_t buf, const char *name);
|
||||
|
||||
void code_ns_fraction (int ns, char *p);
|
||||
char const *code_timespec (struct timespec ts, char *sbuf);
|
||||
@@ -594,6 +645,7 @@ int deref_stat (bool deref, char const *name, struct stat *buf);
|
||||
|
||||
int chdir_arg (char const *dir);
|
||||
void chdir_do (int dir);
|
||||
int chdir_count (void);
|
||||
|
||||
void close_diag (char const *name);
|
||||
void open_diag (char const *name);
|
||||
@@ -602,6 +654,10 @@ void readlink_diag (char const *name);
|
||||
void savedir_diag (char const *name);
|
||||
void seek_diag_details (char const *name, off_t offset);
|
||||
void stat_diag (char const *name);
|
||||
void file_removed_diag (const char *name, bool top_level,
|
||||
void (*diagfn) (char const *name));
|
||||
void dir_removed_diag (char const *name, bool top_level,
|
||||
void (*diagfn) (char const *name));
|
||||
void write_error_details (char const *name, size_t status, size_t size);
|
||||
void write_fatal (char const *name) __attribute__ ((noreturn));
|
||||
void write_fatal_details (char const *name, ssize_t status, size_t size)
|
||||
@@ -629,12 +685,14 @@ void name_add_dir (const char *name);
|
||||
void name_term (void);
|
||||
const char *name_next (int change_dirs);
|
||||
void name_gather (void);
|
||||
struct name *addname (char const *string, int change_dir);
|
||||
struct name *addname (char const *string, int change_dir,
|
||||
bool cmdline, struct name *parent);
|
||||
void remname (struct name *name);
|
||||
bool name_match (const char *name);
|
||||
void names_notfound (void);
|
||||
void collect_and_sort_names (void);
|
||||
struct name *name_scan (const char *name);
|
||||
char *name_from_list (void);
|
||||
struct name const *name_from_list (void);
|
||||
void blank_name_list (void);
|
||||
char *new_name (const char *dir_name, const char *name);
|
||||
size_t stripped_prefix_len (char const *file_name, size_t num);
|
||||
@@ -666,6 +724,7 @@ void usage (int) __attribute__ ((noreturn));
|
||||
int tar_timespec_cmp (struct timespec a, struct timespec b);
|
||||
const char *archive_format_string (enum archive_format fmt);
|
||||
const char *subcommand_string (enum subcommand c);
|
||||
void set_exit_status (int val);
|
||||
|
||||
/* Module update.c. */
|
||||
|
||||
@@ -681,7 +740,7 @@ void xheader_decode_global (struct xheader *xhdr);
|
||||
void xheader_store (char const *keyword, struct tar_stat_info *st,
|
||||
void const *data);
|
||||
void xheader_read (struct xheader *xhdr, union block *header, size_t size);
|
||||
void xheader_write (char type, char *name, struct xheader *xhdr);
|
||||
void xheader_write (char type, char *name, time_t t, struct xheader *xhdr);
|
||||
void xheader_write_global (struct xheader *xhdr);
|
||||
void xheader_finish (struct xheader *hdr);
|
||||
void xheader_destroy (struct xheader *hdr);
|
||||
@@ -752,3 +811,49 @@ void set_comression_program_by_suffix (const char *name, const char *defprog);
|
||||
void checkpoint_compile_action (const char *str);
|
||||
void checkpoint_finish_compile (void);
|
||||
void checkpoint_run (bool do_write);
|
||||
|
||||
/* Module warning.c */
|
||||
#define WARN_ALONE_ZERO_BLOCK 0x00000001
|
||||
#define WARN_BAD_DUMPDIR 0x00000002
|
||||
#define WARN_CACHEDIR 0x00000004
|
||||
#define WARN_CONTIGUOUS_CAST 0x00000008
|
||||
#define WARN_FILE_CHANGED 0x00000010
|
||||
#define WARN_FILE_IGNORED 0x00000020
|
||||
#define WARN_FILE_REMOVED 0x00000040
|
||||
#define WARN_FILE_SHRANK 0x00000080
|
||||
#define WARN_FILE_UNCHANGED 0x00000100
|
||||
#define WARN_FILENAME_WITH_NULS 0x00000200
|
||||
#define WARN_IGNORE_ARCHIVE 0x00000400
|
||||
#define WARN_IGNORE_NEWER 0x00000800
|
||||
#define WARN_NEW_DIRECTORY 0x00001000
|
||||
#define WARN_RENAME_DIRECTORY 0x00002000
|
||||
#define WARN_SYMLINK_CAST 0x00004000
|
||||
#define WARN_TIMESTAMP 0x00008000
|
||||
#define WARN_UNKNOWN_CAST 0x00010000
|
||||
#define WARN_UNKNOWN_KEYWORD 0x00020000
|
||||
#define WARN_XDEV 0x00040000
|
||||
|
||||
/* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
|
||||
in verbose mode */
|
||||
#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY)
|
||||
#define WARN_ALL (0xffffffff & ~WARN_VERBOSE_WARNINGS)
|
||||
|
||||
void set_warning_option (const char *arg);
|
||||
|
||||
extern int warning_option;
|
||||
|
||||
#define WARNOPT(opt,args) \
|
||||
do \
|
||||
{ \
|
||||
if (warning_option & opt) WARN (args); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Module unlink.c */
|
||||
|
||||
void queue_deferred_unlink (const char *name, bool is_dir);
|
||||
void finish_deferred_unlinks (void);
|
||||
|
||||
/* Module exit.c */
|
||||
extern void (*fatal_exit_hook) (void);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Diff files from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1987-04-30.
|
||||
|
||||
@@ -66,8 +66,7 @@ report_difference (struct tar_stat_info *st, const char *fmt, ...)
|
||||
fprintf (stdlis, "\n");
|
||||
}
|
||||
|
||||
if (exit_status == TAREXIT_SUCCESS)
|
||||
exit_status = TAREXIT_DIFFERS;
|
||||
set_exit_status (TAREXIT_DIFFERS);
|
||||
}
|
||||
|
||||
/* Take a buffer returned by read_and_process and do nothing with it. */
|
||||
@@ -380,7 +379,8 @@ diff_dumpdir (void)
|
||||
else
|
||||
dev = stat_data.st_dev;
|
||||
|
||||
dumpdir_buffer = get_directory_contents (current_stat_info.file_name, dev);
|
||||
dumpdir_buffer = directory_contents
|
||||
(scan_directory (current_stat_info.file_name, dev, false));
|
||||
|
||||
if (dumpdir_buffer)
|
||||
{
|
||||
@@ -460,7 +460,7 @@ diff_archive (void)
|
||||
{
|
||||
if (now_verifying)
|
||||
fprintf (stdlis, _("Verify "));
|
||||
print_header (¤t_stat_info, -1);
|
||||
print_header (¤t_stat_info, current_header, -1);
|
||||
}
|
||||
|
||||
switch (current_header->header.typeflag)
|
||||
@@ -578,7 +578,9 @@ verify_volume (void)
|
||||
flush_read ();
|
||||
while (1)
|
||||
{
|
||||
enum read_header status = read_header (false);
|
||||
enum read_header status = read_header (¤t_header,
|
||||
¤t_stat_info,
|
||||
read_header_auto);
|
||||
|
||||
if (status == HEADER_FAILURE)
|
||||
{
|
||||
@@ -588,7 +590,8 @@ verify_volume (void)
|
||||
{
|
||||
counter++;
|
||||
set_next_block_after (current_header);
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
}
|
||||
while (status == HEADER_FAILURE);
|
||||
|
||||
@@ -606,11 +609,13 @@ verify_volume (void)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
if (status == HEADER_ZERO_BLOCK)
|
||||
break;
|
||||
WARN ((0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
WARNOPT (WARN_ALONE_ZERO_BLOCK,
|
||||
(0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
362
src/create.c
362
src/create.c
@@ -1,7 +1,7 @@
|
||||
/* Create a tar archive.
|
||||
|
||||
Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-08-25.
|
||||
|
||||
@@ -63,22 +63,23 @@ exclusion_tag_warning (const char *dirname, const char *tagname,
|
||||
const char *message)
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0,
|
||||
_("%s: contains a cache directory tag %s; %s"),
|
||||
quotearg_colon (dirname),
|
||||
quotearg_n (1, tagname),
|
||||
message));
|
||||
WARNOPT (WARN_CACHEDIR,
|
||||
(0, 0,
|
||||
_("%s: contains a cache directory tag %s; %s"),
|
||||
quotearg_colon (dirname),
|
||||
quotearg_n (1, tagname),
|
||||
message));
|
||||
}
|
||||
|
||||
enum exclusion_tag_type
|
||||
check_exclusion_tags (char *dirname, const char **tag_file_name)
|
||||
check_exclusion_tags (const char *dirname, const char **tag_file_name)
|
||||
{
|
||||
static char *tagname;
|
||||
static size_t tagsize;
|
||||
struct exclusion_tag *tag;
|
||||
size_t dlen = strlen (dirname);
|
||||
int addslash = dirname[dlen-1] != '/';
|
||||
char *nptr = NULL;
|
||||
int addslash = !ISSLASH (dirname[dlen-1]);
|
||||
size_t noff = 0;
|
||||
|
||||
for (tag = exclusion_tags; tag; tag = tag->next)
|
||||
{
|
||||
@@ -89,14 +90,14 @@ check_exclusion_tags (char *dirname, const char **tag_file_name)
|
||||
tagname = xrealloc (tagname, tagsize);
|
||||
}
|
||||
|
||||
if (!nptr)
|
||||
if (noff == 0)
|
||||
{
|
||||
strcpy (tagname, dirname);
|
||||
nptr = tagname + dlen;
|
||||
noff = dlen;
|
||||
if (addslash)
|
||||
*nptr++ = '/';
|
||||
tagname[noff++] = '/';
|
||||
}
|
||||
strcpy (nptr, tag->name);
|
||||
strcpy (tagname + noff, tag->name);
|
||||
if (access (tagname, F_OK) == 0
|
||||
&& (!tag->predicate || tag->predicate (tagname)))
|
||||
{
|
||||
@@ -401,8 +402,7 @@ mode_to_chars (mode_t v, char *p, size_t s)
|
||||
&& S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC
|
||||
&& archive_format != POSIX_FORMAT
|
||||
&& archive_format != USTAR_FORMAT
|
||||
&& archive_format != GNU_FORMAT
|
||||
&& archive_format != OLDGNU_FORMAT)
|
||||
&& archive_format != GNU_FORMAT)
|
||||
{
|
||||
negative = v < 0;
|
||||
u = v;
|
||||
@@ -515,9 +515,8 @@ write_eot (void)
|
||||
|
||||
/* Write a "private" header */
|
||||
union block *
|
||||
start_private_header (const char *name, size_t size)
|
||||
start_private_header (const char *name, size_t size, time_t t)
|
||||
{
|
||||
time_t t;
|
||||
union block *header = find_next_block ();
|
||||
|
||||
memset (header->buffer, 0, sizeof (union block));
|
||||
@@ -525,7 +524,6 @@ start_private_header (const char *name, size_t size)
|
||||
tar_name_copy_str (header->header.name, name, NAME_FIELD_SIZE);
|
||||
OFF_TO_CHARS (size, header->header.size);
|
||||
|
||||
time (&t);
|
||||
TIME_TO_CHARS (t, header->header.mtime);
|
||||
MODE_TO_CHARS (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, header->header.mode);
|
||||
UID_TO_CHARS (getuid (), header->header.uid);
|
||||
@@ -563,13 +561,13 @@ write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
|
||||
union block *header;
|
||||
char *tmpname;
|
||||
|
||||
header = start_private_header ("././@LongLink", size);
|
||||
FILL(header->header.mtime, '0');
|
||||
FILL(header->header.mode, '0');
|
||||
FILL(header->header.uid, '0');
|
||||
FILL(header->header.gid, '0');
|
||||
FILL(header->header.devmajor, 0);
|
||||
FILL(header->header.devminor, 0);
|
||||
header = start_private_header ("././@LongLink", size, time (NULL));
|
||||
FILL (header->header.mtime, '0');
|
||||
FILL (header->header.mode, '0');
|
||||
FILL (header->header.uid, '0');
|
||||
FILL (header->header.gid, '0');
|
||||
FILL (header->header.devmajor, 0);
|
||||
FILL (header->header.devminor, 0);
|
||||
uid_to_uname (0, &tmpname);
|
||||
UNAME_TO_CHARS (tmpname, header->header.uname);
|
||||
free (tmpname);
|
||||
@@ -604,8 +602,10 @@ split_long_name (const char *name, size_t length)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (length > PREFIX_FIELD_SIZE)
|
||||
if (length > PREFIX_FIELD_SIZE + 1)
|
||||
length = PREFIX_FIELD_SIZE + 1;
|
||||
else if (ISSLASH (name[length - 1]))
|
||||
length--;
|
||||
for (i = length - 1; i > 0; i--)
|
||||
if (ISSLASH (name[i]))
|
||||
break;
|
||||
@@ -616,9 +616,9 @@ static union block *
|
||||
write_ustar_long_name (const char *name)
|
||||
{
|
||||
size_t length = strlen (name);
|
||||
size_t i;
|
||||
size_t i, nlen;
|
||||
union block *header;
|
||||
|
||||
|
||||
if (length > PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1)
|
||||
{
|
||||
ERROR ((0, 0, _("%s: file name is too long (max %d); not dumped"),
|
||||
@@ -628,7 +628,7 @@ write_ustar_long_name (const char *name)
|
||||
}
|
||||
|
||||
i = split_long_name (name, length);
|
||||
if (i == 0 || length - i - 1 > NAME_FIELD_SIZE)
|
||||
if (i == 0 || (nlen = length - i - 1) > NAME_FIELD_SIZE || nlen == 0)
|
||||
{
|
||||
ERROR ((0, 0,
|
||||
_("%s: file name is too long (cannot be split); not dumped"),
|
||||
@@ -712,7 +712,8 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
|
||||
union block *header, hp;
|
||||
char *p;
|
||||
int type;
|
||||
|
||||
time_t t;
|
||||
|
||||
if (st->xhdr.buffer || st->xhdr.stk == NULL)
|
||||
return old_header;
|
||||
|
||||
@@ -722,13 +723,15 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
|
||||
{
|
||||
type = XGLTYPE;
|
||||
p = xheader_ghdr_name ();
|
||||
time (&t);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = XHDTYPE;
|
||||
p = xheader_xhdr_name (st);
|
||||
t = st->stat.st_mtime;
|
||||
}
|
||||
xheader_write (type, p, &st->xhdr);
|
||||
xheader_write (type, p, t, &st->xhdr);
|
||||
free (p);
|
||||
header = find_next_block ();
|
||||
memcpy (header, &hp.buffer, sizeof (hp.buffer));
|
||||
@@ -993,11 +996,9 @@ finish_header (struct tar_stat_info *st,
|
||||
&& header->header.typeflag != XHDTYPE
|
||||
&& header->header.typeflag != XGLTYPE)
|
||||
{
|
||||
/* These globals are parameters to print_header, sigh. */
|
||||
|
||||
current_header = header;
|
||||
/* FIXME: This global is used in print_header, sigh. */
|
||||
current_format = archive_format;
|
||||
print_header (st, block_ordinal);
|
||||
print_header (st, header, block_ordinal);
|
||||
}
|
||||
|
||||
header = write_extended (false, st, header);
|
||||
@@ -1072,14 +1073,15 @@ dump_regular_file (int fd, struct tar_stat_info *st)
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
memset (blk->buffer + count, 0, bufsize - count);
|
||||
WARN ((0, 0,
|
||||
ngettext ("%s: File shrank by %s byte; padding with zeros",
|
||||
"%s: File shrank by %s bytes; padding with zeros",
|
||||
size_left),
|
||||
quotearg_colon (st->orig_file_name),
|
||||
STRINGIFY_BIGINT (size_left, buf)));
|
||||
WARNOPT (WARN_FILE_SHRANK,
|
||||
(0, 0,
|
||||
ngettext ("%s: File shrank by %s byte; padding with zeros",
|
||||
"%s: File shrank by %s bytes; padding with zeros",
|
||||
size_left),
|
||||
quotearg_colon (st->orig_file_name),
|
||||
STRINGIFY_BIGINT (size_left, buf)));
|
||||
if (! ignore_failed_read_option)
|
||||
exit_status = TAREXIT_DIFFERS;
|
||||
set_exit_status (TAREXIT_DIFFERS);
|
||||
pad_archive (size_left - (bufsize - count));
|
||||
return dump_status_short;
|
||||
}
|
||||
@@ -1090,79 +1092,74 @@ dump_regular_file (int fd, struct tar_stat_info *st)
|
||||
|
||||
static void
|
||||
dump_dir0 (char *directory,
|
||||
struct tar_stat_info *st, int top_level, dev_t parent_device)
|
||||
struct tar_stat_info *st, bool top_level, dev_t parent_device)
|
||||
{
|
||||
dev_t our_device = st->stat.st_dev;
|
||||
const char *tag_file_name;
|
||||
|
||||
if (!is_avoided_name (st->orig_file_name))
|
||||
union block *blk = NULL;
|
||||
off_t block_ordinal = current_block_ordinal ();
|
||||
|
||||
st->stat.st_size = 0; /* force 0 size on dir */
|
||||
|
||||
blk = start_header (st);
|
||||
if (!blk)
|
||||
return;
|
||||
|
||||
if (incremental_option && archive_format != POSIX_FORMAT)
|
||||
blk->header.typeflag = GNUTYPE_DUMPDIR;
|
||||
else /* if (standard_option) */
|
||||
blk->header.typeflag = DIRTYPE;
|
||||
|
||||
/* If we're gnudumping, we aren't done yet so don't close it. */
|
||||
|
||||
if (!incremental_option)
|
||||
finish_header (st, blk, block_ordinal);
|
||||
else if (gnu_list_name->directory)
|
||||
{
|
||||
union block *blk = NULL;
|
||||
off_t block_ordinal = current_block_ordinal ();
|
||||
st->stat.st_size = 0; /* force 0 size on dir */
|
||||
|
||||
blk = start_header (st);
|
||||
if (!blk)
|
||||
return;
|
||||
|
||||
if (incremental_option && archive_format != POSIX_FORMAT)
|
||||
blk->header.typeflag = GNUTYPE_DUMPDIR;
|
||||
else /* if (standard_option) */
|
||||
blk->header.typeflag = DIRTYPE;
|
||||
|
||||
/* If we're gnudumping, we aren't done yet so don't close it. */
|
||||
|
||||
if (!incremental_option)
|
||||
finish_header (st, blk, block_ordinal);
|
||||
else if (gnu_list_name->dir_contents)
|
||||
if (archive_format == POSIX_FORMAT)
|
||||
{
|
||||
if (archive_format == POSIX_FORMAT)
|
||||
{
|
||||
xheader_store ("GNU.dumpdir", st, gnu_list_name->dir_contents);
|
||||
finish_header (st, blk, block_ordinal);
|
||||
}
|
||||
else
|
||||
{
|
||||
off_t size_left;
|
||||
off_t totsize;
|
||||
size_t bufsize;
|
||||
ssize_t count;
|
||||
const char *buffer, *p_buffer;
|
||||
|
||||
block_ordinal = current_block_ordinal ();
|
||||
buffer = gnu_list_name->dir_contents;
|
||||
if (buffer)
|
||||
totsize = dumpdir_size (buffer);
|
||||
else
|
||||
totsize = 0;
|
||||
OFF_TO_CHARS (totsize, blk->header.size);
|
||||
finish_header (st, blk, block_ordinal);
|
||||
p_buffer = buffer;
|
||||
size_left = totsize;
|
||||
|
||||
mv_begin (st);
|
||||
mv_total_size (totsize);
|
||||
while (size_left > 0)
|
||||
{
|
||||
mv_size_left (size_left);
|
||||
blk = find_next_block ();
|
||||
bufsize = available_space_after (blk);
|
||||
if (size_left < bufsize)
|
||||
{
|
||||
bufsize = size_left;
|
||||
count = bufsize % BLOCKSIZE;
|
||||
if (count)
|
||||
memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
|
||||
}
|
||||
memcpy (blk->buffer, p_buffer, bufsize);
|
||||
size_left -= bufsize;
|
||||
p_buffer += bufsize;
|
||||
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
|
||||
}
|
||||
mv_end ();
|
||||
}
|
||||
return;
|
||||
xheader_store ("GNU.dumpdir", st,
|
||||
safe_directory_contents (gnu_list_name->directory));
|
||||
finish_header (st, blk, block_ordinal);
|
||||
}
|
||||
else
|
||||
{
|
||||
off_t size_left;
|
||||
off_t totsize;
|
||||
size_t bufsize;
|
||||
ssize_t count;
|
||||
const char *buffer, *p_buffer;
|
||||
|
||||
block_ordinal = current_block_ordinal ();
|
||||
buffer = safe_directory_contents (gnu_list_name->directory);
|
||||
totsize = dumpdir_size (buffer);
|
||||
OFF_TO_CHARS (totsize, blk->header.size);
|
||||
finish_header (st, blk, block_ordinal);
|
||||
p_buffer = buffer;
|
||||
size_left = totsize;
|
||||
|
||||
mv_begin (st);
|
||||
mv_total_size (totsize);
|
||||
while (size_left > 0)
|
||||
{
|
||||
mv_size_left (size_left);
|
||||
blk = find_next_block ();
|
||||
bufsize = available_space_after (blk);
|
||||
if (size_left < bufsize)
|
||||
{
|
||||
bufsize = size_left;
|
||||
count = bufsize % BLOCKSIZE;
|
||||
if (count)
|
||||
memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
|
||||
}
|
||||
memcpy (blk->buffer, p_buffer, bufsize);
|
||||
size_left -= bufsize;
|
||||
p_buffer += bufsize;
|
||||
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
|
||||
}
|
||||
mv_end ();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!recursion_option)
|
||||
@@ -1173,9 +1170,10 @@ dump_dir0 (char *directory,
|
||||
&& parent_device != st->stat.st_dev)
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0,
|
||||
_("%s: file is on a different filesystem; not dumped"),
|
||||
quotearg_colon (st->orig_file_name)));
|
||||
WARNOPT (WARN_XDEV,
|
||||
(0, 0,
|
||||
_("%s: file is on a different filesystem; not dumped"),
|
||||
quotearg_colon (st->orig_file_name)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1209,7 +1207,7 @@ dump_dir0 (char *directory,
|
||||
}
|
||||
strcpy (name_buf + name_len, entry);
|
||||
if (!excluded_name (name_buf))
|
||||
dump_file (name_buf, 0, our_device);
|
||||
dump_file (name_buf, false, our_device);
|
||||
}
|
||||
|
||||
free (name_buf);
|
||||
@@ -1223,7 +1221,7 @@ dump_dir0 (char *directory,
|
||||
name_buf = xmalloc (name_size);
|
||||
strcpy (name_buf, st->orig_file_name);
|
||||
strcat (name_buf, tag_file_name);
|
||||
dump_file (name_buf, 0, our_device);
|
||||
dump_file (name_buf, false, our_device);
|
||||
free (name_buf);
|
||||
break;
|
||||
|
||||
@@ -1249,7 +1247,8 @@ ensure_slash (char **pstr)
|
||||
}
|
||||
|
||||
static bool
|
||||
dump_dir (int fd, struct tar_stat_info *st, int top_level, dev_t parent_device)
|
||||
dump_dir (int fd, struct tar_stat_info *st, bool top_level,
|
||||
dev_t parent_device)
|
||||
{
|
||||
char *directory = fdsavedir (fd);
|
||||
if (!directory)
|
||||
@@ -1270,7 +1269,7 @@ dump_dir (int fd, struct tar_stat_info *st, int top_level, dev_t parent_device)
|
||||
void
|
||||
create_archive (void)
|
||||
{
|
||||
const char *p;
|
||||
struct name const *p;
|
||||
|
||||
open_archive (ACCESS_WRITE);
|
||||
buffer_write_global_xheader ();
|
||||
@@ -1284,24 +1283,24 @@ create_archive (void)
|
||||
collect_and_sort_names ();
|
||||
|
||||
while ((p = name_from_list ()) != NULL)
|
||||
if (!excluded_name (p))
|
||||
dump_file (p, -1, (dev_t) 0);
|
||||
if (!excluded_name (p->name))
|
||||
dump_file (p->name, p->cmdline, (dev_t) 0);
|
||||
|
||||
blank_name_list ();
|
||||
while ((p = name_from_list ()) != NULL)
|
||||
if (!excluded_name (p))
|
||||
if (!excluded_name (p->name))
|
||||
{
|
||||
size_t plen = strlen (p);
|
||||
size_t plen = strlen (p->name);
|
||||
if (buffer_size <= plen)
|
||||
{
|
||||
while ((buffer_size *= 2) <= plen)
|
||||
continue;
|
||||
buffer = xrealloc (buffer, buffer_size);
|
||||
}
|
||||
memcpy (buffer, p, plen);
|
||||
memcpy (buffer, p->name, plen);
|
||||
if (! ISSLASH (buffer[plen - 1]))
|
||||
buffer[plen++] = '/';
|
||||
q = gnu_list_name->dir_contents;
|
||||
buffer[plen++] = DIRECTORY_SEPARATOR;
|
||||
q = directory_contents (gnu_list_name->directory);
|
||||
if (q)
|
||||
while (*q)
|
||||
{
|
||||
@@ -1315,7 +1314,7 @@ create_archive (void)
|
||||
buffer = xrealloc (buffer, buffer_size);
|
||||
}
|
||||
strcpy (buffer + plen, q + 1);
|
||||
dump_file (buffer, -1, (dev_t) 0);
|
||||
dump_file (buffer, false, (dev_t) 0);
|
||||
}
|
||||
q += qlen + 1;
|
||||
}
|
||||
@@ -1324,14 +1323,15 @@ create_archive (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((p = name_next (1)) != NULL)
|
||||
if (!excluded_name (p))
|
||||
dump_file (p, 1, (dev_t) 0);
|
||||
const char *name;
|
||||
while ((name = name_next (1)) != NULL)
|
||||
if (!excluded_name (name))
|
||||
dump_file (name, true, (dev_t) 0);
|
||||
}
|
||||
|
||||
write_eot ();
|
||||
close_archive ();
|
||||
|
||||
finish_deferred_unlinks ();
|
||||
if (listed_incremental_option)
|
||||
write_directory_file ();
|
||||
}
|
||||
@@ -1358,10 +1358,11 @@ compare_links (void const *entry1, void const *entry2)
|
||||
static void
|
||||
unknown_file_error (char const *p)
|
||||
{
|
||||
WARN ((0, 0, _("%s: Unknown file type; file ignored"),
|
||||
quotearg_colon (p)));
|
||||
WARNOPT (WARN_FILE_IGNORED,
|
||||
(0, 0, _("%s: Unknown file type; file ignored"),
|
||||
quotearg_colon (p)));
|
||||
if (!ignore_failed_read_option)
|
||||
exit_status = TAREXIT_FAILURE;
|
||||
set_exit_status (TAREXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1377,7 +1378,7 @@ static Hash_table *link_table;
|
||||
static bool
|
||||
dump_hard_link (struct tar_stat_info *st)
|
||||
{
|
||||
if (link_table && st->stat.st_nlink > 1)
|
||||
if (link_table && (st->stat.st_nlink > 1 || remove_files_option))
|
||||
{
|
||||
struct link lp;
|
||||
struct link *duplicate;
|
||||
@@ -1410,8 +1411,8 @@ dump_hard_link (struct tar_stat_info *st)
|
||||
blk->header.typeflag = LNKTYPE;
|
||||
finish_header (st, blk, block_ordinal);
|
||||
|
||||
if (remove_files_option && unlink (st->orig_file_name) != 0)
|
||||
unlink_error (st->orig_file_name);
|
||||
if (remove_files_option)
|
||||
queue_deferred_unlink (st->orig_file_name, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1427,19 +1428,26 @@ file_count_links (struct tar_stat_info *st)
|
||||
if (st->stat.st_nlink > 1)
|
||||
{
|
||||
struct link *duplicate;
|
||||
struct link *lp = xmalloc (offsetof (struct link, name)
|
||||
+ strlen (st->orig_file_name) + 1);
|
||||
char *linkname = NULL;
|
||||
struct link *lp;
|
||||
|
||||
assign_string (&linkname, st->orig_file_name);
|
||||
transform_name (&linkname, XFORM_LINK);
|
||||
|
||||
lp = xmalloc (offsetof (struct link, name)
|
||||
+ strlen (linkname) + 1);
|
||||
lp->ino = st->stat.st_ino;
|
||||
lp->dev = st->stat.st_dev;
|
||||
lp->nlink = st->stat.st_nlink;
|
||||
strcpy (lp->name, st->orig_file_name);
|
||||
|
||||
strcpy (lp->name, linkname);
|
||||
free (linkname);
|
||||
|
||||
if (! ((link_table
|
||||
|| (link_table = hash_initialize (0, 0, hash_link,
|
||||
compare_links, 0)))
|
||||
&& (duplicate = hash_insert (link_table, lp))))
|
||||
xalloc_die ();
|
||||
|
||||
|
||||
if (duplicate != lp)
|
||||
abort ();
|
||||
lp->nlink--;
|
||||
@@ -1461,12 +1469,11 @@ check_links (void)
|
||||
{
|
||||
if (lp->nlink)
|
||||
{
|
||||
WARN ((0, 0, _("Missing links to %s.\n"), quote (lp->name)));
|
||||
WARN ((0, 0, _("Missing links to %s."), quote (lp->name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Dump a single file, recursing on directories. P is the file name
|
||||
to dump. TOP_LEVEL tells whether this is a top-level call; zero
|
||||
means no, positive means yes, and negative means the top level
|
||||
@@ -1478,7 +1485,7 @@ check_links (void)
|
||||
|
||||
static void
|
||||
dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
int top_level, dev_t parent_device)
|
||||
bool top_level, dev_t parent_device)
|
||||
{
|
||||
union block *header;
|
||||
char type;
|
||||
@@ -1499,7 +1506,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
|
||||
if (deref_stat (dereference_option, p, &st->stat) != 0)
|
||||
{
|
||||
stat_diag (p);
|
||||
file_removed_diag (p, top_level, stat_diag);
|
||||
return;
|
||||
}
|
||||
st->archive_file_size = original_size = st->stat.st_size;
|
||||
@@ -1522,32 +1529,31 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
|
||||
/* See if we want only new files, and check if this one is too old to
|
||||
put in the archive.
|
||||
|
||||
|
||||
This check is omitted if incremental_option is set *and* the
|
||||
requested file is not explicitely listed in the command line. */
|
||||
|
||||
|
||||
if (!(incremental_option && !is_individual_file (p))
|
||||
&& !S_ISDIR (st->stat.st_mode)
|
||||
&& OLDER_TAR_STAT_TIME (*st, m)
|
||||
&& (!after_date_option || OLDER_TAR_STAT_TIME (*st, c)))
|
||||
{
|
||||
if (!incremental_option && verbose_option)
|
||||
WARN ((0, 0, _("%s: file is unchanged; not dumped"),
|
||||
quotearg_colon (p)));
|
||||
WARNOPT (WARN_FILE_UNCHANGED,
|
||||
(0, 0, _("%s: file is unchanged; not dumped"),
|
||||
quotearg_colon (p)));
|
||||
return;
|
||||
}
|
||||
|
||||
/* See if we are trying to dump the archive. */
|
||||
if (sys_file_is_archive (st))
|
||||
{
|
||||
WARN ((0, 0, _("%s: file is the archive; not dumped"),
|
||||
quotearg_colon (p)));
|
||||
WARNOPT (WARN_IGNORE_ARCHIVE,
|
||||
(0, 0, _("%s: file is the archive; not dumped"),
|
||||
quotearg_colon (p)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_avoided_name (p))
|
||||
return;
|
||||
|
||||
is_dir = S_ISDIR (st->stat.st_mode) != 0;
|
||||
|
||||
if (!is_dir && dump_hard_link (st))
|
||||
@@ -1569,11 +1575,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
: 0)));
|
||||
if (fd < 0)
|
||||
{
|
||||
if (!top_level && errno == ENOENT)
|
||||
WARN ((0, 0, _("%s: File removed before we read it"),
|
||||
quotearg_colon (p)));
|
||||
else
|
||||
open_diag (p);
|
||||
file_removed_diag (p, top_level, open_diag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1589,6 +1591,8 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
{
|
||||
exclusion_tag_warning (st->orig_file_name, tag_file_name,
|
||||
_("directory not dumped"));
|
||||
if (fd >= 0)
|
||||
close (fd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1643,7 +1647,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
: fstat (fd, &final_stat))
|
||||
!= 0)
|
||||
{
|
||||
stat_diag (p);
|
||||
file_removed_diag (p, top_level, stat_diag);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
@@ -1656,10 +1660,10 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
&& !(remove_files_option && is_dir))
|
||||
|| original_size < final_stat.st_size)
|
||||
{
|
||||
WARN ((0, 0, _("%s: file changed as we read it"),
|
||||
quotearg_colon (p)));
|
||||
if (exit_status == TAREXIT_SUCCESS)
|
||||
exit_status = TAREXIT_DIFFERS;
|
||||
WARNOPT (WARN_FILE_CHANGED,
|
||||
(0, 0, _("%s: file changed as we read it"),
|
||||
quotearg_colon (p)));
|
||||
set_exit_status (TAREXIT_DIFFERS);
|
||||
}
|
||||
else if (atime_preserve_option == replace_atime_preserve
|
||||
&& set_file_atime (fd, p, restore_times) != 0)
|
||||
@@ -1673,18 +1677,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
}
|
||||
|
||||
if (ok && remove_files_option)
|
||||
{
|
||||
if (is_dir)
|
||||
{
|
||||
if (rmdir (p) != 0 && errno != ENOTEMPTY)
|
||||
rmdir_error (p);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlink (p) != 0)
|
||||
unlink_error (p);
|
||||
}
|
||||
}
|
||||
queue_deferred_unlink (p, is_dir);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1700,7 +1693,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
size = readlink (p, buffer, linklen + 1);
|
||||
if (size < 0)
|
||||
{
|
||||
readlink_diag (p);
|
||||
file_removed_diag (p, top_level, readlink_diag);
|
||||
return;
|
||||
}
|
||||
buffer[size] = '\0';
|
||||
@@ -1720,10 +1713,8 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
/* nothing more to do to it */
|
||||
|
||||
if (remove_files_option)
|
||||
{
|
||||
if (unlink (p) == -1)
|
||||
unlink_error (p);
|
||||
}
|
||||
queue_deferred_unlink (p, false);
|
||||
|
||||
file_count_links (st);
|
||||
return;
|
||||
}
|
||||
@@ -1736,12 +1727,14 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
type = FIFOTYPE;
|
||||
else if (S_ISSOCK (st->stat.st_mode))
|
||||
{
|
||||
WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
|
||||
WARNOPT (WARN_FILE_IGNORED,
|
||||
(0, 0, _("%s: socket ignored"), quotearg_colon (p)));
|
||||
return;
|
||||
}
|
||||
else if (S_ISDOOR (st->stat.st_mode))
|
||||
{
|
||||
WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
|
||||
WARNOPT (WARN_FILE_IGNORED,
|
||||
(0, 0, _("%s: door ignored"), quotearg_colon (p)));
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -1773,14 +1766,11 @@ dump_file0 (struct tar_stat_info *st, const char *p,
|
||||
|
||||
finish_header (st, header, block_ordinal);
|
||||
if (remove_files_option)
|
||||
{
|
||||
if (unlink (p) == -1)
|
||||
unlink_error (p);
|
||||
}
|
||||
queue_deferred_unlink (p, false);
|
||||
}
|
||||
|
||||
void
|
||||
dump_file (const char *p, int top_level, dev_t parent_device)
|
||||
dump_file (const char *p, bool top_level, dev_t parent_device)
|
||||
{
|
||||
struct tar_stat_info st;
|
||||
tar_stat_init (&st);
|
||||
|
||||
10
src/delete.c
10
src/delete.c
@@ -1,7 +1,7 @@
|
||||
/* Delete entries from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003, 2004,
|
||||
2005, 2006 Free Software Foundation, Inc.
|
||||
2005, 2006, 2010 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
|
||||
@@ -35,7 +35,6 @@ extern union block *current_block;
|
||||
extern union block *recent_long_name;
|
||||
extern union block *recent_long_link;
|
||||
extern off_t records_read;
|
||||
extern off_t records_written;
|
||||
|
||||
/* The number of records skipped at the start of the archive, when
|
||||
passing over members that are not deleted. */
|
||||
@@ -166,7 +165,9 @@ delete_archive_members (void)
|
||||
|
||||
do
|
||||
{
|
||||
enum read_header status = read_header (true);
|
||||
enum read_header status = read_header (¤t_header,
|
||||
¤t_stat_info,
|
||||
read_header_x_raw);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
@@ -261,7 +262,8 @@ delete_archive_members (void)
|
||||
|
||||
if (current_block == record_end)
|
||||
flush_archive ();
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
|
||||
xheader_decode (¤t_stat_info);
|
||||
|
||||
|
||||
759
src/diffarch.c
759
src/diffarch.c
@@ -1,759 +0,0 @@
|
||||
/* Diff files from a tar archive.
|
||||
Copyright (C) 1988, 1992, 1993 Free Software Foundation
|
||||
|
||||
This file is part of GNU Tar.
|
||||
|
||||
GNU Tar 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.
|
||||
|
||||
GNU Tar 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 GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
* Diff files from a tar archive.
|
||||
*
|
||||
* Written 30 April 1987 by John Gilmore, ihnp4!hoptoad!gnu.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#ifndef STDC_HEADERS
|
||||
extern int errno;
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef BSD42
|
||||
#include <sys/file.h>
|
||||
#else
|
||||
#ifndef V7
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_MTIO_H
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mtio.h>
|
||||
#endif
|
||||
|
||||
#include "tar.h"
|
||||
#include "port.h"
|
||||
#include "rmt.h"
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define lstat stat
|
||||
#endif
|
||||
|
||||
extern void *valloc ();
|
||||
|
||||
extern union record *head; /* Points to current tape header */
|
||||
extern struct stat hstat; /* Stat struct corresponding */
|
||||
extern int head_standard; /* Tape header is in ANSI format */
|
||||
|
||||
void decode_header ();
|
||||
void diff_sparse_files ();
|
||||
void fill_in_sparse_array ();
|
||||
void fl_read ();
|
||||
long from_oct ();
|
||||
int do_stat ();
|
||||
extern void print_header ();
|
||||
int read_header ();
|
||||
void saverec ();
|
||||
void sigh ();
|
||||
extern void skip_file ();
|
||||
extern void skip_extended_headers ();
|
||||
int wantbytes ();
|
||||
|
||||
extern FILE *msg_file;
|
||||
|
||||
int now_verifying = 0; /* Are we verifying at the moment? */
|
||||
|
||||
int diff_fd; /* Descriptor of file we're diffing */
|
||||
|
||||
char *diff_buf = 0; /* Pointer to area for reading
|
||||
file contents into */
|
||||
|
||||
char *diff_dir; /* Directory contents for LF_DUMPDIR */
|
||||
|
||||
int different = 0;
|
||||
|
||||
/*struct sp_array *sparsearray;
|
||||
int sp_ar_size = 10;*/
|
||||
/*
|
||||
* Initialize for a diff operation
|
||||
*/
|
||||
void
|
||||
diff_init ()
|
||||
{
|
||||
/*NOSTRICT*/
|
||||
diff_buf = (char *) valloc ((unsigned) blocksize);
|
||||
if (!diff_buf)
|
||||
{
|
||||
msg ("could not allocate memory for diff buffer of %d bytes",
|
||||
blocksize);
|
||||
exit (EX_ARGSBAD);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Diff a file against the archive.
|
||||
*/
|
||||
void
|
||||
diff_archive ()
|
||||
{
|
||||
register char *data;
|
||||
int check, namelen;
|
||||
int err;
|
||||
long offset;
|
||||
struct stat filestat;
|
||||
int compare_chunk ();
|
||||
int compare_dir ();
|
||||
int no_op ();
|
||||
#ifndef __MSDOS__
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
#endif
|
||||
char *get_dir_contents ();
|
||||
long from_oct ();
|
||||
|
||||
errno = EPIPE; /* FIXME, remove perrors */
|
||||
|
||||
saverec (&head); /* Make sure it sticks around */
|
||||
userec (head); /* And go past it in the archive */
|
||||
decode_header (head, &hstat, &head_standard, 1); /* Snarf fields */
|
||||
|
||||
/* Print the record from 'head' and 'hstat' */
|
||||
if (f_verbose)
|
||||
{
|
||||
if (now_verifying)
|
||||
fprintf (msg_file, "Verify ");
|
||||
print_header ();
|
||||
}
|
||||
|
||||
switch (head->header.linkflag)
|
||||
{
|
||||
|
||||
default:
|
||||
msg ("Unknown file type '%c' for %s, diffed as normal file",
|
||||
head->header.linkflag, current_file_name);
|
||||
/* FALL THRU */
|
||||
|
||||
case LF_OLDNORMAL:
|
||||
case LF_NORMAL:
|
||||
case LF_SPARSE:
|
||||
case LF_CONTIG:
|
||||
/*
|
||||
* Appears to be a file.
|
||||
* See if it's really a directory.
|
||||
*/
|
||||
namelen = strlen (current_file_name) - 1;
|
||||
if (current_file_name[namelen] == '/')
|
||||
goto really_dir;
|
||||
|
||||
|
||||
if (do_stat (&filestat))
|
||||
{
|
||||
if (head->header.isextended)
|
||||
skip_extended_headers ();
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (!S_ISREG (filestat.st_mode))
|
||||
{
|
||||
fprintf (msg_file, "%s: not a regular file\n",
|
||||
current_file_name);
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
filestat.st_mode &= 07777;
|
||||
if (filestat.st_mode != hstat.st_mode)
|
||||
sigh ("mode");
|
||||
if (filestat.st_uid != hstat.st_uid)
|
||||
sigh ("uid");
|
||||
if (filestat.st_gid != hstat.st_gid)
|
||||
sigh ("gid");
|
||||
if (filestat.st_mtime != hstat.st_mtime)
|
||||
sigh ("mod time");
|
||||
if (head->header.linkflag != LF_SPARSE &&
|
||||
filestat.st_size != hstat.st_size)
|
||||
{
|
||||
sigh ("size");
|
||||
skip_file ((long) hstat.st_size);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
|
||||
|
||||
if (diff_fd < 0 && !f_absolute_paths)
|
||||
{
|
||||
char tmpbuf[NAMSIZ + 2];
|
||||
|
||||
tmpbuf[0] = '/';
|
||||
strcpy (&tmpbuf[1], current_file_name);
|
||||
diff_fd = open (tmpbuf, O_NDELAY | O_RDONLY);
|
||||
}
|
||||
if (diff_fd < 0)
|
||||
{
|
||||
msg_perror ("cannot open %s", current_file_name);
|
||||
if (head->header.isextended)
|
||||
skip_extended_headers ();
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
goto quit;
|
||||
}
|
||||
/*
|
||||
* Need to treat sparse files completely differently here.
|
||||
*/
|
||||
if (head->header.linkflag == LF_SPARSE)
|
||||
diff_sparse_files (hstat.st_size);
|
||||
else
|
||||
wantbytes ((long) (hstat.st_size), compare_chunk);
|
||||
|
||||
check = close (diff_fd);
|
||||
if (check < 0)
|
||||
msg_perror ("Error while closing %s", current_file_name);
|
||||
|
||||
quit:
|
||||
break;
|
||||
|
||||
#ifndef __MSDOS__
|
||||
case LF_LINK:
|
||||
if (do_stat (&filestat))
|
||||
break;
|
||||
dev = filestat.st_dev;
|
||||
ino = filestat.st_ino;
|
||||
err = stat (current_link_name, &filestat);
|
||||
if (err < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
fprintf (msg_file, "%s: does not exist\n", current_file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_perror ("cannot stat file %s", current_file_name);
|
||||
}
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
if (filestat.st_dev != dev || filestat.st_ino != ino)
|
||||
{
|
||||
fprintf (msg_file, "%s not linked to %s\n", current_file_name, current_link_name);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef S_ISLNK
|
||||
case LF_SYMLINK:
|
||||
{
|
||||
char linkbuf[NAMSIZ + 3];
|
||||
check = readlink (current_file_name, linkbuf,
|
||||
(sizeof linkbuf) - 1);
|
||||
|
||||
if (check < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
fprintf (msg_file,
|
||||
"%s: no such file or directory\n",
|
||||
current_file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_perror ("cannot read link %s", current_file_name);
|
||||
}
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
|
||||
linkbuf[check] = '\0'; /* Null-terminate it */
|
||||
if (strncmp (current_link_name, linkbuf, check) != 0)
|
||||
{
|
||||
fprintf (msg_file, "%s: symlink differs\n",
|
||||
current_link_name);
|
||||
different++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef S_IFCHR
|
||||
case LF_CHR:
|
||||
hstat.st_mode |= S_IFCHR;
|
||||
goto check_node;
|
||||
#endif
|
||||
|
||||
#ifdef S_IFBLK
|
||||
/* If local system doesn't support block devices, use default case */
|
||||
case LF_BLK:
|
||||
hstat.st_mode |= S_IFBLK;
|
||||
goto check_node;
|
||||
#endif
|
||||
|
||||
#ifdef S_ISFIFO
|
||||
/* If local system doesn't support FIFOs, use default case */
|
||||
case LF_FIFO:
|
||||
#ifdef S_IFIFO
|
||||
hstat.st_mode |= S_IFIFO;
|
||||
#endif
|
||||
hstat.st_rdev = 0; /* FIXME, do we need this? */
|
||||
goto check_node;
|
||||
#endif
|
||||
|
||||
check_node:
|
||||
/* FIXME, deal with umask */
|
||||
if (do_stat (&filestat))
|
||||
break;
|
||||
if (hstat.st_rdev != filestat.st_rdev)
|
||||
{
|
||||
fprintf (msg_file, "%s: device numbers changed\n", current_file_name);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
#ifdef S_IFMT
|
||||
if (hstat.st_mode != filestat.st_mode)
|
||||
#else /* POSIX lossage */
|
||||
if ((hstat.st_mode & 07777) != (filestat.st_mode & 07777))
|
||||
#endif
|
||||
{
|
||||
fprintf (msg_file, "%s: mode or device-type changed\n", current_file_name);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LF_DUMPDIR:
|
||||
data = diff_dir = get_dir_contents (current_file_name, 0);
|
||||
if (data)
|
||||
{
|
||||
wantbytes ((long) (hstat.st_size), compare_dir);
|
||||
free (data);
|
||||
}
|
||||
else
|
||||
wantbytes ((long) (hstat.st_size), no_op);
|
||||
/* FALL THROUGH */
|
||||
|
||||
case LF_DIR:
|
||||
/* Check for trailing / */
|
||||
namelen = strlen (current_file_name) - 1;
|
||||
really_dir:
|
||||
while (namelen && current_file_name[namelen] == '/')
|
||||
current_file_name[namelen--] = '\0'; /* Zap / */
|
||||
|
||||
if (do_stat (&filestat))
|
||||
break;
|
||||
if (!S_ISDIR (filestat.st_mode))
|
||||
{
|
||||
fprintf (msg_file, "%s is no longer a directory\n", current_file_name);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
if ((filestat.st_mode & 07777) != (hstat.st_mode & 07777))
|
||||
sigh ("mode");
|
||||
break;
|
||||
|
||||
case LF_VOLHDR:
|
||||
break;
|
||||
|
||||
case LF_MULTIVOL:
|
||||
namelen = strlen (current_file_name) - 1;
|
||||
if (current_file_name[namelen] == '/')
|
||||
goto really_dir;
|
||||
|
||||
if (do_stat (&filestat))
|
||||
break;
|
||||
|
||||
if (!S_ISREG (filestat.st_mode))
|
||||
{
|
||||
fprintf (msg_file, "%s: not a regular file\n",
|
||||
current_file_name);
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
|
||||
filestat.st_mode &= 07777;
|
||||
offset = from_oct (1 + 12, head->header.offset);
|
||||
if (filestat.st_size != hstat.st_size + offset)
|
||||
{
|
||||
sigh ("size");
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
|
||||
diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);
|
||||
|
||||
if (diff_fd < 0)
|
||||
{
|
||||
msg_perror ("cannot open file %s", current_file_name);
|
||||
skip_file ((long) hstat.st_size);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
err = lseek (diff_fd, offset, 0);
|
||||
if (err != offset)
|
||||
{
|
||||
msg_perror ("cannot seek to %ld in file %s", offset, current_file_name);
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
|
||||
wantbytes ((long) (hstat.st_size), compare_chunk);
|
||||
|
||||
check = close (diff_fd);
|
||||
if (check < 0)
|
||||
{
|
||||
msg_perror ("Error while closing %s", current_file_name);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* We don't need to save it any longer. */
|
||||
saverec ((union record **) 0);/* Unsave it */
|
||||
}
|
||||
|
||||
int
|
||||
compare_chunk (bytes, buffer)
|
||||
long bytes;
|
||||
char *buffer;
|
||||
{
|
||||
int err;
|
||||
|
||||
err = read (diff_fd, diff_buf, bytes);
|
||||
if (err != bytes)
|
||||
{
|
||||
if (err < 0)
|
||||
{
|
||||
msg_perror ("can't read %s", current_file_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (msg_file, "%s: could only read %d of %d bytes\n", current_file_name, err, bytes);
|
||||
}
|
||||
different++;
|
||||
return -1;
|
||||
}
|
||||
if (bcmp (buffer, diff_buf, bytes))
|
||||
{
|
||||
fprintf (msg_file, "%s: data differs\n", current_file_name);
|
||||
different++;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
compare_dir (bytes, buffer)
|
||||
long bytes;
|
||||
char *buffer;
|
||||
{
|
||||
if (bcmp (buffer, diff_dir, bytes))
|
||||
{
|
||||
fprintf (msg_file, "%s: data differs\n", current_file_name);
|
||||
different++;
|
||||
return -1;
|
||||
}
|
||||
diff_dir += bytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sigh about something that differs.
|
||||
*/
|
||||
void
|
||||
sigh (what)
|
||||
char *what;
|
||||
{
|
||||
|
||||
fprintf (msg_file, "%s: %s differs\n",
|
||||
current_file_name, what);
|
||||
}
|
||||
|
||||
void
|
||||
verify_volume ()
|
||||
{
|
||||
int status;
|
||||
#ifdef MTIOCTOP
|
||||
struct mtop t;
|
||||
int er;
|
||||
#endif
|
||||
|
||||
if (!diff_buf)
|
||||
diff_init ();
|
||||
#ifdef MTIOCTOP
|
||||
t.mt_op = MTBSF;
|
||||
t.mt_count = 1;
|
||||
if ((er = rmtioctl (archive, MTIOCTOP, &t)) < 0)
|
||||
{
|
||||
if (errno != EIO || (er = rmtioctl (archive, MTIOCTOP, &t)) < 0)
|
||||
{
|
||||
#endif
|
||||
if (rmtlseek (archive, 0L, 0) != 0)
|
||||
{
|
||||
/* Lseek failed. Try a different method */
|
||||
msg_perror ("Couldn't rewind archive file for verify");
|
||||
return;
|
||||
}
|
||||
#ifdef MTIOCTOP
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ar_reading = 1;
|
||||
now_verifying = 1;
|
||||
fl_read ();
|
||||
for (;;)
|
||||
{
|
||||
status = read_header ();
|
||||
if (status == 0)
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
n = 0;
|
||||
do
|
||||
{
|
||||
n++;
|
||||
status = read_header ();
|
||||
}
|
||||
while (status == 0);
|
||||
msg ("VERIFY FAILURE: %d invalid header%s detected!", n, n == 1 ? "" : "s");
|
||||
}
|
||||
if (status == 2 || status == EOF)
|
||||
break;
|
||||
diff_archive ();
|
||||
}
|
||||
ar_reading = 0;
|
||||
now_verifying = 0;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
do_stat (statp)
|
||||
struct stat *statp;
|
||||
{
|
||||
int err;
|
||||
|
||||
err = f_follow_links ? stat (current_file_name, statp) : lstat (current_file_name, statp);
|
||||
if (err < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
fprintf (msg_file, "%s: does not exist\n", current_file_name);
|
||||
}
|
||||
else
|
||||
msg_perror ("can't stat file %s", current_file_name);
|
||||
/* skip_file((long)hstat.st_size);
|
||||
different++;*/
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* JK
|
||||
* Diff'ing a sparse file with its counterpart on the tar file is a
|
||||
* bit of a different story than a normal file. First, we must know
|
||||
* what areas of the file to skip through, i.e., we need to contruct
|
||||
* a sparsearray, which will hold all the information we need. We must
|
||||
* compare small amounts of data at a time as we find it.
|
||||
*/
|
||||
|
||||
void
|
||||
diff_sparse_files (filesize)
|
||||
int filesize;
|
||||
|
||||
{
|
||||
int sparse_ind = 0;
|
||||
char *buf;
|
||||
int buf_size = RECORDSIZE;
|
||||
union record *datarec;
|
||||
int err;
|
||||
long numbytes;
|
||||
/* int amt_read = 0;*/
|
||||
int size = filesize;
|
||||
|
||||
buf = (char *) ck_malloc (buf_size * sizeof (char));
|
||||
|
||||
fill_in_sparse_array ();
|
||||
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
datarec = findrec ();
|
||||
if (!sparsearray[sparse_ind].numbytes)
|
||||
break;
|
||||
|
||||
/*
|
||||
* 'numbytes' is nicer to write than
|
||||
* 'sparsearray[sparse_ind].numbytes' all the time ...
|
||||
*/
|
||||
numbytes = sparsearray[sparse_ind].numbytes;
|
||||
|
||||
lseek (diff_fd, sparsearray[sparse_ind].offset, 0);
|
||||
/*
|
||||
* take care to not run out of room in our buffer
|
||||
*/
|
||||
while (buf_size < numbytes)
|
||||
{
|
||||
buf = (char *) ck_realloc (buf, buf_size * 2 * sizeof (char));
|
||||
buf_size *= 2;
|
||||
}
|
||||
while (numbytes > RECORDSIZE)
|
||||
{
|
||||
if ((err = read (diff_fd, buf, RECORDSIZE)) != RECORDSIZE)
|
||||
{
|
||||
if (err < 0)
|
||||
msg_perror ("can't read %s", current_file_name);
|
||||
else
|
||||
fprintf (msg_file, "%s: could only read %d of %d bytes\n",
|
||||
current_file_name, err, numbytes);
|
||||
break;
|
||||
}
|
||||
if (bcmp (buf, datarec->charptr, RECORDSIZE))
|
||||
{
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
numbytes -= err;
|
||||
size -= err;
|
||||
userec (datarec);
|
||||
datarec = findrec ();
|
||||
}
|
||||
if ((err = read (diff_fd, buf, numbytes)) != numbytes)
|
||||
{
|
||||
if (err < 0)
|
||||
msg_perror ("can't read %s", current_file_name);
|
||||
else
|
||||
fprintf (msg_file, "%s: could only read %d of %d bytes\n",
|
||||
current_file_name, err, numbytes);
|
||||
break;
|
||||
}
|
||||
|
||||
if (bcmp (buf, datarec->charptr, numbytes))
|
||||
{
|
||||
different++;
|
||||
break;
|
||||
}
|
||||
/* amt_read += numbytes;
|
||||
if (amt_read >= RECORDSIZE) {
|
||||
amt_read = 0;
|
||||
userec(datarec);
|
||||
datarec = findrec();
|
||||
}*/
|
||||
userec (datarec);
|
||||
sparse_ind++;
|
||||
size -= numbytes;
|
||||
}
|
||||
/*
|
||||
* if the number of bytes read isn't the
|
||||
* number of bytes supposedly in the file,
|
||||
* they're different
|
||||
*/
|
||||
/* if (amt_read != filesize)
|
||||
different++;*/
|
||||
userec (datarec);
|
||||
free (sparsearray);
|
||||
if (different)
|
||||
fprintf (msg_file, "%s: data differs\n", current_file_name);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* JK
|
||||
* This routine should be used more often than it is ... look into
|
||||
* that. Anyhow, what it does is translate the sparse information
|
||||
* on the header, and in any subsequent extended headers, into an
|
||||
* array of structures with true numbers, as opposed to character
|
||||
* strings. It simply makes our life much easier, doing so many
|
||||
* comparisong and such.
|
||||
*/
|
||||
void
|
||||
fill_in_sparse_array ()
|
||||
{
|
||||
int ind;
|
||||
|
||||
/*
|
||||
* allocate space for our scratch space; it's initially
|
||||
* 10 elements long, but can change in this routine if
|
||||
* necessary
|
||||
*/
|
||||
sp_array_size = 10;
|
||||
sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
|
||||
|
||||
/*
|
||||
* there are at most five of these structures in the header
|
||||
* itself; read these in first
|
||||
*/
|
||||
for (ind = 0; ind < SPARSE_IN_HDR; ind++)
|
||||
{
|
||||
if (!head->header.sp[ind].numbytes)
|
||||
break;
|
||||
sparsearray[ind].offset =
|
||||
from_oct (1 + 12, head->header.sp[ind].offset);
|
||||
sparsearray[ind].numbytes =
|
||||
from_oct (1 + 12, head->header.sp[ind].numbytes);
|
||||
}
|
||||
/*
|
||||
* if the header's extended, we gotta read in exhdr's till
|
||||
* we're done
|
||||
*/
|
||||
if (head->header.isextended)
|
||||
{
|
||||
/* how far into the sparsearray we are 'so far' */
|
||||
static int so_far_ind = SPARSE_IN_HDR;
|
||||
union record *exhdr;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
exhdr = findrec ();
|
||||
for (ind = 0; ind < SPARSE_EXT_HDR; ind++)
|
||||
{
|
||||
if (ind + so_far_ind > sp_array_size - 1)
|
||||
{
|
||||
/*
|
||||
* we just ran out of room in our
|
||||
* scratch area - realloc it
|
||||
*/
|
||||
sparsearray = (struct sp_array *)
|
||||
ck_realloc (sparsearray,
|
||||
sp_array_size * 2 * sizeof (struct sp_array));
|
||||
sp_array_size *= 2;
|
||||
}
|
||||
/*
|
||||
* convert the character strings into longs
|
||||
*/
|
||||
sparsearray[ind + so_far_ind].offset =
|
||||
from_oct (1 + 12, exhdr->ext_hdr.sp[ind].offset);
|
||||
sparsearray[ind + so_far_ind].numbytes =
|
||||
from_oct (1 + 12, exhdr->ext_hdr.sp[ind].numbytes);
|
||||
}
|
||||
/*
|
||||
* if this is the last extended header for this
|
||||
* file, we can stop
|
||||
*/
|
||||
if (!exhdr->ext_hdr.isextended)
|
||||
break;
|
||||
else
|
||||
{
|
||||
so_far_ind += SPARSE_EXT_HDR;
|
||||
userec (exhdr);
|
||||
}
|
||||
}
|
||||
/* be sure to skip past the last one */
|
||||
userec (exhdr);
|
||||
}
|
||||
}
|
||||
37
src/exit.c
Normal file
37
src/exit.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of GNU tar.
|
||||
Copyright (C) 2009 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 3, 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 "common.h"
|
||||
|
||||
void (*fatal_exit_hook) (void);
|
||||
|
||||
void
|
||||
fatal_exit (void)
|
||||
{
|
||||
if (fatal_exit_hook)
|
||||
fatal_exit_hook ();
|
||||
error (TAREXIT_FAILURE, 0, _("Error is not recoverable: exiting now"));
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
xalloc_die (void)
|
||||
{
|
||||
error (0, 0, "%s", _("memory exhausted"));
|
||||
fatal_exit ();
|
||||
}
|
||||
134
src/extract.c
134
src/extract.c
@@ -1,7 +1,7 @@
|
||||
/* Extract files from a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-11-19.
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <utimens.h>
|
||||
#include <errno.h>
|
||||
#include <xgetcwd.h>
|
||||
#include <priv-set.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -144,7 +145,8 @@ set_mode (char const *file_name,
|
||||
char typeflag)
|
||||
{
|
||||
mode_t mode;
|
||||
|
||||
bool failed;
|
||||
|
||||
if (0 < same_permissions_option
|
||||
&& permstatus != INTERDIR_PERMSTATUS)
|
||||
{
|
||||
@@ -186,7 +188,17 @@ set_mode (char const *file_name,
|
||||
mode = cur_info->st_mode ^ invert_permissions;
|
||||
}
|
||||
|
||||
if (chmod (file_name, mode) != 0)
|
||||
failed = chmod (file_name, mode) != 0;
|
||||
if (failed && errno == EPERM)
|
||||
{
|
||||
/* On Solaris, chmod may fail if we don't have PRIV_ALL. */
|
||||
if (priv_set_restore_linkdir () == 0)
|
||||
{
|
||||
failed = chmod (file_name, mode) != 0;
|
||||
priv_set_remove_linkdir ();
|
||||
}
|
||||
}
|
||||
if (failed)
|
||||
chmod_error_details (file_name, mode);
|
||||
}
|
||||
|
||||
@@ -195,8 +207,9 @@ static void
|
||||
check_time (char const *file_name, struct timespec t)
|
||||
{
|
||||
if (t.tv_sec <= 0)
|
||||
WARN ((0, 0, _("%s: implausibly old time stamp %s"),
|
||||
file_name, tartime (t, true)));
|
||||
WARNOPT (WARN_TIMESTAMP,
|
||||
(0, 0, _("%s: implausibly old time stamp %s"),
|
||||
file_name, tartime (t, true)));
|
||||
else if (timespec_cmp (volume_start_time, t) < 0)
|
||||
{
|
||||
struct timespec now;
|
||||
@@ -212,8 +225,9 @@ check_time (char const *file_name, struct timespec t)
|
||||
diff.tv_nsec += BILLION;
|
||||
diff.tv_sec--;
|
||||
}
|
||||
WARN ((0, 0, _("%s: time stamp %s is %s s in the future"),
|
||||
file_name, tartime (t, true), code_timespec (diff, buf)));
|
||||
WARNOPT (WARN_TIMESTAMP,
|
||||
(0, 0, _("%s: time stamp %s is %s s in the future"),
|
||||
file_name, tartime (t, true), code_timespec (diff, buf)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,9 +488,13 @@ file_newer_p (const char *file_name, struct tar_stat_info *tar_stat)
|
||||
|
||||
if (stat (file_name, &st))
|
||||
{
|
||||
stat_warn (file_name);
|
||||
/* Be on the safe side: if the file does exist assume it is newer */
|
||||
return errno != ENOENT;
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
stat_warn (file_name);
|
||||
/* Be on the safe side: if the file does exist assume it is newer */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!S_ISDIR (st.st_mode)
|
||||
&& tar_timespec_cmp (tar_stat->mtime, get_stat_mtime (&st)) <= 0)
|
||||
@@ -486,17 +504,24 @@ file_newer_p (const char *file_name, struct tar_stat_info *tar_stat)
|
||||
return false;
|
||||
}
|
||||
|
||||
#define RECOVER_NO 0
|
||||
#define RECOVER_OK 1
|
||||
#define RECOVER_SKIP 2
|
||||
|
||||
/* Attempt repairing what went wrong with the extraction. Delete an
|
||||
already existing file or create missing intermediate directories.
|
||||
Return nonzero if we somewhat increased our chances at a successful
|
||||
extraction. errno is properly restored on zero return. */
|
||||
Return RECOVER_OK if we somewhat increased our chances at a successful
|
||||
extraction, RECOVER_NO if there are no chances, and RECOVER_SKIP if the
|
||||
caller should skip extraction of that member. The value of errno is
|
||||
properly restored on returning RECOVER_NO. */
|
||||
|
||||
static int
|
||||
maybe_recoverable (char *file_name, int *interdir_made)
|
||||
{
|
||||
int e = errno;
|
||||
|
||||
if (*interdir_made)
|
||||
return 0;
|
||||
return RECOVER_NO;
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
@@ -506,13 +531,13 @@ maybe_recoverable (char *file_name, int *interdir_made)
|
||||
switch (old_files_option)
|
||||
{
|
||||
case KEEP_OLD_FILES:
|
||||
return 0;
|
||||
return RECOVER_SKIP;
|
||||
|
||||
case KEEP_NEWER_FILES:
|
||||
if (file_newer_p (file_name, ¤t_stat_info))
|
||||
{
|
||||
errno = e;
|
||||
return 0;
|
||||
return RECOVER_NO;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
|
||||
@@ -522,7 +547,7 @@ maybe_recoverable (char *file_name, int *interdir_made)
|
||||
{
|
||||
int r = remove_any_file (file_name, ORDINARY_REMOVE_OPTION);
|
||||
errno = EEXIST;
|
||||
return r;
|
||||
return r > 0 ? RECOVER_OK : RECOVER_NO;
|
||||
}
|
||||
|
||||
case UNLINK_FIRST_OLD_FILES:
|
||||
@@ -534,15 +559,15 @@ maybe_recoverable (char *file_name, int *interdir_made)
|
||||
if (! make_directories (file_name))
|
||||
{
|
||||
errno = ENOENT;
|
||||
return 0;
|
||||
return RECOVER_NO;
|
||||
}
|
||||
*interdir_made = 1;
|
||||
return 1;
|
||||
return RECOVER_OK;
|
||||
|
||||
default:
|
||||
/* Just say we can't do anything about it... */
|
||||
|
||||
return 0;
|
||||
return RECOVER_NO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,6 +684,7 @@ extract_dir (char *file_name, int typeflag)
|
||||
}
|
||||
if (S_ISDIR (st.st_mode))
|
||||
{
|
||||
status = 0;
|
||||
mode = st.st_mode;
|
||||
break;
|
||||
}
|
||||
@@ -666,13 +692,21 @@ extract_dir (char *file_name, int typeflag)
|
||||
errno = EEXIST;
|
||||
}
|
||||
|
||||
if (maybe_recoverable (file_name, &interdir_made))
|
||||
continue;
|
||||
|
||||
if (errno != EEXIST)
|
||||
switch (maybe_recoverable (file_name, &interdir_made))
|
||||
{
|
||||
mkdir_error (file_name);
|
||||
return 1;
|
||||
case RECOVER_OK:
|
||||
continue;
|
||||
|
||||
case RECOVER_SKIP:
|
||||
break;
|
||||
|
||||
case RECOVER_NO:
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
mkdir_error (file_name);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -721,7 +755,8 @@ open_output_file (char *file_name, int typeflag, mode_t mode)
|
||||
if (!conttype_diagnosed)
|
||||
{
|
||||
conttype_diagnosed = 1;
|
||||
WARN ((0, 0, _("Extracting contiguous files as regular files")));
|
||||
WARNOPT (WARN_CONTIGUOUS_CAST,
|
||||
(0, 0, _("Extracting contiguous files as regular files")));
|
||||
}
|
||||
}
|
||||
fd = open (file_name, openflag, mode);
|
||||
@@ -760,13 +795,18 @@ extract_file (char *file_name, int typeflag)
|
||||
}
|
||||
else
|
||||
{
|
||||
int recover = RECOVER_NO;
|
||||
do
|
||||
fd = open_output_file (file_name, typeflag, mode ^ invert_permissions);
|
||||
while (fd < 0 && maybe_recoverable (file_name, &interdir_made));
|
||||
while (fd < 0
|
||||
&& (recover = maybe_recoverable (file_name, &interdir_made))
|
||||
== RECOVER_OK);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
skip_member ();
|
||||
if (recover == RECOVER_SKIP)
|
||||
return 0;
|
||||
open_error (file_name);
|
||||
return 1;
|
||||
}
|
||||
@@ -994,7 +1034,9 @@ extract_symlink (char *file_name, int typeflag)
|
||||
if (!warned_once)
|
||||
{
|
||||
warned_once = 1;
|
||||
WARN ((0, 0, _("Attempting extraction of symbolic links as hard links")));
|
||||
WARNOPT (WARN_SYMBOLIC_CAST,
|
||||
(0, 0,
|
||||
_("Attempting extraction of symbolic links as hard links")));
|
||||
}
|
||||
return extract_link (file_name, typeflag);
|
||||
#endif
|
||||
@@ -1050,8 +1092,6 @@ extract_fifo (char *file_name, int typeflag)
|
||||
static int
|
||||
extract_volhdr (char *file_name, int typeflag)
|
||||
{
|
||||
if (verbose_option)
|
||||
fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name));
|
||||
skip_member ();
|
||||
return 0;
|
||||
}
|
||||
@@ -1152,9 +1192,10 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN ((0, 0,
|
||||
_("%s: Unknown file type `%c', extracted as normal file"),
|
||||
quotearg_colon (file_name), typeflag));
|
||||
WARNOPT (WARN_UNKNOWN_CAST,
|
||||
(0, 0,
|
||||
_("%s: Unknown file type `%c', extracted as normal file"),
|
||||
quotearg_colon (file_name), typeflag));
|
||||
*fun = extract_file;
|
||||
}
|
||||
|
||||
@@ -1178,8 +1219,9 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
|
||||
case KEEP_NEWER_FILES:
|
||||
if (file_newer_p (file_name, ¤t_stat_info))
|
||||
{
|
||||
WARN ((0, 0, _("Current %s is newer or same age"),
|
||||
quote (file_name)));
|
||||
WARNOPT (WARN_IGNORE_NEWER,
|
||||
(0, 0, _("Current %s is newer or same age"),
|
||||
quote (file_name)));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@@ -1198,6 +1240,11 @@ extract_archive (void)
|
||||
char typeflag;
|
||||
tar_extractor_t fun;
|
||||
|
||||
fatal_exit_hook = extract_finish;
|
||||
|
||||
/* Try to disable the ability to unlink a directory. */
|
||||
priv_set_remove_linkdir ();
|
||||
|
||||
set_next_block_after (current_header);
|
||||
decode_header (current_header, ¤t_stat_info, ¤t_format, 1);
|
||||
if (!current_stat_info.file_name[0]
|
||||
@@ -1210,7 +1257,7 @@ extract_archive (void)
|
||||
|
||||
/* Print the block from current_header and current_stat. */
|
||||
if (verbose_option)
|
||||
print_header (¤t_stat_info, -1);
|
||||
print_header (¤t_stat_info, current_header, -1);
|
||||
|
||||
/* Restore stats for all non-ancestor directories, unless
|
||||
it is an incremental archive.
|
||||
@@ -1359,18 +1406,3 @@ rename_directory (char *src, char *dst)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
fatal_exit (void)
|
||||
{
|
||||
extract_finish ();
|
||||
error (TAREXIT_FAILURE, 0, _("Error is not recoverable: exiting now"));
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
xalloc_die (void)
|
||||
{
|
||||
error (0, 0, "%s", _("memory exhausted"));
|
||||
fatal_exit ();
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/* Replacement for getopt() that can be used by tar.
|
||||
Copyright (C) 1988 Free Software Foundation
|
||||
|
||||
This file is part of GNU Tar.
|
||||
|
||||
GNU Tar 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.
|
||||
|
||||
GNU Tar 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 GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
* Plug-compatible replacement for getopt() for parsing tar-like
|
||||
* arguments. If the first argument begins with "-", it uses getopt;
|
||||
* otherwise, it uses the old rules used by tar, dump, and ps.
|
||||
*
|
||||
* Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "getopt.h"
|
||||
#include "tar.h" /* For msg() declaration if STDC_MSG. */
|
||||
#include <sys/types.h>
|
||||
#include "port.h"
|
||||
|
||||
int
|
||||
getoldopt (argc, argv, optstring, long_options, opt_index)
|
||||
int argc;
|
||||
char **argv;
|
||||
char *optstring;
|
||||
struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
extern char *optarg; /* Points to next arg */
|
||||
extern int optind; /* Global argv index */
|
||||
static char *key; /* Points to next keyletter */
|
||||
static char use_getopt; /* !=0 if argv[1][0] was '-' */
|
||||
char c;
|
||||
char *place;
|
||||
|
||||
optarg = NULL;
|
||||
|
||||
if (key == NULL)
|
||||
{ /* First time */
|
||||
if (argc < 2)
|
||||
return EOF;
|
||||
key = argv[1];
|
||||
if ((*key == '-') || (*key == '+'))
|
||||
use_getopt++;
|
||||
else
|
||||
optind = 2;
|
||||
}
|
||||
|
||||
if (use_getopt)
|
||||
return getopt_long (argc, argv, optstring,
|
||||
long_options, opt_index);
|
||||
|
||||
c = *key++;
|
||||
if (c == '\0')
|
||||
{
|
||||
key--;
|
||||
return EOF;
|
||||
}
|
||||
place = index (optstring, c);
|
||||
|
||||
if (place == NULL || c == ':')
|
||||
{
|
||||
msg ("unknown option %c", c);
|
||||
return ('?');
|
||||
}
|
||||
|
||||
place++;
|
||||
if (*place == ':')
|
||||
{
|
||||
if (optind < argc)
|
||||
{
|
||||
optarg = argv[optind];
|
||||
optind++;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg ("%c argument missing", c);
|
||||
return ('?');
|
||||
}
|
||||
}
|
||||
|
||||
return (c);
|
||||
}
|
||||
677
src/gnu.c
677
src/gnu.c
@@ -1,677 +0,0 @@
|
||||
/* GNU dump extensions to tar.
|
||||
Copyright (C) 1988, 1992, 1993 Free Software Foundation
|
||||
|
||||
This file is part of GNU Tar.
|
||||
|
||||
GNU Tar 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.
|
||||
|
||||
GNU Tar 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 GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#ifndef STDC_HEADERS
|
||||
extern int errno;
|
||||
#endif
|
||||
#include <time.h>
|
||||
time_t time ();
|
||||
|
||||
#include "tar.h"
|
||||
#include "port.h"
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define lstat stat
|
||||
#endif
|
||||
|
||||
extern time_t new_time;
|
||||
extern FILE *msg_file;
|
||||
|
||||
void addname ();
|
||||
int check_exclude ();
|
||||
extern PTR ck_malloc ();
|
||||
extern PTR ck_realloc ();
|
||||
int confirm ();
|
||||
extern PTR init_buffer ();
|
||||
extern char *get_buffer ();
|
||||
int is_dot_or_dotdot ();
|
||||
extern void add_buffer ();
|
||||
extern void flush_buffer ();
|
||||
void name_gather ();
|
||||
int recursively_delete ();
|
||||
void skip_file ();
|
||||
char *un_quote_string ();
|
||||
|
||||
extern char *new_name ();
|
||||
|
||||
static void add_dir_name ();
|
||||
|
||||
struct dirname
|
||||
{
|
||||
struct dirname *next;
|
||||
char *name;
|
||||
char *dir_text;
|
||||
int dev;
|
||||
int ino;
|
||||
int allnew;
|
||||
};
|
||||
static struct dirname *dir_list;
|
||||
static time_t this_time;
|
||||
|
||||
void
|
||||
add_dir (name, dev, ino, text)
|
||||
char *name;
|
||||
char *text;
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
{
|
||||
struct dirname *dp;
|
||||
|
||||
dp = (struct dirname *) ck_malloc (sizeof (struct dirname));
|
||||
if (!dp)
|
||||
abort ();
|
||||
dp->next = dir_list;
|
||||
dir_list = dp;
|
||||
dp->dev = dev;
|
||||
dp->ino = ino;
|
||||
dp->name = ck_malloc (strlen (name) + 1);
|
||||
strcpy (dp->name, name);
|
||||
dp->dir_text = text;
|
||||
dp->allnew = 0;
|
||||
}
|
||||
|
||||
void
|
||||
read_dir_file ()
|
||||
{
|
||||
int dev;
|
||||
int ino;
|
||||
char *strp;
|
||||
FILE *fp;
|
||||
char buf[512];
|
||||
static char *path = 0;
|
||||
|
||||
if (path == 0)
|
||||
path = ck_malloc (PATH_MAX);
|
||||
time (&this_time);
|
||||
if (gnu_dumpfile[0] != '/')
|
||||
{
|
||||
#if defined(__MSDOS__) || defined(HAVE_GETCWD) || defined(_POSIX_VERSION)
|
||||
if (!getcwd (path, PATH_MAX))
|
||||
{
|
||||
msg ("Couldn't get current directory.");
|
||||
exit (EX_SYSTEM);
|
||||
}
|
||||
#else
|
||||
char *getwd ();
|
||||
|
||||
if (!getwd (path))
|
||||
{
|
||||
msg ("Couldn't get current directory: %s", path);
|
||||
exit (EX_SYSTEM);
|
||||
}
|
||||
#endif
|
||||
/* If this doesn't fit, we're in serious trouble */
|
||||
strcat (path, "/");
|
||||
strcat (path, gnu_dumpfile);
|
||||
gnu_dumpfile = path;
|
||||
}
|
||||
fp = fopen (gnu_dumpfile, "r");
|
||||
if (fp == 0 && errno != ENOENT)
|
||||
{
|
||||
msg_perror ("Can't open %s", gnu_dumpfile);
|
||||
return;
|
||||
}
|
||||
if (!fp)
|
||||
return;
|
||||
fgets (buf, sizeof (buf), fp);
|
||||
if (!f_new_files)
|
||||
{
|
||||
f_new_files++;
|
||||
new_time = atol (buf);
|
||||
}
|
||||
while (fgets (buf, sizeof (buf), fp))
|
||||
{
|
||||
strp = &buf[strlen (buf)];
|
||||
if (strp[-1] == '\n')
|
||||
strp[-1] = '\0';
|
||||
strp = buf;
|
||||
dev = atol (strp);
|
||||
while (isdigit (*strp))
|
||||
strp++;
|
||||
ino = atol (strp);
|
||||
while (isspace (*strp))
|
||||
strp++;
|
||||
while (isdigit (*strp))
|
||||
strp++;
|
||||
strp++;
|
||||
add_dir (un_quote_string (strp), dev, ino, (char *) 0);
|
||||
}
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
void
|
||||
write_dir_file ()
|
||||
{
|
||||
FILE *fp;
|
||||
struct dirname *dp;
|
||||
char *str;
|
||||
extern char *quote_copy_string ();
|
||||
|
||||
fp = fopen (gnu_dumpfile, "w");
|
||||
if (fp == 0)
|
||||
{
|
||||
msg_perror ("Can't write to %s", gnu_dumpfile);
|
||||
return;
|
||||
}
|
||||
fprintf (fp, "%lu\n", this_time);
|
||||
for (dp = dir_list; dp; dp = dp->next)
|
||||
{
|
||||
if (!dp->dir_text)
|
||||
continue;
|
||||
str = quote_copy_string (dp->name);
|
||||
if (str)
|
||||
{
|
||||
fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, str);
|
||||
free (str);
|
||||
}
|
||||
else
|
||||
fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, dp->name);
|
||||
}
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
struct dirname *
|
||||
get_dir (name)
|
||||
char *name;
|
||||
{
|
||||
struct dirname *dp;
|
||||
|
||||
for (dp = dir_list; dp; dp = dp->next)
|
||||
{
|
||||
if (!strcmp (dp->name, name))
|
||||
return dp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Collect all the names from argv[] (or whatever), then expand them into
|
||||
a directory tree, and put all the directories at the beginning. */
|
||||
void
|
||||
collect_and_sort_names ()
|
||||
{
|
||||
struct name *n, *n_next;
|
||||
int num_names;
|
||||
struct stat statbuf;
|
||||
int name_cmp ();
|
||||
char *merge_sort ();
|
||||
|
||||
name_gather ();
|
||||
|
||||
if (gnu_dumpfile)
|
||||
read_dir_file ();
|
||||
if (!namelist)
|
||||
addname (".");
|
||||
for (n = namelist; n; n = n_next)
|
||||
{
|
||||
n_next = n->next;
|
||||
if (n->found || n->dir_contents)
|
||||
continue;
|
||||
if (n->regexp) /* FIXME just skip regexps for now */
|
||||
continue;
|
||||
if (n->change_dir)
|
||||
if (chdir (n->change_dir) < 0)
|
||||
{
|
||||
msg_perror ("can't chdir to %s", n->change_dir);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef AIX
|
||||
if (statx (n->name, &statbuf, STATSIZE, STX_HIDDEN | STX_LINK))
|
||||
#else
|
||||
if (lstat (n->name, &statbuf) < 0)
|
||||
#endif /* AIX */
|
||||
{
|
||||
msg_perror ("can't stat %s", n->name);
|
||||
continue;
|
||||
}
|
||||
if (S_ISDIR (statbuf.st_mode))
|
||||
{
|
||||
n->found++;
|
||||
add_dir_name (n->name, statbuf.st_dev);
|
||||
}
|
||||
}
|
||||
|
||||
num_names = 0;
|
||||
for (n = namelist; n; n = n->next)
|
||||
num_names++;
|
||||
namelist = (struct name *) merge_sort ((PTR) namelist, num_names, (char *) (&(namelist->next)) - (char *) namelist, name_cmp);
|
||||
|
||||
for (n = namelist; n; n = n->next)
|
||||
{
|
||||
n->found = 0;
|
||||
}
|
||||
if (gnu_dumpfile)
|
||||
write_dir_file ();
|
||||
}
|
||||
|
||||
int
|
||||
name_cmp (n1, n2)
|
||||
struct name *n1, *n2;
|
||||
{
|
||||
if (n1->found)
|
||||
{
|
||||
if (n2->found)
|
||||
return strcmp (n1->name, n2->name);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else if (n2->found)
|
||||
return 1;
|
||||
else
|
||||
return strcmp (n1->name, n2->name);
|
||||
}
|
||||
|
||||
int
|
||||
dirent_cmp (p1, p2)
|
||||
const PTR p1;
|
||||
const PTR p2;
|
||||
{
|
||||
char *frst, *scnd;
|
||||
|
||||
frst = (*(char **) p1) + 1;
|
||||
scnd = (*(char **) p2) + 1;
|
||||
|
||||
return strcmp (frst, scnd);
|
||||
}
|
||||
|
||||
char *
|
||||
get_dir_contents (p, device)
|
||||
char *p;
|
||||
int device;
|
||||
{
|
||||
DIR *dirp;
|
||||
register struct dirent *d;
|
||||
char *new_buf;
|
||||
char *namebuf;
|
||||
int bufsiz;
|
||||
int len;
|
||||
PTR the_buffer;
|
||||
char *buf;
|
||||
size_t n_strs;
|
||||
/* int n_size;*/
|
||||
char *p_buf;
|
||||
char **vec, **p_vec;
|
||||
|
||||
extern int errno;
|
||||
|
||||
errno = 0;
|
||||
dirp = opendir (p);
|
||||
bufsiz = strlen (p) + NAMSIZ;
|
||||
namebuf = ck_malloc (bufsiz + 2);
|
||||
if (!dirp)
|
||||
{
|
||||
if (errno)
|
||||
msg_perror ("can't open directory %s", p);
|
||||
else
|
||||
msg ("error opening directory %s", p);
|
||||
new_buf = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct dirname *dp;
|
||||
int all_children;
|
||||
|
||||
dp = get_dir (p);
|
||||
all_children = dp ? dp->allnew : 0;
|
||||
(void) strcpy (namebuf, p);
|
||||
if (p[strlen (p) - 1] != '/')
|
||||
(void) strcat (namebuf, "/");
|
||||
len = strlen (namebuf);
|
||||
|
||||
the_buffer = init_buffer ();
|
||||
while (d = readdir (dirp))
|
||||
{
|
||||
struct stat hs;
|
||||
|
||||
/* Skip . and .. */
|
||||
if (is_dot_or_dotdot (d->d_name))
|
||||
continue;
|
||||
if (NLENGTH (d) + len >= bufsiz)
|
||||
{
|
||||
bufsiz += NAMSIZ;
|
||||
namebuf = ck_realloc (namebuf, bufsiz + 2);
|
||||
}
|
||||
(void) strcpy (namebuf + len, d->d_name);
|
||||
#ifdef AIX
|
||||
if (0 != f_follow_links ?
|
||||
statx (namebuf, &hs, STATSIZE, STX_HIDDEN) :
|
||||
statx (namebuf, &hs, STATSIZE, STX_HIDDEN | STX_LINK))
|
||||
#else
|
||||
if (0 != f_follow_links ? stat (namebuf, &hs) : lstat (namebuf, &hs))
|
||||
#endif
|
||||
{
|
||||
msg_perror ("can't stat %s", namebuf);
|
||||
continue;
|
||||
}
|
||||
if ((f_local_filesys && device != hs.st_dev)
|
||||
|| (f_exclude && check_exclude (namebuf)))
|
||||
add_buffer (the_buffer, "N", 1);
|
||||
#ifdef AIX
|
||||
else if (S_ISHIDDEN (hs.st_mode))
|
||||
{
|
||||
add_buffer (the_buffer, "D", 1);
|
||||
strcat (d->d_name, "A");
|
||||
d->d_namlen++;
|
||||
}
|
||||
#endif /* AIX */
|
||||
else if (S_ISDIR (hs.st_mode))
|
||||
{
|
||||
if (dp = get_dir (namebuf))
|
||||
{
|
||||
if (dp->dev != hs.st_dev
|
||||
|| dp->ino != hs.st_ino)
|
||||
{
|
||||
if (f_verbose)
|
||||
msg ("directory %s has been renamed.", namebuf);
|
||||
dp->allnew = 1;
|
||||
dp->dev = hs.st_dev;
|
||||
dp->ino = hs.st_ino;
|
||||
}
|
||||
dp->dir_text = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (f_verbose)
|
||||
msg ("Directory %s is new", namebuf);
|
||||
add_dir (namebuf, hs.st_dev, hs.st_ino, "");
|
||||
dp = get_dir (namebuf);
|
||||
dp->allnew = 1;
|
||||
}
|
||||
if (all_children)
|
||||
dp->allnew = 1;
|
||||
|
||||
add_buffer (the_buffer, "D", 1);
|
||||
}
|
||||
else if (!all_children
|
||||
&& f_new_files
|
||||
&& new_time > hs.st_mtime
|
||||
&& (f_new_files > 1
|
||||
|| new_time > hs.st_ctime))
|
||||
add_buffer (the_buffer, "N", 1);
|
||||
else
|
||||
add_buffer (the_buffer, "Y", 1);
|
||||
add_buffer (the_buffer, d->d_name, (int) (NLENGTH (d) + 1));
|
||||
}
|
||||
add_buffer (the_buffer, "\000\000", 2);
|
||||
closedir (dirp);
|
||||
|
||||
/* Well, we've read in the contents of the dir, now sort them */
|
||||
buf = get_buffer (the_buffer);
|
||||
if (buf[0] == '\0')
|
||||
{
|
||||
flush_buffer (the_buffer);
|
||||
new_buf = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
n_strs = 0;
|
||||
for (p_buf = buf; *p_buf;)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
tmp = strlen (p_buf) + 1;
|
||||
n_strs++;
|
||||
p_buf += tmp;
|
||||
}
|
||||
vec = (char **) ck_malloc (sizeof (char *) * (n_strs + 1));
|
||||
for (p_vec = vec, p_buf = buf; *p_buf; p_buf += strlen (p_buf) + 1)
|
||||
*p_vec++ = p_buf;
|
||||
*p_vec = 0;
|
||||
qsort ((PTR) vec, n_strs, sizeof (char *), dirent_cmp);
|
||||
new_buf = (char *) ck_malloc (p_buf - buf + 2);
|
||||
for (p_vec = vec, p_buf = new_buf; *p_vec; p_vec++)
|
||||
{
|
||||
char *p_tmp;
|
||||
|
||||
for (p_tmp = *p_vec; *p_buf++ = *p_tmp++;)
|
||||
;
|
||||
}
|
||||
*p_buf++ = '\0';
|
||||
free (vec);
|
||||
flush_buffer (the_buffer);
|
||||
}
|
||||
}
|
||||
free (namebuf);
|
||||
return new_buf;
|
||||
}
|
||||
|
||||
/* p is a directory. Add all the files in P to the namelist. If any of the
|
||||
files is a directory, recurse on the subdirectory. . . */
|
||||
static void
|
||||
add_dir_name (p, device)
|
||||
char *p;
|
||||
int device;
|
||||
{
|
||||
char *new_buf;
|
||||
char *p_buf;
|
||||
|
||||
char *namebuf;
|
||||
int buflen;
|
||||
register int len;
|
||||
int sublen;
|
||||
|
||||
/* PTR the_buffer;*/
|
||||
|
||||
/* char *buf;*/
|
||||
/* char **vec,**p_vec;*/
|
||||
/* int n_strs,n_size;*/
|
||||
|
||||
struct name *n;
|
||||
|
||||
int dirent_cmp ();
|
||||
|
||||
new_buf = get_dir_contents (p, device);
|
||||
|
||||
for (n = namelist; n; n = n->next)
|
||||
{
|
||||
if (!strcmp (n->name, p))
|
||||
{
|
||||
n->dir_contents = new_buf ? new_buf : "\0\0\0\0";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_buf)
|
||||
{
|
||||
len = strlen (p);
|
||||
buflen = NAMSIZ <= len ? len + NAMSIZ : NAMSIZ;
|
||||
namebuf = ck_malloc (buflen + 1);
|
||||
|
||||
(void) strcpy (namebuf, p);
|
||||
if (namebuf[len - 1] != '/')
|
||||
{
|
||||
namebuf[len++] = '/';
|
||||
namebuf[len] = '\0';
|
||||
}
|
||||
for (p_buf = new_buf; *p_buf; p_buf += sublen + 1)
|
||||
{
|
||||
sublen = strlen (p_buf);
|
||||
if (*p_buf == 'D')
|
||||
{
|
||||
if (len + sublen >= buflen)
|
||||
{
|
||||
buflen += NAMSIZ;
|
||||
namebuf = ck_realloc (namebuf, buflen + 1);
|
||||
}
|
||||
(void) strcpy (namebuf + len, p_buf + 1);
|
||||
addname (namebuf);
|
||||
add_dir_name (namebuf, device);
|
||||
}
|
||||
}
|
||||
free (namebuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns non-zero if p is . or .. This could be a macro for speed. */
|
||||
int
|
||||
is_dot_or_dotdot (p)
|
||||
char *p;
|
||||
{
|
||||
return (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
gnu_restore (skipcrud)
|
||||
int skipcrud;
|
||||
{
|
||||
char *current_dir;
|
||||
/* int current_dir_length; */
|
||||
|
||||
char *archive_dir;
|
||||
/* int archive_dir_length; */
|
||||
PTR the_buffer;
|
||||
char *p;
|
||||
DIR *dirp;
|
||||
struct dirent *d;
|
||||
char *cur, *arc;
|
||||
extern struct stat hstat; /* Stat struct corresponding */
|
||||
long size, copied;
|
||||
char *from, *to;
|
||||
extern union record *head;
|
||||
|
||||
dirp = opendir (skipcrud + current_file_name);
|
||||
|
||||
if (!dirp)
|
||||
{
|
||||
/* The directory doesn't exist now. It'll be created.
|
||||
In any case, we don't have to delete any files out
|
||||
of it */
|
||||
skip_file ((long) hstat.st_size);
|
||||
return;
|
||||
}
|
||||
|
||||
the_buffer = init_buffer ();
|
||||
while (d = readdir (dirp))
|
||||
{
|
||||
if (is_dot_or_dotdot (d->d_name))
|
||||
continue;
|
||||
|
||||
add_buffer (the_buffer, d->d_name, (int) (NLENGTH (d) + 1));
|
||||
}
|
||||
closedir (dirp);
|
||||
add_buffer (the_buffer, "", 1);
|
||||
|
||||
current_dir = get_buffer (the_buffer);
|
||||
archive_dir = (char *) ck_malloc (hstat.st_size);
|
||||
if (archive_dir == 0)
|
||||
{
|
||||
msg ("Can't allocate %d bytes for restore", hstat.st_size);
|
||||
skip_file ((long) hstat.st_size);
|
||||
return;
|
||||
}
|
||||
to = archive_dir;
|
||||
for (size = hstat.st_size; size > 0; size -= copied)
|
||||
{
|
||||
from = findrec ()->charptr;
|
||||
if (!from)
|
||||
{
|
||||
msg ("Unexpected EOF in archive\n");
|
||||
break;
|
||||
}
|
||||
copied = endofrecs ()->charptr - from;
|
||||
if (copied > size)
|
||||
copied = size;
|
||||
bcopy ((PTR) from, (PTR) to, (int) copied);
|
||||
to += copied;
|
||||
userec ((union record *) (from + copied - 1));
|
||||
}
|
||||
|
||||
for (cur = current_dir; *cur; cur += strlen (cur) + 1)
|
||||
{
|
||||
for (arc = archive_dir; *arc; arc += strlen (arc) + 1)
|
||||
{
|
||||
arc++;
|
||||
if (!strcmp (arc, cur))
|
||||
break;
|
||||
}
|
||||
if (*arc == '\0')
|
||||
{
|
||||
p = new_name (skipcrud + current_file_name, cur);
|
||||
if (f_confirm && !confirm ("delete", p))
|
||||
{
|
||||
free (p);
|
||||
continue;
|
||||
}
|
||||
if (f_verbose)
|
||||
fprintf (msg_file, "%s: deleting %s\n", tar, p);
|
||||
if (recursively_delete (p))
|
||||
{
|
||||
msg ("%s: Error while deleting %s\n", tar, p);
|
||||
}
|
||||
free (p);
|
||||
}
|
||||
|
||||
}
|
||||
flush_buffer (the_buffer);
|
||||
free (archive_dir);
|
||||
}
|
||||
|
||||
int
|
||||
recursively_delete (path)
|
||||
char *path;
|
||||
{
|
||||
struct stat sbuf;
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
char *path_buf;
|
||||
/* int path_len; */
|
||||
|
||||
|
||||
if (lstat (path, &sbuf) < 0)
|
||||
return 1;
|
||||
if (S_ISDIR (sbuf.st_mode))
|
||||
{
|
||||
|
||||
/* path_len=strlen(path); */
|
||||
dirp = opendir (path);
|
||||
if (dirp == 0)
|
||||
return 1;
|
||||
while (dp = readdir (dirp))
|
||||
{
|
||||
if (is_dot_or_dotdot (dp->d_name))
|
||||
continue;
|
||||
path_buf = new_name (path, dp->d_name);
|
||||
if (recursively_delete (path_buf))
|
||||
{
|
||||
free (path_buf);
|
||||
closedir (dirp);
|
||||
return 1;
|
||||
}
|
||||
free (path_buf);
|
||||
}
|
||||
closedir (dirp);
|
||||
|
||||
if (rmdir (path) < 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if (unlink (path) < 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
354
src/incremen.c
354
src/incremen.c
@@ -1,7 +1,7 @@
|
||||
/* GNU dump extensions to tar.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009 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
|
||||
@@ -73,6 +73,7 @@ struct directory
|
||||
the original directory structure */
|
||||
const char *tagfile; /* Tag file, if the directory falls under
|
||||
exclusion_tag_under */
|
||||
char *caname; /* canonical name */
|
||||
char *name; /* file name of directory */
|
||||
};
|
||||
|
||||
@@ -212,19 +213,19 @@ static Hash_table *directory_meta_table;
|
||||
|
||||
/* Calculate the hash of a directory. */
|
||||
static size_t
|
||||
hash_directory_name (void const *entry, size_t n_buckets)
|
||||
hash_directory_canonical_name (void const *entry, size_t n_buckets)
|
||||
{
|
||||
struct directory const *directory = entry;
|
||||
return hash_string (directory->name, n_buckets);
|
||||
return hash_string (directory->caname, n_buckets);
|
||||
}
|
||||
|
||||
/* Compare two directories for equality of their names. */
|
||||
static bool
|
||||
compare_directory_names (void const *entry1, void const *entry2)
|
||||
compare_directory_canonical_names (void const *entry1, void const *entry2)
|
||||
{
|
||||
struct directory const *directory1 = entry1;
|
||||
struct directory const *directory2 = entry2;
|
||||
return strcmp (directory1->name, directory2->name) == 0;
|
||||
return strcmp (directory1->caname, directory2->caname) == 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
@@ -245,9 +246,11 @@ compare_directory_meta (void const *entry1, void const *entry2)
|
||||
&& directory1->inode_number == directory2->inode_number;
|
||||
}
|
||||
|
||||
/* Make a directory entry for given NAME */
|
||||
/* Make a directory entry for given relative NAME and canonical name CANAME.
|
||||
The latter is "stolen", i.e. the returned directory contains pointer to
|
||||
it. */
|
||||
static struct directory *
|
||||
make_directory (const char *name)
|
||||
make_directory (const char *name, char *caname)
|
||||
{
|
||||
size_t namelen = strlen (name);
|
||||
struct directory *directory = xmalloc (sizeof (*directory));
|
||||
@@ -260,6 +263,7 @@ make_directory (const char *name)
|
||||
directory->name = xmalloc (namelen + 1);
|
||||
memcpy (directory->name, name, namelen);
|
||||
directory->name[namelen] = 0;
|
||||
directory->caname = caname;
|
||||
directory->tagfile = NULL;
|
||||
return directory;
|
||||
}
|
||||
@@ -267,6 +271,7 @@ make_directory (const char *name)
|
||||
static void
|
||||
free_directory (struct directory *dir)
|
||||
{
|
||||
free (dir->caname);
|
||||
free (dir->name);
|
||||
free (dir);
|
||||
}
|
||||
@@ -274,7 +279,8 @@ free_directory (struct directory *dir)
|
||||
static struct directory *
|
||||
attach_directory (const char *name)
|
||||
{
|
||||
struct directory *dir = make_directory (name);
|
||||
char *cname = normalize_filename (name);
|
||||
struct directory *dir = make_directory (name, cname);
|
||||
if (dirtail)
|
||||
dirtail->next = dir;
|
||||
else
|
||||
@@ -284,24 +290,6 @@ attach_directory (const char *name)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
replace_prefix (char **pname, const char *samp, size_t slen,
|
||||
const char *repl, size_t rlen)
|
||||
{
|
||||
char *name = *pname;
|
||||
size_t nlen = strlen (name);
|
||||
if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
|
||||
{
|
||||
if (rlen > slen)
|
||||
{
|
||||
name = xrealloc (name, nlen - slen + rlen + 1);
|
||||
*pname = name;
|
||||
}
|
||||
memmove (name + rlen, name + slen, nlen - slen + 1);
|
||||
memcpy (name, repl, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dirlist_replace_prefix (const char *pref, const char *repl)
|
||||
{
|
||||
@@ -338,8 +326,8 @@ note_directory (char const *name, struct timespec mtime,
|
||||
|
||||
if (! ((directory_table
|
||||
|| (directory_table = hash_initialize (0, 0,
|
||||
hash_directory_name,
|
||||
compare_directory_names, 0)))
|
||||
hash_directory_canonical_name,
|
||||
compare_directory_canonical_names, 0)))
|
||||
&& hash_insert (directory_table, directory)))
|
||||
xalloc_die ();
|
||||
|
||||
@@ -362,13 +350,38 @@ find_directory (const char *name)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
struct directory *dir = make_directory (name);
|
||||
char *caname = normalize_filename (name);
|
||||
struct directory *dir = make_directory (name, caname);
|
||||
struct directory *ret = hash_lookup (directory_table, dir);
|
||||
free_directory (dir);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Remove directory entry for the given CANAME */
|
||||
void
|
||||
remove_directory (const char *caname)
|
||||
{
|
||||
struct directory *dir = make_directory (caname, xstrdup (caname));
|
||||
struct directory *ret = hash_delete (directory_table, dir);
|
||||
if (ret)
|
||||
free_directory (ret);
|
||||
free_directory (dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If first OLD_PREFIX_LEN bytes of DIR->NAME name match OLD_PREFIX,
|
||||
replace them with NEW_PREFIX. */
|
||||
void
|
||||
rebase_directory (struct directory *dir,
|
||||
const char *old_prefix, size_t old_prefix_len,
|
||||
const char *new_prefix, size_t new_prefix_len)
|
||||
{
|
||||
replace_prefix (&dir->name, old_prefix, old_prefix_len,
|
||||
new_prefix, new_prefix_len);
|
||||
}
|
||||
|
||||
/* Return a directory entry for a given combination of device and inode
|
||||
numbers, or zero if none found. */
|
||||
static struct directory *
|
||||
@@ -378,7 +391,7 @@ find_directory_meta (dev_t dev, ino_t ino)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
struct directory *dir = make_directory ("");
|
||||
struct directory *dir = make_directory ("", NULL);
|
||||
struct directory *ret;
|
||||
dir->device_number = dev;
|
||||
dir->inode_number = ino;
|
||||
@@ -400,18 +413,25 @@ update_parent_directory (const char *name)
|
||||
{
|
||||
struct stat st;
|
||||
if (deref_stat (dereference_option, p, &st) != 0)
|
||||
stat_diag (name);
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
stat_diag (directory->name);
|
||||
/* else: should have been already reported */
|
||||
}
|
||||
else
|
||||
directory->mtime = get_stat_mtime (&st);
|
||||
}
|
||||
free (p);
|
||||
}
|
||||
|
||||
#define PD_FORCE_CHILDREN 0x10
|
||||
#define PD_FORCE_INIT 0x20
|
||||
#define PD_CHILDREN(f) ((f) & 3)
|
||||
|
||||
static struct directory *
|
||||
procdir (char *name_buffer, struct stat *stat_data,
|
||||
procdir (const char *name_buffer, struct stat *stat_data,
|
||||
dev_t device,
|
||||
enum children children,
|
||||
bool verbose,
|
||||
int flag,
|
||||
char *entry)
|
||||
{
|
||||
struct directory *directory;
|
||||
@@ -420,15 +440,31 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
if ((directory = find_directory (name_buffer)) != NULL)
|
||||
{
|
||||
if (DIR_IS_INITED (directory))
|
||||
return directory;
|
||||
{
|
||||
if (flag & PD_FORCE_INIT)
|
||||
{
|
||||
assign_string (&directory->name, name_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
*entry = 'N'; /* Avoid duplicating this directory */
|
||||
return directory;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp (directory->name, name_buffer))
|
||||
{
|
||||
*entry = 'N';
|
||||
return directory;
|
||||
}
|
||||
|
||||
/* With NFS, the same file can have two different devices
|
||||
if an NFS directory is mounted in multiple locations,
|
||||
which is relatively common when automounting.
|
||||
To avoid spurious incremental redumping of
|
||||
directories, consider all NFS devices as equal,
|
||||
relying on the i-node to establish differences. */
|
||||
|
||||
|
||||
if (! ((!check_device_option
|
||||
|| (DIR_IS_NFS (directory) && nfs)
|
||||
|| directory->device_number == stat_data->st_dev)
|
||||
@@ -441,10 +477,11 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
{
|
||||
if (strcmp (d->name, name_buffer))
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
WARNOPT (WARN_RENAME_DIRECTORY,
|
||||
(0, 0,
|
||||
_("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
directory->orig = d;
|
||||
DIR_SET_FLAG (directory, DIRF_RENAMED);
|
||||
dirlist_replace_prefix (d->name, name_buffer);
|
||||
@@ -453,9 +490,9 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (verbose_option)
|
||||
WARN ((0, 0, _("%s: Directory has been renamed"),
|
||||
quotearg_colon (name_buffer)));
|
||||
WARNOPT (WARN_RENAME_DIRECTORY,
|
||||
(0, 0, _("%s: Directory has been renamed"),
|
||||
quotearg_colon (name_buffer)));
|
||||
directory->children = ALL_CHILDREN;
|
||||
directory->device_number = stat_data->st_dev;
|
||||
directory->inode_number = stat_data->st_ino;
|
||||
@@ -465,14 +502,14 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
}
|
||||
else
|
||||
directory->children = CHANGED_CHILDREN;
|
||||
|
||||
|
||||
DIR_SET_FLAG (directory, DIRF_FOUND);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct directory *d = find_directory_meta (stat_data->st_dev,
|
||||
stat_data->st_ino);
|
||||
|
||||
|
||||
directory = note_directory (name_buffer,
|
||||
get_stat_mtime(stat_data),
|
||||
stat_data->st_dev,
|
||||
@@ -485,10 +522,10 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
{
|
||||
if (strcmp (d->name, name_buffer))
|
||||
{
|
||||
if (verbose)
|
||||
WARN ((0, 0, _("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
WARNOPT (WARN_RENAME_DIRECTORY,
|
||||
(0, 0, _("%s: Directory has been renamed from %s"),
|
||||
quotearg_colon (name_buffer),
|
||||
quote_n (1, d->name)));
|
||||
directory->orig = d;
|
||||
DIR_SET_FLAG (directory, DIRF_RENAMED);
|
||||
dirlist_replace_prefix (d->name, name_buffer);
|
||||
@@ -498,9 +535,9 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
else
|
||||
{
|
||||
DIR_SET_FLAG (directory, DIRF_NEW);
|
||||
if (verbose)
|
||||
WARN ((0, 0, _("%s: Directory is new"),
|
||||
quotearg_colon (name_buffer)));
|
||||
WARNOPT (WARN_NEW_DIRECTORY,
|
||||
(0, 0, _("%s: Directory is new"),
|
||||
quotearg_colon (name_buffer)));
|
||||
directory->children =
|
||||
(listed_incremental_option
|
||||
|| (OLDER_STAT_TIME (*stat_data, m)
|
||||
@@ -516,44 +553,54 @@ procdir (char *name_buffer, struct stat *stat_data,
|
||||
if (one_file_system_option && device != stat_data->st_dev
|
||||
/* ... except if it was explicitely given in the command line */
|
||||
&& !is_individual_file (name_buffer))
|
||||
/* FIXME:
|
||||
WARNOPT (WARN_XDEV,
|
||||
(0, 0,
|
||||
_("%s: directory is on a different filesystem; not dumped"),
|
||||
quotearg_colon (directory->name)));
|
||||
*/
|
||||
directory->children = NO_CHILDREN;
|
||||
else if (children == ALL_CHILDREN)
|
||||
directory->children = ALL_CHILDREN;
|
||||
|
||||
else if (flag & PD_FORCE_CHILDREN)
|
||||
{
|
||||
directory->children = PD_CHILDREN(flag);
|
||||
if (directory->children == NO_CHILDREN)
|
||||
*entry = 'N';
|
||||
}
|
||||
|
||||
DIR_SET_FLAG (directory, DIRF_INIT);
|
||||
|
||||
{
|
||||
const char *tag_file_name;
|
||||
if (directory->children != NO_CHILDREN)
|
||||
{
|
||||
const char *tag_file_name;
|
||||
|
||||
switch (check_exclusion_tags (name_buffer, &tag_file_name))
|
||||
{
|
||||
case exclusion_tag_all:
|
||||
/* This warning can be duplicated by code in dump_file0, but only
|
||||
in case when the topmost directory being archived contains
|
||||
an exclusion tag. */
|
||||
exclusion_tag_warning (name_buffer, tag_file_name,
|
||||
_("directory not dumped"));
|
||||
if (entry)
|
||||
switch (check_exclusion_tags (name_buffer, &tag_file_name))
|
||||
{
|
||||
case exclusion_tag_all:
|
||||
/* This warning can be duplicated by code in dump_file0, but only
|
||||
in case when the topmost directory being archived contains
|
||||
an exclusion tag. */
|
||||
exclusion_tag_warning (name_buffer, tag_file_name,
|
||||
_("directory not dumped"));
|
||||
*entry = 'N';
|
||||
directory->children = NO_CHILDREN;
|
||||
break;
|
||||
directory->children = NO_CHILDREN;
|
||||
break;
|
||||
|
||||
case exclusion_tag_contents:
|
||||
exclusion_tag_warning (name_buffer, tag_file_name,
|
||||
_("contents not dumped"));
|
||||
directory->children = NO_CHILDREN;
|
||||
break;
|
||||
|
||||
case exclusion_tag_under:
|
||||
exclusion_tag_warning (name_buffer, tag_file_name,
|
||||
_("contents not dumped"));
|
||||
directory->tagfile = tag_file_name;
|
||||
break;
|
||||
|
||||
case exclusion_tag_none:
|
||||
break;
|
||||
}
|
||||
}
|
||||
case exclusion_tag_contents:
|
||||
exclusion_tag_warning (name_buffer, tag_file_name,
|
||||
_("contents not dumped"));
|
||||
directory->children = NO_CHILDREN;
|
||||
break;
|
||||
|
||||
case exclusion_tag_under:
|
||||
exclusion_tag_warning (name_buffer, tag_file_name,
|
||||
_("contents not dumped"));
|
||||
directory->tagfile = tag_file_name;
|
||||
break;
|
||||
|
||||
case exclusion_tag_none:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
@@ -635,45 +682,47 @@ makedumpdir (struct directory *directory, const char *dir)
|
||||
free (array);
|
||||
}
|
||||
|
||||
/* Recursively scan the given directory. */
|
||||
static const char *
|
||||
scan_directory (char *dir, dev_t device)
|
||||
/* Recursively scan the given directory DIR.
|
||||
DEVICE is the device number where DIR resides (for --one-file-system).
|
||||
If CMDLINE is true, the directory name was explicitly listed in the
|
||||
command line.
|
||||
Unless *PDIR is NULL, store there a pointer to the struct directory
|
||||
describing DIR. */
|
||||
struct directory *
|
||||
scan_directory (char *dir, dev_t device, bool cmdline)
|
||||
{
|
||||
char *dirp = savedir (dir); /* for scanning directory */
|
||||
char *name_buffer; /* directory, `/', and directory member */
|
||||
size_t name_buffer_size; /* allocated size of name_buffer, minus 2 */
|
||||
size_t name_length; /* used length in name_buffer */
|
||||
namebuf_t nbuf;
|
||||
char *tmp;
|
||||
struct stat stat_data;
|
||||
struct directory *directory;
|
||||
|
||||
char ch;
|
||||
|
||||
if (! dirp)
|
||||
savedir_error (dir);
|
||||
|
||||
name_buffer_size = strlen (dir) + NAME_FIELD_SIZE;
|
||||
name_buffer = xmalloc (name_buffer_size + 2);
|
||||
strcpy (name_buffer, dir);
|
||||
if (! ISSLASH (dir[strlen (dir) - 1]))
|
||||
strcat (name_buffer, "/");
|
||||
name_length = strlen (name_buffer);
|
||||
|
||||
if (deref_stat (dereference_option, name_buffer, &stat_data))
|
||||
tmp = xstrdup (dir);
|
||||
zap_slashes (tmp);
|
||||
|
||||
if (deref_stat (dereference_option, tmp, &stat_data))
|
||||
{
|
||||
stat_diag (name_buffer);
|
||||
/* FIXME: used to be
|
||||
children = CHANGED_CHILDREN;
|
||||
but changed to: */
|
||||
free (name_buffer);
|
||||
dir_removed_diag (tmp, cmdline, stat_diag);
|
||||
free (tmp);
|
||||
free (dirp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
directory = procdir (name_buffer, &stat_data, device, NO_CHILDREN, false,
|
||||
NULL);
|
||||
directory = procdir (tmp, &stat_data, device,
|
||||
(cmdline ? PD_FORCE_INIT : 0),
|
||||
&ch);
|
||||
|
||||
free (tmp);
|
||||
|
||||
nbuf = namebuf_create (dir);
|
||||
|
||||
if (dirp && directory->children != NO_CHILDREN)
|
||||
{
|
||||
char *entry; /* directory entry being scanned */
|
||||
size_t entrylen; /* length of directory entry */
|
||||
dumpdir_iter_t itr;
|
||||
|
||||
makedumpdir (directory, dirp);
|
||||
@@ -682,35 +731,30 @@ scan_directory (char *dir, dev_t device)
|
||||
entry;
|
||||
entry = dumpdir_next (itr))
|
||||
{
|
||||
entrylen = strlen (entry);
|
||||
if (name_buffer_size <= entrylen - 1 + name_length)
|
||||
{
|
||||
do
|
||||
name_buffer_size += NAME_FIELD_SIZE;
|
||||
while (name_buffer_size <= entrylen - 1 + name_length);
|
||||
name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
|
||||
}
|
||||
strcpy (name_buffer + name_length, entry + 1);
|
||||
char *full_name = namebuf_name (nbuf, entry + 1);
|
||||
|
||||
if (*entry == 'I') /* Ignored entry */
|
||||
*entry = 'N';
|
||||
else if (excluded_name (name_buffer))
|
||||
else if (excluded_name (full_name))
|
||||
*entry = 'N';
|
||||
else
|
||||
{
|
||||
if (deref_stat (dereference_option, name_buffer, &stat_data))
|
||||
if (deref_stat (dereference_option, full_name, &stat_data))
|
||||
{
|
||||
stat_diag (name_buffer);
|
||||
file_removed_diag (full_name, false, stat_diag);
|
||||
*entry = 'N';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR (stat_data.st_mode))
|
||||
{
|
||||
int pd_flag = 0;
|
||||
if (!recursion_option)
|
||||
pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
|
||||
else if (directory->children == ALL_CHILDREN)
|
||||
pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
|
||||
*entry = 'D';
|
||||
procdir (name_buffer, &stat_data, device,
|
||||
directory->children,
|
||||
verbose_option, entry);
|
||||
procdir (full_name, &stat_data, device, pd_flag, entry);
|
||||
}
|
||||
|
||||
else if (one_file_system_option && device != stat_data.st_dev)
|
||||
@@ -732,17 +776,35 @@ scan_directory (char *dir, dev_t device)
|
||||
free (itr);
|
||||
}
|
||||
|
||||
free (name_buffer);
|
||||
namebuf_free (nbuf);
|
||||
|
||||
if (dirp)
|
||||
free (dirp);
|
||||
|
||||
return directory->dump ? directory->dump->contents : NULL;
|
||||
return directory;
|
||||
}
|
||||
|
||||
/* Return pointer to the contents of the directory DIR */
|
||||
const char *
|
||||
get_directory_contents (char *dir, dev_t device)
|
||||
directory_contents (struct directory *dir)
|
||||
{
|
||||
return scan_directory (dir, device);
|
||||
if (!dir)
|
||||
return NULL;
|
||||
return dir->dump ? dir->dump->contents : NULL;
|
||||
}
|
||||
|
||||
/* A "safe" version of directory_contents, which never returns NULL. */
|
||||
const char *
|
||||
safe_directory_contents (struct directory *dir)
|
||||
{
|
||||
const char *ret = directory_contents (dir);
|
||||
return ret ? ret : "\0\0\0\0";
|
||||
}
|
||||
|
||||
void
|
||||
name_fill_directory (struct name *name, dev_t device, bool cmdline)
|
||||
{
|
||||
name->directory = scan_directory (name->name, device, cmdline);
|
||||
}
|
||||
|
||||
|
||||
@@ -805,17 +867,19 @@ store_rename (struct directory *dir, struct obstack *stk)
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
append_incremental_renames (const char *dump)
|
||||
void
|
||||
append_incremental_renames (struct directory *dir)
|
||||
{
|
||||
struct obstack stk;
|
||||
size_t size;
|
||||
struct directory *dp;
|
||||
const char *dump;
|
||||
|
||||
if (dirhead == NULL)
|
||||
return dump;
|
||||
return;
|
||||
|
||||
obstack_init (&stk);
|
||||
dump = directory_contents (dir);
|
||||
if (dump)
|
||||
{
|
||||
size = dumpdir_size (dump) - 1;
|
||||
@@ -830,11 +894,10 @@ append_incremental_renames (const char *dump)
|
||||
if (obstack_object_size (&stk) != size)
|
||||
{
|
||||
obstack_1grow (&stk, 0);
|
||||
dump = obstack_finish (&stk);
|
||||
dumpdir_free (dir->dump);
|
||||
dir->dump = dumpdir_create (obstack_finish (&stk));
|
||||
}
|
||||
else
|
||||
obstack_free (&stk, NULL);
|
||||
return dump;
|
||||
obstack_free (&stk, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -859,8 +922,8 @@ read_incr_db_01 (int version, const char *initbuf)
|
||||
uintmax_t u;
|
||||
time_t sec;
|
||||
long int nsec;
|
||||
char *buf = 0;
|
||||
size_t bufsize;
|
||||
char *buf = NULL;
|
||||
size_t bufsize = 0;
|
||||
char *ebuf;
|
||||
long lineno = 1;
|
||||
|
||||
@@ -1219,13 +1282,16 @@ void
|
||||
read_directory_file (void)
|
||||
{
|
||||
int fd;
|
||||
char *buf = 0;
|
||||
size_t bufsize;
|
||||
char *buf = NULL;
|
||||
size_t bufsize = 0;
|
||||
int flags = O_RDWR | O_CREAT;
|
||||
|
||||
if (incremental_level == 0)
|
||||
flags |= O_TRUNC;
|
||||
/* Open the file for both read and write. That way, we can write
|
||||
it later without having to reopen it, and don't have to worry if
|
||||
we chdir in the meantime. */
|
||||
fd = open (listed_incremental_option, O_RDWR | O_CREAT, MODE_RW);
|
||||
fd = open (listed_incremental_option, flags, MODE_RW);
|
||||
if (fd < 0)
|
||||
{
|
||||
open_error (listed_incremental_option);
|
||||
@@ -1240,6 +1306,13 @@ read_directory_file (void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Consume the first name from the name list and reset the
|
||||
list afterwards. This is done to change to the new
|
||||
directory, if the first name is a chdir request (-C dir),
|
||||
which is necessary to recreate absolute file names. */
|
||||
name_from_list ();
|
||||
blank_name_list ();
|
||||
|
||||
if (0 < getline (&buf, &bufsize, listed_incremental_stream))
|
||||
{
|
||||
char *ebuf;
|
||||
@@ -1337,7 +1410,7 @@ write_directory_file (void)
|
||||
if (! fp)
|
||||
return;
|
||||
|
||||
if (fseek (fp, 0L, SEEK_SET) != 0)
|
||||
if (fseeko (fp, 0L, SEEK_SET) != 0)
|
||||
seek_error (listed_incremental_option);
|
||||
if (sys_truncate (fileno (fp)) != 0)
|
||||
truncate_error (listed_incremental_option);
|
||||
@@ -1494,7 +1567,8 @@ dumpdir_ok (char *dumpdir)
|
||||
}
|
||||
|
||||
if (has_tempdir)
|
||||
WARN ((0, 0, _("Malformed dumpdir: 'X' never used")));
|
||||
WARNOPT (WARN_BAD_DUMPDIR,
|
||||
(0, 0, _("Malformed dumpdir: 'X' never used")));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
205
src/list.c
205
src/list.c
@@ -1,7 +1,7 @@
|
||||
/* List a tar archive, with support routines for reading a tar archive.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by John Gilmore, on 1985-08-26.
|
||||
|
||||
@@ -33,6 +33,7 @@ union block *recent_long_name; /* recent long name header and contents */
|
||||
union block *recent_long_link; /* likewise, for long link */
|
||||
size_t recent_long_name_blocks; /* number of blocks in recent_long_name */
|
||||
size_t recent_long_link_blocks; /* likewise, for long link */
|
||||
union block *recent_global_header; /* Recent global header block */
|
||||
|
||||
static uintmax_t from_header (const char *, size_t, const char *,
|
||||
uintmax_t, uintmax_t, bool, bool);
|
||||
@@ -77,7 +78,8 @@ read_and (void (*do_something) (void))
|
||||
prev_status = status;
|
||||
tar_stat_destroy (¤t_stat_info);
|
||||
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
switch (status)
|
||||
{
|
||||
case HEADER_STILL_UNREAD:
|
||||
@@ -138,11 +140,13 @@ read_and (void (*do_something) (void))
|
||||
{
|
||||
char buf[UINTMAX_STRSIZE_BOUND];
|
||||
|
||||
status = read_header (false);
|
||||
status = read_header (¤t_header, ¤t_stat_info,
|
||||
read_header_auto);
|
||||
if (status == HEADER_ZERO_BLOCK)
|
||||
break;
|
||||
WARN ((0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
WARNOPT (WARN_ALONE_ZERO_BLOCK,
|
||||
(0, 0, _("A lone zero block at %s"),
|
||||
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
|
||||
break;
|
||||
}
|
||||
status = prev_status;
|
||||
@@ -204,11 +208,12 @@ void
|
||||
list_archive (void)
|
||||
{
|
||||
off_t block_ordinal = current_block_ordinal ();
|
||||
/* Print the header block. */
|
||||
|
||||
/* Print the header block. */
|
||||
|
||||
decode_header (current_header, ¤t_stat_info, ¤t_format, 0);
|
||||
if (verbose_option)
|
||||
print_header (¤t_stat_info, block_ordinal);
|
||||
print_header (¤t_stat_info, current_header, block_ordinal);
|
||||
|
||||
if (incremental_option)
|
||||
{
|
||||
@@ -279,20 +284,29 @@ tar_checksum (union block *header, bool silent)
|
||||
}
|
||||
|
||||
/* Read a block that's supposed to be a header block. Return its
|
||||
address in "current_header", and if it is good, the file's size
|
||||
and names (file name, link name) in *info.
|
||||
address in *RETURN_BLOCK, and if it is good, the file's size
|
||||
and names (file name, link name) in *INFO.
|
||||
|
||||
Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a
|
||||
block full of zeros (EOF marker).
|
||||
Return one of enum read_header describing the status of the
|
||||
operation.
|
||||
|
||||
If RAW_EXTENDED_HEADERS is nonzero, do not automagically fold the
|
||||
GNU long name and link headers into later headers.
|
||||
The MODE parameter instructs read_header what to do with special
|
||||
header blocks, i.e.: extended POSIX, GNU long name or long link,
|
||||
etc.:
|
||||
|
||||
You must always set_next_block_after(current_header) to skip past
|
||||
read_header_auto process them automatically,
|
||||
read_header_x_raw when a special header is read, return
|
||||
HEADER_SUCCESS_EXTENDED without actually
|
||||
processing the header,
|
||||
read_header_x_global when a POSIX global header is read,
|
||||
decode it and return HEADER_SUCCESS_EXTENDED.
|
||||
|
||||
You must always set_next_block_after(*return_block) to skip past
|
||||
the header which this routine reads. */
|
||||
|
||||
enum read_header
|
||||
read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
read_header (union block **return_block, struct tar_stat_info *info,
|
||||
enum read_header_mode mode)
|
||||
{
|
||||
union block *header;
|
||||
union block *header_copy;
|
||||
@@ -309,7 +323,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
enum read_header status;
|
||||
|
||||
header = find_next_block ();
|
||||
current_header = header;
|
||||
*return_block = header;
|
||||
if (!header)
|
||||
return HEADER_END_OF_FILE;
|
||||
|
||||
@@ -329,7 +343,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
|| header->header.typeflag == XGLTYPE
|
||||
|| header->header.typeflag == SOLARIS_XHDTYPE)
|
||||
{
|
||||
if (raw_extended_headers)
|
||||
if (mode == read_header_x_raw)
|
||||
return HEADER_SUCCESS_EXTENDED;
|
||||
else if (header->header.typeflag == GNUTYPE_LONGNAME
|
||||
|| header->header.typeflag == GNUTYPE_LONGLINK)
|
||||
@@ -391,11 +405,18 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
else if (header->header.typeflag == XGLTYPE)
|
||||
{
|
||||
struct xheader xhdr;
|
||||
|
||||
if (!recent_global_header)
|
||||
recent_global_header = xmalloc (sizeof *recent_global_header);
|
||||
memcpy (recent_global_header, header,
|
||||
sizeof *recent_global_header);
|
||||
memset (&xhdr, 0, sizeof xhdr);
|
||||
xheader_read (&xhdr, header,
|
||||
OFF_FROM_HEADER (header->header.size));
|
||||
xheader_decode_global (&xhdr);
|
||||
xheader_destroy (&xhdr);
|
||||
if (mode == read_header_x_global)
|
||||
return HEADER_SUCCESS_EXTENDED;
|
||||
}
|
||||
|
||||
/* Loop! */
|
||||
@@ -404,7 +425,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
else
|
||||
{
|
||||
char const *name;
|
||||
struct posix_header const *h = ¤t_header->header;
|
||||
struct posix_header const *h = &header->header;
|
||||
char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];
|
||||
|
||||
if (recent_long_name)
|
||||
@@ -463,12 +484,6 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
enum read_header
|
||||
read_header (bool raw_extended_headers)
|
||||
{
|
||||
return read_header_primitive (raw_extended_headers, ¤t_stat_info);
|
||||
}
|
||||
|
||||
static char *
|
||||
decode_xform (char *file_name, void *data)
|
||||
{
|
||||
@@ -530,7 +545,9 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|
||||
enum archive_format *format_pointer, int do_user_group)
|
||||
{
|
||||
enum archive_format format;
|
||||
|
||||
unsigned hbits; /* high bits of the file mode. */
|
||||
mode_t mode = MODE_FROM_HEADER (header->header.mode, &hbits);
|
||||
|
||||
if (strcmp (header->header.magic, TMAGIC) == 0)
|
||||
{
|
||||
if (header->star_header.prefix[130] == 0
|
||||
@@ -545,12 +562,12 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
|
||||
format = USTAR_FORMAT;
|
||||
}
|
||||
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
|
||||
format = OLDGNU_FORMAT;
|
||||
format = hbits ? OLDGNU_FORMAT : GNU_FORMAT;
|
||||
else
|
||||
format = V7_FORMAT;
|
||||
*format_pointer = format;
|
||||
|
||||
stat_info->stat.st_mode = MODE_FROM_HEADER (header->header.mode);
|
||||
stat_info->stat.st_mode = mode;
|
||||
stat_info->mtime.tv_sec = TIME_FROM_HEADER (header->header.mtime);
|
||||
stat_info->mtime.tv_nsec = 0;
|
||||
assign_string (&stat_info->uname,
|
||||
@@ -667,7 +684,8 @@ from_header (char const *where0, size_t digs, char const *type,
|
||||
{
|
||||
if (type && !silent)
|
||||
ERROR ((0, 0,
|
||||
/* TRANSLATORS: %s is type of the value (gid_t, uid_t, etc.) */
|
||||
/* TRANSLATORS: %s is type of the value (gid_t, uid_t,
|
||||
etc.) */
|
||||
_("Blanks in header where numeric %s value expected"),
|
||||
type));
|
||||
return -1;
|
||||
@@ -884,25 +902,28 @@ minor_from_header (const char *p, size_t s)
|
||||
(uintmax_t) TYPE_MAXIMUM (minor_t), false, false);
|
||||
}
|
||||
|
||||
/* Convert P to the file mode, as understood by tar.
|
||||
Store unrecognized mode bits (from 10th up) in HBITS. */
|
||||
mode_t
|
||||
mode_from_header (const char *p, size_t s)
|
||||
mode_from_header (const char *p, size_t s, unsigned *hbits)
|
||||
{
|
||||
/* Do not complain about unrecognized mode bits. */
|
||||
unsigned u = from_header (p, s, "mode_t",
|
||||
- (uintmax_t) TYPE_MINIMUM (mode_t),
|
||||
TYPE_MAXIMUM (uintmax_t), false, false);
|
||||
return ((u & TSUID ? S_ISUID : 0)
|
||||
| (u & TSGID ? S_ISGID : 0)
|
||||
| (u & TSVTX ? S_ISVTX : 0)
|
||||
| (u & TUREAD ? S_IRUSR : 0)
|
||||
| (u & TUWRITE ? S_IWUSR : 0)
|
||||
| (u & TUEXEC ? S_IXUSR : 0)
|
||||
| (u & TGREAD ? S_IRGRP : 0)
|
||||
| (u & TGWRITE ? S_IWGRP : 0)
|
||||
| (u & TGEXEC ? S_IXGRP : 0)
|
||||
| (u & TOREAD ? S_IROTH : 0)
|
||||
| (u & TOWRITE ? S_IWOTH : 0)
|
||||
| (u & TOEXEC ? S_IXOTH : 0));
|
||||
mode_t mode = ((u & TSUID ? S_ISUID : 0)
|
||||
| (u & TSGID ? S_ISGID : 0)
|
||||
| (u & TSVTX ? S_ISVTX : 0)
|
||||
| (u & TUREAD ? S_IRUSR : 0)
|
||||
| (u & TUWRITE ? S_IWUSR : 0)
|
||||
| (u & TUEXEC ? S_IXUSR : 0)
|
||||
| (u & TGREAD ? S_IRGRP : 0)
|
||||
| (u & TGWRITE ? S_IWGRP : 0)
|
||||
| (u & TGEXEC ? S_IXGRP : 0)
|
||||
| (u & TOREAD ? S_IROTH : 0)
|
||||
| (u & TOWRITE ? S_IWOTH : 0)
|
||||
| (u & TOEXEC ? S_IXOTH : 0));
|
||||
*hbits = mode ^ u;
|
||||
return mode;
|
||||
}
|
||||
|
||||
off_t
|
||||
@@ -1013,9 +1034,6 @@ tartime (struct timespec t, bool full_time)
|
||||
they shouldn't. Unix tar is pretty random here anyway. */
|
||||
|
||||
|
||||
/* FIXME: Note that print_header uses the globals HEAD, HSTAT, and
|
||||
HEAD_STANDARD, which must be set up in advance. Not very clean.. */
|
||||
|
||||
/* Width of "user/group size", with initial value chosen
|
||||
heuristically. This grows as needed, though this may cause some
|
||||
stairstepping in the output. Make it too small and the output will
|
||||
@@ -1028,8 +1046,11 @@ static int ugswidth = 19;
|
||||
USGWIDTH, some stairstepping may occur. */
|
||||
static int datewidth = sizeof "YYYY-MM-DD HH:MM" - 1;
|
||||
|
||||
void
|
||||
print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
static bool volume_label_printed = false;
|
||||
|
||||
static void
|
||||
simple_print_header (struct tar_stat_info *st, union block *blk,
|
||||
off_t block_ordinal)
|
||||
{
|
||||
char modes[11];
|
||||
char const *time_stamp;
|
||||
@@ -1045,9 +1066,6 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
int pad;
|
||||
int sizelen;
|
||||
|
||||
if (test_label_option && current_header->header.typeflag != GNUTYPE_VOLHDR)
|
||||
return;
|
||||
|
||||
if (show_transformed_names_option)
|
||||
temp_name = st->file_name ? st->file_name : st->orig_file_name;
|
||||
else
|
||||
@@ -1074,9 +1092,10 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
/* File type and modes. */
|
||||
|
||||
modes[0] = '?';
|
||||
switch (current_header->header.typeflag)
|
||||
switch (blk->header.typeflag)
|
||||
{
|
||||
case GNUTYPE_VOLHDR:
|
||||
volume_label_printed = true;
|
||||
modes[0] = 'V';
|
||||
break;
|
||||
|
||||
@@ -1144,8 +1163,8 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
/* Try parsing it as an unsigned integer first, and as a
|
||||
uid_t if that fails. This method can list positive user
|
||||
ids that are too large to fit in a uid_t. */
|
||||
uintmax_t u = from_header (current_header->header.uid,
|
||||
sizeof current_header->header.uid, 0,
|
||||
uintmax_t u = from_header (blk->header.uid,
|
||||
sizeof blk->header.uid, 0,
|
||||
(uintmax_t) 0,
|
||||
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
|
||||
false, false);
|
||||
@@ -1154,7 +1173,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
else
|
||||
{
|
||||
sprintf (uform, "%ld",
|
||||
(long) UID_FROM_HEADER (current_header->header.uid));
|
||||
(long) UID_FROM_HEADER (blk->header.uid));
|
||||
user = uform;
|
||||
}
|
||||
}
|
||||
@@ -1169,8 +1188,8 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
/* Try parsing it as an unsigned integer first, and as a
|
||||
gid_t if that fails. This method can list positive group
|
||||
ids that are too large to fit in a gid_t. */
|
||||
uintmax_t g = from_header (current_header->header.gid,
|
||||
sizeof current_header->header.gid, 0,
|
||||
uintmax_t g = from_header (blk->header.gid,
|
||||
sizeof blk->header.gid, 0,
|
||||
(uintmax_t) 0,
|
||||
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
|
||||
false, false);
|
||||
@@ -1179,14 +1198,14 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
else
|
||||
{
|
||||
sprintf (gform, "%ld",
|
||||
(long) GID_FROM_HEADER (current_header->header.gid));
|
||||
(long) GID_FROM_HEADER (blk->header.gid));
|
||||
group = gform;
|
||||
}
|
||||
}
|
||||
|
||||
/* Format the file size or major/minor device numbers. */
|
||||
|
||||
switch (current_header->header.typeflag)
|
||||
switch (blk->header.typeflag)
|
||||
{
|
||||
case CHRTYPE:
|
||||
case BLKTYPE:
|
||||
@@ -1216,7 +1235,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
|
||||
fprintf (stdlis, " %s", quotearg (temp_name));
|
||||
|
||||
switch (current_header->header.typeflag)
|
||||
switch (blk->header.typeflag)
|
||||
{
|
||||
case SYMTYPE:
|
||||
fprintf (stdlis, " -> %s\n", quotearg (st->link_name));
|
||||
@@ -1229,7 +1248,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
default:
|
||||
{
|
||||
char type_string[2];
|
||||
type_string[0] = current_header->header.typeflag;
|
||||
type_string[0] = blk->header.typeflag;
|
||||
type_string[1] = '\0';
|
||||
fprintf (stdlis, _(" unknown file type %s\n"),
|
||||
quote (type_string));
|
||||
@@ -1263,7 +1282,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
case GNUTYPE_MULTIVOL:
|
||||
strcpy (size,
|
||||
STRINGIFY_BIGINT
|
||||
(UINTMAX_FROM_HEADER (current_header->oldgnu_header.offset),
|
||||
(UINTMAX_FROM_HEADER (blk->oldgnu_header.offset),
|
||||
uintbuf));
|
||||
fprintf (stdlis, _("--Continued at byte %s--\n"), size);
|
||||
break;
|
||||
@@ -1272,6 +1291,40 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
|
||||
fflush (stdlis);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
print_volume_label ()
|
||||
{
|
||||
struct tar_stat_info vstat;
|
||||
union block vblk;
|
||||
enum archive_format dummy;
|
||||
|
||||
memset (&vblk, 0, sizeof (vblk));
|
||||
vblk.header.typeflag = GNUTYPE_VOLHDR;
|
||||
if (recent_global_header)
|
||||
memcpy (vblk.header.mtime, recent_global_header->header.mtime,
|
||||
sizeof vblk.header.mtime);
|
||||
tar_stat_init (&vstat);
|
||||
assign_string (&vstat.file_name, ".");
|
||||
decode_header (&vblk, &vstat, &dummy, 0);
|
||||
assign_string (&vstat.file_name, volume_label);
|
||||
simple_print_header (&vstat, &vblk, 0);
|
||||
tar_stat_destroy (&vstat);
|
||||
}
|
||||
|
||||
void
|
||||
print_header (struct tar_stat_info *st, union block *blk,
|
||||
off_t block_ordinal)
|
||||
{
|
||||
if (current_format == POSIX_FORMAT && !volume_label_printed && volume_label)
|
||||
{
|
||||
print_volume_label ();
|
||||
volume_label_printed = true;
|
||||
}
|
||||
|
||||
simple_print_header (st, blk, block_ordinal);
|
||||
}
|
||||
|
||||
/* Print a similar line when we make a directory automatically. */
|
||||
void
|
||||
print_for_mkdir (char *dirname, int length, mode_t mode)
|
||||
@@ -1348,3 +1401,33 @@ skip_member (void)
|
||||
mv_end ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_archive_label ()
|
||||
{
|
||||
base64_init ();
|
||||
name_gather ();
|
||||
|
||||
open_archive (ACCESS_READ);
|
||||
if (read_header (¤t_header, ¤t_stat_info, read_header_auto)
|
||||
== HEADER_SUCCESS)
|
||||
{
|
||||
char *s = NULL;
|
||||
|
||||
decode_header (current_header,
|
||||
¤t_stat_info, ¤t_format, 0);
|
||||
if (current_header->header.typeflag == GNUTYPE_VOLHDR)
|
||||
assign_string (&volume_label, current_header->header.name);
|
||||
|
||||
if (volume_label
|
||||
&& (name_match (volume_label)
|
||||
|| (multi_volume_option
|
||||
&& (s = drop_volume_label_suffix (volume_label))
|
||||
&& name_match (s))))
|
||||
if (verbose_option)
|
||||
print_volume_label ();
|
||||
free (s);
|
||||
}
|
||||
close_archive ();
|
||||
names_notfound ();
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# Makefile for GNU tar on MS-DOS using Turbo C 2.0.
|
||||
# Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
CC = tcc
|
||||
RM = rm -f
|
||||
|
||||
MODEL = m
|
||||
DEFS = -DNONAMES -DNO_REMOTE -DNO_MTIO -DSTDC_HEADERS -m$(MODEL) -Dmain=_main
|
||||
LIBS =
|
||||
DEF_AR_FILE = tar.out
|
||||
DEFBLOCKING = 20
|
||||
|
||||
CFLAGS = -I. $(DEFS) \
|
||||
-DDEF_AR_FILE="$(DEF_AR_FILE)" \
|
||||
-DDEFBLOCKING=$(DEFBLOCKING)
|
||||
LDFLAGS = -m$(MODEL)
|
||||
|
||||
OBJ1 = tar.obj create.obj extract.obj buffer.obj getoldopt.obj update.obj gnu.obj mangle.obj
|
||||
OBJ2 = version.obj list.obj names.obj diffarch.obj port.obj wildmat.obj getopt.obj
|
||||
OBJ3 = getopt1.obj regex.obj getdate.obj alloca.obj tcexparg.obj msd_dir.obj
|
||||
OBJS = $(OBJ1) $(OBJ2) $(OBJ3)
|
||||
|
||||
all: tar
|
||||
|
||||
tar: testpad.h getdate.c $(OBJS)
|
||||
$(RM) testpad.obj
|
||||
$(CC) $(LDFLAGS) -etar *.obj $(LIBS)
|
||||
|
||||
.c.obj:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
testpad.h: testpad.exe
|
||||
testpad
|
||||
|
||||
testpad.exe: testpad.c
|
||||
$(CC) $(LDFLAGS) -etestpad testpad.c $(LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) errs *.obj tar testpad testpad.h
|
||||
|
||||
distclean: clean
|
||||
|
||||
realclean: clean
|
||||
164
src/misc.c
164
src/misc.c
@@ -1,7 +1,7 @@
|
||||
/* Miscellaneous functions, not really specific to GNU tar.
|
||||
|
||||
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
2003, 2004, 2005, 2006, 2007, 2009 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
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <xgetcwd.h>
|
||||
#include <unlinkdir.h>
|
||||
#include <utimens.h>
|
||||
#include <canonicalize.h>
|
||||
|
||||
#if HAVE_STROPTS_H
|
||||
# include <stropts.h>
|
||||
@@ -214,6 +215,46 @@ unquote_string (char *string)
|
||||
*destination = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Zap trailing slashes. */
|
||||
char *
|
||||
zap_slashes (char *name)
|
||||
{
|
||||
char *q;
|
||||
|
||||
if (!name || *name == 0)
|
||||
return name;
|
||||
q = name + strlen (name) - 1;
|
||||
while (q > name && ISSLASH (*q))
|
||||
*q-- = '\0';
|
||||
return name;
|
||||
}
|
||||
|
||||
char *
|
||||
normalize_filename (const char *name)
|
||||
{
|
||||
return zap_slashes (canonicalize_filename_mode (name, CAN_MISSING));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
replace_prefix (char **pname, const char *samp, size_t slen,
|
||||
const char *repl, size_t rlen)
|
||||
{
|
||||
char *name = *pname;
|
||||
size_t nlen = strlen (name);
|
||||
if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
|
||||
{
|
||||
if (rlen > slen)
|
||||
{
|
||||
name = xrealloc (name, nlen - slen + rlen + 1);
|
||||
*pname = name;
|
||||
}
|
||||
memmove (name + rlen, name + slen, nlen - slen + 1);
|
||||
memcpy (name, repl, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handling numbers. */
|
||||
|
||||
@@ -257,6 +298,10 @@ code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
|
||||
char *np;
|
||||
bool negative = s < 0;
|
||||
|
||||
/* ignore invalid values of ns */
|
||||
if (BILLION <= ns || ns < 0)
|
||||
ns = 0;
|
||||
|
||||
if (negative && ns != 0)
|
||||
{
|
||||
s++;
|
||||
@@ -417,6 +462,15 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
|
||||
{
|
||||
struct stat file_stat;
|
||||
|
||||
assign_string (&before_backup_name, file_name);
|
||||
|
||||
/* A run situation may exist between Emacs or other GNU programs trying to
|
||||
make a backup for the same file simultaneously. If theoretically
|
||||
possible, real problems are unlikely. Doing any better would require a
|
||||
convention, GNU-wide, for all programs doing backups. */
|
||||
|
||||
assign_string (&after_backup_name, 0);
|
||||
|
||||
/* Check if we really need to backup the file. */
|
||||
|
||||
if (this_is_the_archive && _remdev (file_name))
|
||||
@@ -438,14 +492,6 @@ maybe_backup_file (const char *file_name, bool this_is_the_archive)
|
||||
&& (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
|
||||
return true;
|
||||
|
||||
assign_string (&before_backup_name, file_name);
|
||||
|
||||
/* A run situation may exist between Emacs or other GNU programs trying to
|
||||
make a backup for the same file simultaneously. If theoretically
|
||||
possible, real problems are unlikely. Doing any better would require a
|
||||
convention, GNU-wide, for all programs doing backups. */
|
||||
|
||||
assign_string (&after_backup_name, 0);
|
||||
after_backup_name = find_backup_file_name (file_name, backup_type);
|
||||
if (! after_backup_name)
|
||||
xalloc_die ();
|
||||
@@ -531,17 +577,25 @@ struct wd
|
||||
static struct wd *wd;
|
||||
|
||||
/* The number of working directories in the vector. */
|
||||
static size_t wds;
|
||||
static size_t wd_count;
|
||||
|
||||
/* The allocated size of the vector. */
|
||||
static size_t wd_alloc;
|
||||
|
||||
int
|
||||
chdir_count ()
|
||||
{
|
||||
if (wd_count == 0)
|
||||
return wd_count;
|
||||
return wd_count - 1;
|
||||
}
|
||||
|
||||
/* DIR is the operand of a -C option; add it to vector of chdir targets,
|
||||
and return the index of its location. */
|
||||
int
|
||||
chdir_arg (char const *dir)
|
||||
{
|
||||
if (wds == wd_alloc)
|
||||
if (wd_count == wd_alloc)
|
||||
{
|
||||
if (wd_alloc == 0)
|
||||
{
|
||||
@@ -551,11 +605,11 @@ chdir_arg (char const *dir)
|
||||
else
|
||||
wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
|
||||
|
||||
if (! wds)
|
||||
if (! wd_count)
|
||||
{
|
||||
wd[wds].name = ".";
|
||||
wd[wds].saved = 0;
|
||||
wds++;
|
||||
wd[wd_count].name = ".";
|
||||
wd[wd_count].saved = 0;
|
||||
wd_count++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,12 +621,12 @@ chdir_arg (char const *dir)
|
||||
for (dir += 2; ISSLASH (*dir); dir++)
|
||||
continue;
|
||||
if (! dir[dir[0] == '.'])
|
||||
return wds - 1;
|
||||
return wd_count - 1;
|
||||
}
|
||||
|
||||
wd[wds].name = dir;
|
||||
wd[wds].saved = 0;
|
||||
return wds++;
|
||||
wd[wd_count].name = dir;
|
||||
wd[wd_count].saved = 0;
|
||||
return wd_count++;
|
||||
}
|
||||
|
||||
/* Change to directory I. If I is 0, change to the initial working
|
||||
@@ -695,6 +749,36 @@ stat_diag (char const *name)
|
||||
stat_error (name);
|
||||
}
|
||||
|
||||
void
|
||||
file_removed_diag (const char *name, bool top_level,
|
||||
void (*diagfn) (char const *name))
|
||||
{
|
||||
if (!top_level && errno == ENOENT)
|
||||
{
|
||||
WARNOPT (WARN_FILE_REMOVED,
|
||||
(0, 0, _("%s: File removed before we read it"),
|
||||
quotearg_colon (name)));
|
||||
set_exit_status (TAREXIT_DIFFERS);
|
||||
}
|
||||
else
|
||||
diagfn (name);
|
||||
}
|
||||
|
||||
void
|
||||
dir_removed_diag (const char *name, bool top_level,
|
||||
void (*diagfn) (char const *name))
|
||||
{
|
||||
if (!top_level && errno == ENOENT)
|
||||
{
|
||||
WARNOPT (WARN_FILE_REMOVED,
|
||||
(0, 0, _("%s: Directory removed before we read it"),
|
||||
quotearg_colon (name)));
|
||||
set_exit_status (TAREXIT_DIFFERS);
|
||||
}
|
||||
else
|
||||
diagfn (name);
|
||||
}
|
||||
|
||||
void
|
||||
write_fatal_details (char const *name, ssize_t status, size_t size)
|
||||
{
|
||||
@@ -746,3 +830,45 @@ page_aligned_alloc (void **ptr, size_t size)
|
||||
*ptr = xmalloc (size1);
|
||||
return ptr_align (*ptr, alignment);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct namebuf
|
||||
{
|
||||
char *buffer; /* directory, `/', and directory member */
|
||||
size_t buffer_size; /* allocated size of name_buffer */
|
||||
size_t dir_length; /* length of directory part in buffer */
|
||||
};
|
||||
|
||||
namebuf_t
|
||||
namebuf_create (const char *dir)
|
||||
{
|
||||
namebuf_t buf = xmalloc (sizeof (*buf));
|
||||
buf->buffer_size = strlen (dir) + 2;
|
||||
buf->buffer = xmalloc (buf->buffer_size);
|
||||
strcpy (buf->buffer, dir);
|
||||
buf->dir_length = strlen (buf->buffer);
|
||||
if (!ISSLASH (buf->buffer[buf->dir_length - 1]))
|
||||
buf->buffer[buf->dir_length++] = DIRECTORY_SEPARATOR;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
namebuf_free (namebuf_t buf)
|
||||
{
|
||||
free (buf->buffer);
|
||||
free (buf);
|
||||
}
|
||||
|
||||
char *
|
||||
namebuf_name (namebuf_t buf, const char *name)
|
||||
{
|
||||
size_t len = strlen (name);
|
||||
while (buf->dir_length + len + 1 >= buf->buffer_size)
|
||||
buf->buffer = x2realloc (buf->buffer, &buf->buffer_size);
|
||||
strcpy (buf->buffer + buf->dir_length, name);
|
||||
return buf->buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user