pax_global_header00006660000000000000000000000064122253056000014505gustar00rootroot0000000000000052 comment=0907a9034eaf2a57e8e4a9439f793f3f05d446cd libtar/000077500000000000000000000000001222530560000123265ustar00rootroot00000000000000libtar/.cvsignore000066400000000000000000000000451222530560000143250ustar00rootroot00000000000000autom4te.cache config.h.in configure libtar/AUTHORS000066400000000000000000000000001222530560000133640ustar00rootroot00000000000000libtar/COPYING000077700000000000000000000000001222530560000146472COPYRIGHTustar00rootroot00000000000000libtar/COPYRIGHT000066400000000000000000000033721222530560000136260ustar00rootroot00000000000000Copyright (c) 1998-2003 University of Illinois Board of Trustees Copyright (c) 1998-2003 Mark D. Roth All rights reserved. Developed by: Campus Information Technologies and Educational Services, University of Illinois at Urbana-Champaign Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of Campus Information Technologies and Educational Services, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. libtar/ChangeLog000066400000000000000000000257271222530560000141150ustar00rootroot00000000000000 NOTE: All releases below marked (Chris Frey) are maintenance releases done by Chris Frey, temporarily stepping in for Mark Roth. These releases are git-based only and can be found at: http://repo.or.cz/w/libtar.git Both git downloads and tarball downloads are possible at this site. libtar 1.2.20 - 2013/10/09 (Chris Frey) ------------- Added extern "C" protectors to listhash.h Added autoconf checks for __thread compiler support Fixed size_t overflow bug, as reported by Timo Warns Fixed thread-safe bug in th_get_pathname() (Sergey Zhitomirsky) libtar 1.2.19 - 2012/12/11 (Chris Frey) ------------- Removed varargs.h and all dependencies, to avoid user compile errors Fixed some short int / int compiler warnings in va_arg() usage Fixed some gcc built-in compiler warnings Changed autoconf support code from AC_RUN_ to AC_COMPILE_ to fix issues reported during cross-compiling. Applied most of Jan Cermak's const char* function argument patch. libtar 1.2.18 - 2012/08/02 (Chris Frey) ------------- Added more forgiving CRC checking logic when reading tar files Note: If your application uses the macro th_crc_ok(), then to gain full advantage of the changes in this version, you will need to recompile your application against the new headers. Otherwise, the library is drop-in replaceable, as usual. libtar 1.2.17 - 2012/07/24 (Chris Frey) ------------- Applied Tim Band's checksum patch from mailing list (thanks!) libtar 1.2.16 - 2012/05/17 (Chris Frey) ------------- Fixed build system to allow for out-of-source tree builds libtar 1.2.15 - 2012/05/10 (Chris Frey) ------------- Chris Frey (1): Fixed harmless buffer overflow which is caught by FORTIFY on some systems libtar 1.2.14 - 2011/12/22 (Chris Frey) ------------- Chris Frey (1): Fixed truncation check, so 100 char names get GNU extension support when enabled libtar 1.2.13 - 2011/06/13 (Chris Frey) ------------- Chris Frey (10): Fixed incorrect URL in readme Added autoconf/ as macro dir Added autogen.sh script to build a fresh configure Renamed autoconf/aclocal.m4 to psg.m4 so aclocal isn't so confused Removed m4 includes, and straightened out [] m4 quoting for modern autoconfs Removed auto-generated files Added datarootdir to Makefile.in's Fixed header warnings Applied Marcin Gibula's patch fixing tar_extract_glob() Changed root Makefile.in to Makefile.am, which make autoreconf workable Glenn McGrath (1): Use libtool to build dynamic library James Morrison (1): Document stupidity of tartype_t in libtar.c. Magnus Holmgren (1): Escape hyphens that should be minus signs in man pages. Per Lidén (2): Fix memory leak in th_get_pathname Reduce memory used by libtar when extracting files. ------------------------------------------------------------------------------ libtar 1.2.11 - 3/2/03 ------------- - updated autoconf macros, compat code, and listhash code - fixed tar_extract_regfile() to pass mode argument to open() (caused EPERM on Solaris NFS clients) - updated README ------------------------------------------------------------------------------ libtar 1.2.10 - 12/15/02 ------------- - updated README - minor Makefile fixes - fixed TH_ISREG() macro to not return true for hard links ------------------------------------------------------------------------------ libtar 1.2.9 - 11/19/02 ------------ - fixed th_read() to return 1 on EOF (thanks to Yves Crespin for the bug report) - minor portability fixes (thanks to Yves Crespin for the bug report) - fixed segfault on extracting filenames with 8-bit ASCII characters (thanks to Per Liden for the patch) - fixed TH_ISDIR() macro and th_get_mode() function to handle old archives that don't set the typeflag field right for directories - use 0777 instead of 0755 in mkdirhier() (thanks to Yves Crespin for the bug report) ------------------------------------------------------------------------------ libtar 1.2.8 - 9/13/02 ------------ - added "-I../listhash" to CPPFLAGS in libtar/Makefile.in (thanks to Kris Warkentin for the bug report) - added .PHONY target to Makefile.in (thanks to Steven Engelhardt for the bug report) ------------------------------------------------------------------------------ libtar 1.2.7 - 9/12/02 ------------ - fixed minor bugs in listhash code (thanks to Jim Knoble for the bug reports) ------------------------------------------------------------------------------ libtar 1.2.6 - 9/10/02 ------------ - updated COPYRIGHT file - do not check magic field by default (replaced TAR_IGNORE_MAGIC option with TAR_CHECK_MAGIC to enable check) - fixed th_get_mode() not to modify S_IFMT bits if they were already set - fixed TH_IS*() macros to check the S_IFMT mode bits in addition to typeflag (this allows us to handle old tar archives that set mode bits but not typeflag field for directories and other special files) - updated to autoconf-2.53 - restructured autoconf macros - added "b" to gzoflags in gzopen_frontend() for win32 compatibility (thanks to Kris Eric Warkentin for reporting this) - if O_BINARY is defined (as on win32), set that bit in oflags in tar_open() (thanks to Kris Eric Warkentin for reporting this) - also use O_BINARY in when calling open() from tar_extract_regfile() (based on patch from Graeme Peterson ) - added COMPAT_FUNC_MAKEDEV macro to handle 3-arg version of makedev() (based on patch from Graeme Peterson ) ------------------------------------------------------------------------------ libtar 1.2.5 - 2/20/02 ------------ - updated to autoconf-2.52 - improved Makefile portability - fixed memory leak in hard-link detection code (thanks to Michael Kamp for the bug report) - fixed memory leak in symlink handling code (thanks to Michael Kamp for the bug report) - fixed memory leak in GNU long filename code ------------------------------------------------------------------------------ libtar 1.2.4 - 7/24/01 ------------ - code cleanups to make gcc -Wall happy (thanks to Jim Knoble for the patch) - call utime() before chmod() in tar_set_file_perms() for cygwin (thanks to Kris Eric Warkentin for reporting this) - added "-g" flag to trigger GNU extensions in libtar binary - fixed buffer termination bugs in POSIX filename prefix encoding (thanks to Joerg Schilling for reporting this) - fixed bug in th_crc_calc() for filenames with 8-bit ASCII characters (thanks to Hamdouni El Bachir for reporting the bug and Antoniu-George SAVU for the patch) - fixed backwards conditional expression in th_read() (thanks to Antoniu-George SAVU for the patch) - added new tar_open() options to replace compile-time settings: TAR_IGNORE_EOT, TAR_IGNORE_MAGIC, TAR_CHECK_VERSION, TAR_IGNORE_CRC (based on feedback from Kris Eric Warkentin ) ------------------------------------------------------------------------------ libtar 1.2.3 - 6/26/01 ------------ - misc portability fixes for OpenBSD - fixed libtar.h to work with C++ programs - fixed tar_extract_file() to properly check for pre-existing symlinks (based on patch from Per Lid?n ) - fixed hash creation in tar_init() - replaced mkdirhier() with non-recursive version - updated autoconf macros, compat code, and listhash code - reformatted code for readability ------------------------------------------------------------------------------ libtar 1.2.2 - 1/12/01 ------------ - fixed th_print_long_ls() to not truncate user and group names - code cleanups to make -Wall happy ------------------------------------------------------------------------------ libtar 1.2.1 - 1/8/01 ------------ - updated WSG_ENCAP autoconf macro - fixed autoconf macros to behave properly when a config.cache file is present - fixed doc/Makefile.in to create links during compilation, not installation - fixed listhash manpage .so link lists ------------------------------------------------------------------------------ libtar 1.2 - 1/4/01 ---------- - minor code cleanups ------------------------------------------------------------------------------ libtar 1.1.b8 - 1/2/01 ------------- - updated WSG_ENCAP autoconf macro ------------------------------------------------------------------------------ libtar 1.1.b7 - 12/13/00 ------------- - fixed autoconf snprintf() test to make sure it NUL-terminates ------------------------------------------------------------------------------ libtar 1.1.b6 - 11/30/00 ------------- - added $(DESTDIR) to Makefiles - Makefile changes to support WSG_PKG and WSG_ENCAP autoconf macros - changed lib/output.c to use strftime() where available ------------------------------------------------------------------------------ libtar 1.1.b5 - 10/29/00 ------------- - Makefile fix ------------------------------------------------------------------------------ libtar 1.1.b4 - 10/29/00 ------------- - more directory reorganization - minor Makefile cleanups - minor portability fixes - added function typecasting to avoid compiler warnings ------------------------------------------------------------------------------ libtar 1.1.b3 - 10/26/00 ------------- - updated aclocal.m4 - updated README - updated manpages - minor directory structure changes because of CVS setup ------------------------------------------------------------------------------ libtar 1.1.b2 - 10/5/00 ------------- - added --without-zlib configure option - minor portability fixes ------------------------------------------------------------------------------ libtar 1.1.b1 - 8/21/00 ------------- - API changes: - implemented tar_fdopen() - implemented tar_fd() - added TAR **t argument to tar_open() instead of returning dynamic memory - if TAR_NOOVERWRITE is set in options and O_CREAT is set in oflags, tar_open() automatically sets O_EXCL as well ------------------------------------------------------------------------------ libtar 1.1.b0 - 7/10/00 ------------- - API changes: - replaced internal table of tar file types with a tartype_t passed to tar_open() by the caller (allows file access methods to be defined dynamically) - fixed tar_append_tree() to grok normal files as well as directories - replaced mk_dirs_for_file() with mkdirhier() from epkg - replaced strtok_r() with strsep() - updated list/hash code to new interface - autoconf changes: - added aclocal.m4 to clean up configure.in - minor portability fixes related to lib/fnmatch.c - fixed a bug in tar_open() where the result of open() was being checked for 0 instead of -1 to detect error - updated libtar driver program to handle both .tar.gz and ordinary .tar via the -z option libtar/ChangeLog-1.0.x000066400000000000000000000076111222530560000146470ustar00rootroot00000000000000libtar 1.0.2 - 6/21/00 ------------ - tar_set_file_perms() now calls chown() only if the effective user ID is 0 (workaround for IRIX and HP-UX, which allow file giveaways) - tar_set_file_perms() now calls chmod() or lchmod() after chown() (this fixes a problem with extracting setuid files under Linux) - removed calls to fchown() and fchmod() from tar_extract_regfile() - fixed bugs in th_read() which didn't set errno properly - removed various unused variables ---------------------------------------------------------------------- libtar 1.0.1 - 4/1/00 ------------ - removed libgen.h include from dirname and basename compat code - added lib/fnmatch.c compatability module from OpenBSD - fixed several objdirs bugs in libtar/Makefile.in - misc Makefile changes (added $CPPFLAGS support, added -o flag to compile commands, use $CFLAGS on link line, etc) - removed "inline" keyword from all source files to prevent portability problems - updated README ---------------------------------------------------------------------- libtar 1.0 - 1/2/00 ---------- - various portability fixes - "make install" now runs mkencap and epkg if they're available - libmisc is now integrated into libtar ---------------------------------------------------------------------- libtar 0.5.6 beta - 12/16/99 ----------------- - changed API to allow better error reporting via errno - added manpages to document libtar API - replaced symbolic_mode() call with strmode() compatibility code ---------------------------------------------------------------------- libtar 0.5.5 beta - 11/16/99 ----------------- - fixed conditional expression in extract.c to check if we're overwriting a pre-existing file - many improvements to libtar.c driver program (better error checking, added -C and -v options, etc) - changed API to include list of canned file types, instead of passing function pointers to tar_open() - fixed tar_set_file_perms() to not complain about chown() if not root and not to call utime() on a symlink - added hash code for extracting hard links in other directory paths - fixed tar_extract_glob() to only print filenames if TAR_VERBOSE option is set - replaced GNU basename(), dirname(), and strdup() compatibility code with OpenBSD versions - configure performs super-anal checking of basename() and dirname() ---------------------------------------------------------------------- libtar 0.5.4 beta - 11/13/99 ----------------- - portability fix: use ranlib instead of ar -s - misc fixes in append.c, extract.c, and wrapper.c to do error checking - fixed a bug in tar_append_file() in append.c which added some garbage characters to encoded symlink names (wasn't NULL-terminating the result of readlink()) - fixed a bug in symbolic_mode() in output.c concerning setuid and setgid bit displaying - fixed tar_extract_all() in wrapper.c to only call print_long_ls() if the TAR_VERBOSE option is set - added libtar_version constant string to handle.c for external configure scripts to detect what version of libtar is installed ---------------------------------------------------------------------- libtar 0.5.3 beta - 09/27/99 ----------------- - fixed mk_dirs_for_file() to avoid broken dirname() implementations - misc portability fixes - merged old "compat" and "libds" directories into new "misc" directory and cleaned up Makefiles ---------------------------------------------------------------------- libtar 0.5.2 beta - 09/10/99 ----------------- - use calloc() instead of malloc() in tar_open() to fix a bounds-checking bug in tar_extract_all() - fix tar_extract_all() to properly honor the prefix argument ---------------------------------------------------------------------- libtar 0.5.1 beta - 08/27/99 ----------------- - misc portability fixes ---------------------------------------------------------------------- libtar 0.5 beta - 07/05/99 --------------- - first public release libtar/Makefile.am000066400000000000000000000003221222530560000143570ustar00rootroot00000000000000DISTCHECK_CONFIGURE_FLAGS = ACLOCAL_FLAGS = -I autoconf ACLOCAL_AMFLAGS = -I autoconf #PACKAGE_NAME = @PACKAGE_NAME@ #PACKAGE_VERSION = @PACKAGE_VERSION@ @ENCAP_DEFS@ #@SET_MAKE@ SUBDIRS = lib libtar doc libtar/NEWS000066400000000000000000000000001222530560000130130ustar00rootroot00000000000000libtar/README000066400000000000000000000063541222530560000132160ustar00rootroot00000000000000libtar - C library for manipulating tar files ====== libtar is a library for manipulating tar files from within C programs. Here are some of its features: * Handles both POSIX tar file format and the GNU extensions. * API provides functions for easy use, such as tar_extract_all(). * Also provides functions for more granular use, such as tar_append_regfile(). Installation ------------ To build libtar, you should be able to simply run these commands: ./configure make make install Encap Package Support --------------------- To build this software as an Encap package, you can pass the --enable-encap option to configure. This will be automatically enabled if the epkg or mkencap programs are detected on the system, but can be overridden by the --disable-encap option. When building an Encap package, the configure script will automatically adjust the installation prefix to use an appropriate Encap package directory. It does this using a heuristic algorithm which examines the values of the ${ENCAP_SOURCE} and ${ENCAP_TARGET} environment variables and the argument to configure's --prefix option. If mkencap was detected on the system, it will be automatically run during "make install". By default, epkg will also be run, but this can be inhibited with the --disable-epkg-install configure option. For information on the Encap package management system, see the WSG Encap Archive: http://www.encap.org/ zlib Support ------------ The configure script will attempt to find the zlib library on your system for use with the libtar driver program. The zlib package is available from: http://www.gzip.org/zlib/ If zlib is installed on your system, but you do not wish to use it, specify the --without-zlib option when you invoke configure. More Information ---------------- For documentation of the libtar API, see the enclosed manpages. For more information on the libtar package, see: http://www.feep.net/libtar/ Source code for the latest version of libtar will be available there, as well as Encap binary distributions for many common platforms. Supported Platforms ------------------- I develop and test libtar on the following platforms: AIX 4.3.3 and 5.1 HP-UX 11.00 IRIX 6.5 RedHat Linux 7.2 Solaris 8 and 9 It should also build on the following platforms, but I do not actively support them: AIX 3.2.5 AIX 4.2.1 Cygwin FreeBSD HP-UX 10.20 Linux/libc5 OpenBSD Solaris 2.5 Solaris 2.6 Solaris 7 If you successfully build libtar on another platform, please email me a patch and/or configuration information. Compatibility Code ------------------ libtar depends on some library calls which are not available or not usable on some platforms. To accomodate these systems, I've included a version of these calls in the compat subdirectory. I've slightly modified these functions for integration into this source tree, but the functionality has not been modified from the original source. Please note that while this code should work for you, I didn't write it, so please don't send me bug reports on it. Author ------ Feedback and bug reports are welcome. Mark D. Roth Campus Information Technologies and Educational Services University of Illinois at Urbana-Champaign libtar/TODO000066400000000000000000000006401222530560000130160ustar00rootroot00000000000000* library API: - revamp API (make analogs for Unix fs access calls) - add dircache list to tar handle - support star format(s)? - add support for POSIX.1-2001 pax format - large file support? - support reading from tape devices with different block sizes? * libtar program: - make the libtar program a much more fully-featured tar - move output.c and wrapper.c from lib directory to libtar directory libtar/autoconf/000077500000000000000000000000001222530560000141445ustar00rootroot00000000000000libtar/autoconf/ac_path_generic.m4000066400000000000000000000135341222530560000175070ustar00rootroot00000000000000dnl @synopsis AC_PATH_GENERIC(LIBRARY [, MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl dnl Runs a LIBRARY-config script and defines LIBRARY_CFLAGS and LIBRARY_LIBS dnl dnl The script must support `--cflags' and `--libs' args. dnl If MINIMUM-VERSION is specified, the script must also support the dnl `--version' arg. dnl If the `--with-library-[exec-]prefix' arguments to ./configure are given, dnl it must also support `--prefix' and `--exec-prefix'. dnl (In other words, it must be like gtk-config.) dnl dnl For example: dnl dnl AC_PATH_GENERIC(Foo, 1.0.0) dnl dnl would run `foo-config --version' and check that it is at least 1.0.0 dnl dnl If so, the following would then be defined: dnl dnl FOO_CFLAGS to `foo-config --cflags` dnl FOO_LIBS to `foo-config --libs` dnl dnl At present there is no support for additional "MODULES" (see AM_PATH_GTK) dnl (shamelessly stolen from gtk.m4 and then hacked around a fair amount) dnl dnl @author Angus Lees dnl @version $Id: ac_path_generic.m4,v 1.1.4.1 2002/09/06 19:43:55 roth Exp $ AC_DEFUN([AC_PATH_GENERIC], [dnl dnl we're going to need uppercase, lowercase and user-friendly versions of the dnl string `LIBRARY' pushdef([UP], translit([$1], [a-z], [A-Z]))dnl pushdef([DOWN], translit([$1], [A-Z], [a-z]))dnl dnl dnl Get the cflags and libraries from the LIBRARY-config script dnl AC_ARG_WITH(DOWN-prefix,[ --with-]DOWN[-prefix=PFX Prefix where $1 is installed (optional)], DOWN[]_config_prefix="$withval", DOWN[]_config_prefix="") AC_ARG_WITH(DOWN-exec-prefix,[ --with-]DOWN[-exec-prefix=PFX Exec prefix where $1 is installed (optional)], DOWN[]_config_exec_prefix="$withval", DOWN[]_config_exec_prefix="") if test x$DOWN[]_config_exec_prefix != x ; then DOWN[]_config_args="$DOWN[]_config_args --exec-prefix=$DOWN[]_config_exec_prefix" if test x${UP[]_CONFIG+set} != xset ; then UP[]_CONFIG=$DOWN[]_config_exec_prefix/bin/DOWN-config fi fi if test x$DOWN[]_config_prefix != x ; then DOWN[]_config_args="$DOWN[]_config_args --prefix=$DOWN[]_config_prefix" if test x${UP[]_CONFIG+set} != xset ; then UP[]_CONFIG=$DOWN[]_config_prefix/bin/DOWN-config fi fi AC_PATH_PROG(UP[]_CONFIG, DOWN-config, no) ifelse([$2], , AC_MSG_CHECKING(for $1), AC_MSG_CHECKING(for $1 - version >= $2) ) no_[]DOWN="" if test "$UP[]_CONFIG" = "no" ; then no_[]DOWN=yes else UP[]_CFLAGS="`$UP[]_CONFIG $DOWN[]_config_args --cflags`" UP[]_LIBS="`$UP[]_CONFIG $DOWN[]_config_args --libs`" ifelse([$2], , ,[ DOWN[]_config_major_version=`$UP[]_CONFIG $DOWN[]_config_args \ --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` DOWN[]_config_minor_version=`$UP[]_CONFIG $DOWN[]_config_args \ --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` DOWN[]_config_micro_version=`$UP[]_CONFIG $DOWN[]_config_args \ --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` DOWN[]_wanted_major_version="regexp($2, [\<\([0-9]*\)], [\1])" DOWN[]_wanted_minor_version="regexp($2, [\<\([0-9]*\)\.\([0-9]*\)], [\2])" DOWN[]_wanted_micro_version="regexp($2, [\<\([0-9]*\).\([0-9]*\).\([0-9]*\)], [\3])" # Compare wanted version to what config script returned. # If I knew what library was being run, i'd probably also compile # a test program at this point (which also extracted and tested # the version in some library-specific way) if test "$DOWN[]_config_major_version" -lt \ "$DOWN[]_wanted_major_version" \ -o \( "$DOWN[]_config_major_version" -eq \ "$DOWN[]_wanted_major_version" \ -a "$DOWN[]_config_minor_version" -lt \ "$DOWN[]_wanted_minor_version" \) \ -o \( "$DOWN[]_config_major_version" -eq \ "$DOWN[]_wanted_major_version" \ -a "$DOWN[]_config_minor_version" -eq \ "$DOWN[]_wanted_minor_version" \ -a "$DOWN[]_config_micro_version" -lt \ "$DOWN[]_wanted_micro_version" \) ; then # older version found no_[]DOWN=yes echo -n "*** An old version of $1 " echo -n "($DOWN[]_config_major_version" echo -n ".$DOWN[]_config_minor_version" echo ".$DOWN[]_config_micro_version) was found." echo -n "*** You need a version of $1 newer than " echo -n "$DOWN[]_wanted_major_version" echo -n ".$DOWN[]_wanted_minor_version" echo ".$DOWN[]_wanted_micro_version." echo "***" echo "*** If you have already installed a sufficiently new version, this error" echo "*** probably means that the wrong copy of the DOWN-config shell script is" echo "*** being found. The easiest way to fix this is to remove the old version" echo "*** of $1, but you can also set the UP[]_CONFIG environment to point to the" echo "*** correct copy of DOWN-config. (In this case, you will have to" echo "*** modify your LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf" echo "*** so that the correct libraries are found at run-time)" fi ]) fi if test "x$no_[]DOWN" = x ; then AC_MSG_RESULT(yes) ifelse([$3], , :, [$3]) else AC_MSG_RESULT(no) if test "$UP[]_CONFIG" = "no" ; then echo "*** The DOWN-config script installed by $1 could not be found" echo "*** If $1 was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the UP[]_CONFIG environment variable to the" echo "*** full path to DOWN-config." fi UP[]_CFLAGS="" UP[]_LIBS="" ifelse([$4], , :, [$4]) fi AC_SUBST(UP[]_CFLAGS) AC_SUBST(UP[]_LIBS) popdef([UP]) popdef([DOWN]) ]) libtar/autoconf/ax_tls.m4000066400000000000000000000056541222530560000157120ustar00rootroot00000000000000# =========================================================================== # http://autoconf-archive.cryp.to/ax_tls.html # =========================================================================== # # SYNOPSIS # # AX_TLS # # DESCRIPTION # # Provides a test for the compiler support of thread local storage (TLS) # extensions. Defines TLS if it is found. Currently only knows about GCC # and MSVC. I think SunPro uses the same as GCC, and Borland apparently # supports either. # # LICENSE # # Copyright (c) 2008 Alan Woodland # # 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 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 # 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, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. AC_DEFUN([AX_TLS], [ AC_MSG_CHECKING(for thread local storage (TLS) class) AC_CACHE_VAL(ac_cv_tls, [ ax_tls_keywords="__thread __declspec(thread) none" for ax_tls_keyword in $ax_tls_keywords; do case $ax_tls_keyword in none) ac_cv_tls=none ; break ;; *) AC_TRY_COMPILE( [#include static void foo(void) { static ] $ax_tls_keyword [ int bar; exit(1); }], [], [ac_cv_tls=$ax_tls_keyword ; break], ac_cv_tls=none ) esac done ]) if test "$ac_cv_tls" != "none"; then dnl AC_DEFINE([TLS], [], [If the compiler supports a TLS storage class define it to that here]) AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here]) fi AC_MSG_RESULT($ac_cv_tls) ]) libtar/autoconf/encap.m4000066400000000000000000000110601222530560000154720ustar00rootroot00000000000000# ENCAP_PKG([mkencap-options], [install target if enabled], # [install target if disabled]) # --------------------------------------------------------- # Check for Encap tools. AC_DEFUN([ENCAP_PKG], [ MKENCAP_OPTS=$1; # allow user to disable Encap support AC_ARG_ENABLE([encap], [ --disable-encap Do not configure as an Encap package], [], [enable_encap=default]) if test "$enable_encap" != "no"; then # look for epkg and mkencap AC_PATH_PROG([EPKG], [epkg]) AC_PATH_PROG([MKENCAP], [mkencap]) # enable by default if epkg or mkencap are found if test "${EPKG:+set}" = "set" || test "${MKENCAP:+set}" = "set" && test "$enable_encap" = "default"; then enable_encap=yes; fi fi if test "$enable_encap" = "yes"; then # generate fallback values for ${ENCAP_SOURCE} and ${ENCAP_TARGET} # from the environment or the default prefix if test -z "${ENCAP_SOURCE}" && test -z "${ENCAP_TARGET}"; then ENCAP_SOURCE="${ac_default_prefix}/encap"; ENCAP_TARGET="${ac_default_prefix}"; elif test -z "${ENCAP_TARGET}"; then ENCAP_TARGET="`dirname ${ENCAP_SOURCE}`"; elif test -z "${ENCAP_SOURCE}"; then ENCAP_SOURCE="${ENCAP_TARGET}/encap"; fi # if --prefix is specified: # 1) if its next-to-last component is "encap", assume that it # points to the package directory # 2) otherwise, assume it points to the target directory if test "${prefix}" != "NONE"; then prefixdir="`dirname ${prefix}`"; prefixbase="`basename ${prefix}`"; if test "`basename ${prefixdir}`" = "encap"; then ENCAP_SOURCE="${prefixdir}"; ENCAP_TARGET="`dirname ${ENCAP_SOURCE}`"; elif test "${prefixdir}" != "${ENCAP_SOURCE}"; then ENCAP_SOURCE="${prefix}/encap"; ENCAP_TARGET="${prefix}"; fi if ( test "`basename ${prefixdir}`" = "encap" || \ test "${prefixdir}" = "${ENCAP_SOURCE}" ) && \ test "${prefixbase}" != "${PACKAGE_NAME}-${PACKAGE_VERSION}"; then ENCAP_PKGSPEC="${prefixbase}"; fi fi # display results AC_MSG_CHECKING([for Encap source directory]) AC_MSG_RESULT([${ENCAP_SOURCE}]) AC_MSG_CHECKING([for Encap target directory]) AC_MSG_RESULT([${ENCAP_TARGET}]) AC_MSG_CHECKING([for Encap package directory]) if test "${ENCAP_PKGSPEC:-unset}" = "unset"; then ENCAP_PKGSPEC='${PACKAGE_NAME}-${PACKAGE_VERSION}'; AC_MSG_RESULT([${ENCAP_SOURCE}/${PACKAGE_NAME}-${PACKAGE_VERSION}]) else AC_MSG_RESULT([${ENCAP_SOURCE}/${ENCAP_PKGSPEC}]) fi prefix='${ENCAP_SOURCE}/${ENCAP_PKGSPEC}'; # override default sysconfdir and localstatedir if test "$sysconfdir" = '${prefix}/etc'; then sysconfdir='${ENCAP_TARGET}/etc'; fi if test "$localstatedir" = '${prefix}/var'; then localstatedir='/var/lib/${PACKAGE_NAME}'; fi # check for --disable-epkg-install AC_ARG_ENABLE([epkg-install], [ --disable-epkg-install Do not run epkg during make install], [], [enable_epkg_install=yes]) if test "$enable_epkg_install" = "no"; then EPKG=":"; fi # generate Makefile variables dnl AC_SUBST([ENCAP_SOURCE]) dnl AC_SUBST([ENCAP_TARGET]) dnl AC_SUBST([ENCAP_PKGSPEC]) dnl AC_SUBST([EPKG]) dnl AC_SUBST([MKENCAP]) dnl AC_SUBST([MKENCAP_OPTS]) dnl dnl m4_ifdef([EM_MAKEFILE_END], [ dnl # generate rules for make install target dnl EM_MAKEFILE_END([[ dnl target modify : dnl command \\\${MKENCAP} \\\`test -f \\\${srcdir}/COPYRIGHT && echo -I \\\${srcdir}/COPYRIGHT\\\` \\\${MKENCAP_OPTS} -s \\\${DESTDIR}\\\${ENCAP_SOURCE} -e \\\${ENCAP_PKGSPEC} dnl command if test -z \\\\\"\\\${DESTDIR}\\\\\"; then \ dnl \\\${EPKG} -s \\\${ENCAP_SOURCE} -t \\\${ENCAP_TARGET} \\\${ENCAP_PKGSPEC}; \ dnl fi dnl ]])]) ENCAP_DEFS="ENCAP_SOURCE = ${ENCAP_SOURCE}\\ ENCAP_TARGET = ${ENCAP_TARGET}\\ ENCAP_PKGSPEC = ${ENCAP_PKGSPEC}\\ EPKG = ${EPKG:-:}\\ MKENCAP = ${MKENCAP:-:}\\ MKENCAP_OPTS = ${MKENCAP_OPTS}"; AC_SUBST([ENCAP_DEFS]) dnl ### generate rules for make install target ENCAP_INSTALL_RULES='if test -f ${top_srcdir}/COPYRIGHT; then \\\ ${INSTALL_DATA} ${top_srcdir}/COPYRIGHT ${ENCAP_SOURCE}/${ENCAP_PKGSPEC}; \\\ fi\ ${MKENCAP} ${MKENCAP_OPTS} -s ${DESTDIR}${ENCAP_SOURCE} -e ${ENCAP_PKGSPEC};\ if test -z \"${DESTDIR}\"; then \\\ ${EPKG} -s ${ENCAP_SOURCE} -t ${ENCAP_TARGET} ${ENCAP_PKGSPEC}; \\\ fi'; AC_SUBST([ENCAP_INSTALL_RULES]) ENCAP_INSTALL_TARGET=$2 else ENCAP_INSTALL_TARGET=$3 fi AC_SUBST([ENCAP_INSTALL_TARGET]) ]) libtar/autoconf/psg.m4000066400000000000000000000112411222530560000151760ustar00rootroot00000000000000# PSG_LIB_READLINE # ---------------- # Check for GNU readline library. AC_DEFUN([PSG_LIB_READLINE], [ AC_CHECK_HEADERS([readline/readline.h]) AC_CHECK_HEADERS([readline/history.h]) if test "$ac_cv_header_readline_readline_h" = "yes"; then AC_SEARCH_LIBS([tputs], [termcap curses]) AC_CHECK_LIB([readline], [rl_callback_handler_install]) fi ]) # PSG_LIB_TAR # ----------- # Check for usable version of libtar library. AC_DEFUN([PSG_LIB_TAR], [ psg_old_libs="$LIBS" LIBS="$LIBS -ltar" AC_CACHE_CHECK([for usable version of libtar], [psg_cv_lib_tar_usable], [AC_TRY_RUN([ #include #include #include int main(int argc, char *argv[]) { return (strcmp(libtar_version, "1.2") >= 0 ? 0 : 1); } ], [psg_cv_lib_tar_usable=yes], [psg_cv_lib_tar_usable=no], [psg_cv_lib_tar_usable=no] )] ) if test "$psg_cv_lib_tar_usable" = "yes"; then AC_DEFINE([HAVE_LIBTAR], 1, [Define if your system has a current version of libtar]) else LIBS="$psg_old_libs" fi ]) # PSG_LIB_FGET # ------------ # Check for usable version of libfget library. AC_DEFUN([PSG_LIB_FGET], [ psg_old_libs="$LIBS" AC_CHECK_LIB([socket], [socket]) AC_CHECK_LIB([nsl], [gethostbyname]) LIBS="$LIBS -lfget" AC_CACHE_CHECK([for usable version of libfget], [psg_cv_lib_fget_usable], [AC_TRY_COMPILE([ #include ], [ FTP *ftp; char buf[10240]; struct ftp_url fu; ftp_url_parse("ftp://host.com/dir/file.txt", &fu); ftp_connect(&ftp, fu.fu_hostname, buf, sizeof(buf), 0, 0, -1, -1, NULL, NULL); ], [psg_cv_lib_fget_usable=yes], [psg_cv_lib_fget_usable=no] )] ) if test "$psg_cv_lib_fget_usable" = "yes"; then AC_DEFINE([HAVE_LIBFGET], 1, [Define if your system has a current version of libfget]) else LIBS="$psg_old_libs"; fi ]) # PSG_LIB_WRAP # ------------ # Check for TCP Wrapper library. AC_DEFUN([PSG_LIB_WRAP], [ AC_CHECK_HEADERS([tcpd.h]) if test "$ac_cv_header_tcpd_h" = "yes"; then psg_old_libs="$LIBS" LIBS="$LIBS -lwrap" AC_CACHE_CHECK([for libwrap library], [psg_cv_lib_wrap_hosts_ctl], AC_TRY_LINK([ #include #include int allow_severity; int deny_severity; ], [ hosts_ctl("test", STRING_UNKNOWN, "10.0.0.1", STRING_UNKNOWN); ], [psg_cv_lib_wrap_hosts_ctl=yes], [psg_cv_lib_wrap_hosts_ctl=no] ) ) if test "$psg_cv_lib_wrap_hosts_ctl" = "yes"; then AC_DEFINE([HAVE_LIBWRAP], 1, [Define if you have libwrap]) else LIBS="$psg_old_libs" fi fi ]) # PSG_REPLACE_TYPE(type_t, default, [includes]) # --------------------------------------------- # Check for arbitrary type in arbitrary header file(s). AC_DEFUN([PSG_REPLACE_TYPE], [AC_CHECK_TYPES([$1], , [AC_DEFINE($1, $2, [Define to `$2' if not defined in system header files.] )], $3 )] ) # PSG_SHLIB(includes, code) # ------------------------- # Check how to build shared libraries containing the specified code # (very rudimentary). AC_DEFUN([PSG_SHLIB], [ AC_MSG_CHECKING([how to build shared libraries]) cflag_options="-fpic"; ldflag_options="-G -shared"; if test "$CC" != "gcc"; then case "`uname`" in HP-UX) cflag_options="+Z $cflag_options"; ldflag_options="-Wl,-b $ldflag_options"; ;; SunOS) cflag_options="-Kpic $cflag_options"; ;; esac fi for SHLIB_CFLAGS in $cflag_options ""; do for SHLIB_LDFLAGS in $ldflag_options ""; do psg_old_cflags="$CFLAGS"; CFLAGS="$CFLAGS $SHLIB_CFLAGS"; psg_old_ldflags="$LDFLAGS"; LDFLAGS="$LDFLAGS $SHLIB_LDFLAGS"; AC_LINK_IFELSE([AC_LANG_SOURCE([[ $1 int dummy(void) { $2 return 0; } ]])], [psg_cv_flags_shlib="CFLAGS=$SHLIB_CFLAGS LDFLAGS=$SHLIB_LDFLAGS"], [psg_cv_flags_shlib=no] ) CFLAGS="$psg_old_cflags"; LDFLAGS="$psg_old_ldflags"; if test "$psg_cv_flags_shlib" != "no"; then break; fi done if test "$psg_cv_flags_shlib" != "no"; then break; fi done if test "$psg_cv_flags_shlib" = "no"; then SHLIB_CFLAGS=""; SHLIB_LDFLAGS=""; fi AC_SUBST([SHLIB_CFLAGS]) AC_SUBST([SHLIB_LDFLAGS]) AC_MSG_RESULT([$psg_cv_flags_shlib]) ]) # PSG_MODULE(subdir, [args, ...]) # ------------------------------- # Process the module.ac file in subdir. If the module.ac file defines a # macro called subdir[]_INIT, call it with the arguments passed to # PSG_MODULE(). AC_DEFUN([PSG_MODULE], [ m4_define([subdir], [$1])dnl m4_include([$1]/module.ac)dnl m4_ifdef([$1][_INIT], [$1][_INIT($@)])dnl m4_undefine([subdir])dnl ]) libtar/compat/000077500000000000000000000000001222530560000136115ustar00rootroot00000000000000libtar/compat/ChangeLog000066400000000000000000000015121222530560000153620ustar00rootroot000000000000002003-01-08 added COMPAT_FUNC_MAKEDEV macro 2002-12-20 added COMPAT_VAR___PROGNAME macro 2002-12-19 include necessary header files from gethostbyname_r.c and getservbyname_r.c check for size_t in COMPAT_FUNC_GETHOSTBYNAME_R and COMPAT_FUNC_GETSERVBYNAME_R macros 2002-12-18 define _LINUX_SOURCE_COMPAT in compat.h if strsep() is needed on AIX avoid prototype syntax problem with IBM C compiler in fnmatch.c 2002-11-24 added COMPAT_PROTO_MACRO macro 2002-11-22 updated gethostbyname_r() and getservbyname_r() code and macros to detect and use weird AIX implementation added warnings if thread-safe functions are not found 2002-10-18 new macros and corresponding compat code: * COMPAT_FUNC_GETHOSTBYNAME_R * COMPAT_FUNC_GETSERVBYNAME_R 2002-10-15 added COMPAT_FUNC_GETPWUID_R macro 2002-07-17 added inet_aton.c libtar/compat/README000066400000000000000000000006661222530560000145010ustar00rootroot00000000000000Compatibility Suite ------------------- This directory contains a compatibility suite that provides alternate implementations of various library functions which are not available or not usable on some platforms. The original copyright information for each function is included in the source files. I've modified the files slightly for integration into this suite, but the functionality has not been modified from the original source. libtar/compat/TODO000066400000000000000000000003701222530560000143010ustar00rootroot00000000000000- fix COMPAT_FUNC_INET_ATON to check for existing function in -lresolv - fix COMPAT_FUNC_MAKEDEV to avoid problems with IBM C compiler (calling cpp macro with more args that necessary doesn't fail, but calling it with too few macros does fail) libtar/compat/basename.c000066400000000000000000000047241222530560000155370ustar00rootroot00000000000000/* $OpenBSD: basename.c,v 1.4 1999/05/30 17:10:30 espie Exp $ */ /* * Copyright (c) 1997 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef lint static char rcsid[] = "$OpenBSD: basename.c,v 1.4 1999/05/30 17:10:30 espie Exp $"; #endif /* not lint */ #include #include #include char * openbsd_basename(path) const char *path; { static char bname[MAXPATHLEN]; register const char *endp, *startp; /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { (void)strcpy(bname, "."); return(bname); } /* Strip trailing slashes */ endp = path + strlen(path) - 1; while (endp > path && *endp == '/') endp--; /* All slashes becomes "/" */ if (endp == path && *endp == '/') { (void)strcpy(bname, "/"); return(bname); } /* Find the start of the base */ startp = endp; while (startp > path && *(startp - 1) != '/') startp--; if (endp - startp + 1 > sizeof(bname)) { errno = ENAMETOOLONG; return(NULL); } (void)strncpy(bname, startp, endp - startp + 1); bname[endp - startp + 1] = '\0'; return(bname); } libtar/compat/compat.h000066400000000000000000000141771222530560000152570ustar00rootroot00000000000000/* prototypes for borrowed "compatibility" code */ #include #include #include #include #include #ifdef HAVE_LIBGEN_H # include #endif #if defined(NEED_BASENAME) && !defined(HAVE_BASENAME) # ifdef basename # undef basename /* fix glibc brokenness */ # endif char *openbsd_basename(const char *); # define basename openbsd_basename #endif /* NEED_BASENAME && ! HAVE_BASENAME */ #if defined(NEED_DIRNAME) && !defined(HAVE_DIRNAME) char *openbsd_dirname(const char *); # define dirname openbsd_dirname #endif /* NEED_DIRNAME && ! HAVE_DIRNAME */ #ifdef NEED_FNMATCH # ifndef HAVE_FNMATCH # define FNM_NOMATCH 1 /* Match failed. */ # define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ # define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ # define FNM_PERIOD 0x04 /* Period must be matched by period. */ # define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ # define FNM_CASEFOLD 0x10 /* Case insensitive search. */ # define FNM_IGNORECASE FNM_CASEFOLD # define FNM_FILE_NAME FNM_PATHNAME int openbsd_fnmatch(const char *, const char *, int); # define fnmatch openbsd_fnmatch # else /* HAVE_FNMATCH */ # ifdef HAVE_FNMATCH_H # include # endif # endif /* ! HAVE_FNMATCH */ #endif /* NEED_FNMATCH */ #ifdef NEED_GETHOSTBYNAME_R # include # if GETHOSTBYNAME_R_NUM_ARGS != 6 int compat_gethostbyname_r(const char *, struct hostent *, char *, size_t, struct hostent **, int *); # define gethostbyname_r compat_gethostbyname_r # endif /* GETHOSTBYNAME_R_NUM_ARGS != 6 */ #endif /* NEED_GETHOSTBYNAME_R */ #if defined(NEED_GETHOSTNAME) && !defined(HAVE_GETHOSTNAME) int gethostname(char *, size_t); #endif /* NEED_GETHOSTNAME && ! HAVE_GETHOSTNAME */ #ifdef NEED_GETSERVBYNAME_R # include # if GETSERVBYNAME_R_NUM_ARGS != 6 int compat_getservbyname_r(const char *, const char *, struct servent *, char *, size_t, struct servent **); # define getservbyname_r compat_getservbyname_r # endif /* GETSERVBYNAME_R_NUM_ARGS != 6 */ #endif /* NEED_GETSERVBYNAME_R */ #ifdef NEED_GLOB # ifndef HAVE_GLOB typedef struct { int gl_pathc; /* Count of total paths so far. */ int gl_matchc; /* Count of paths matching pattern. */ int gl_offs; /* Reserved at beginning of gl_pathv. */ int gl_flags; /* Copy of flags parameter to glob. */ char **gl_pathv; /* List of paths matching pattern. */ /* Copy of errfunc parameter to glob. */ int (*gl_errfunc)(const char *, int); /* * Alternate filesystem access methods for glob; replacement * versions of closedir(3), readdir(3), opendir(3), stat(2) * and lstat(2). */ void (*gl_closedir)(void *); struct dirent *(*gl_readdir)(void *); void *(*gl_opendir)(const char *); int (*gl_lstat)(const char *, struct stat *); int (*gl_stat)(const char *, struct stat *); } glob_t; /* Flags */ # define GLOB_APPEND 0x0001 /* Append to output from previous call. */ # define GLOB_DOOFFS 0x0002 /* Use gl_offs. */ # define GLOB_ERR 0x0004 /* Return on error. */ # define GLOB_MARK 0x0008 /* Append / to matching directories. */ # define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */ # define GLOB_NOSORT 0x0020 /* Don't sort. */ # define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ # define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ # define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */ # define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ # define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ # define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ # define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */ /* Error values returned by glob(3) */ # define GLOB_NOSPACE (-1) /* Malloc call failed. */ # define GLOB_ABORTED (-2) /* Unignored error. */ # define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */ # define GLOB_NOSYS (-4) /* Function not supported. */ # define GLOB_ABEND GLOB_ABORTED int openbsd_glob(const char *, int, int (*)(const char *, int), glob_t *); void openbsd_globfree(glob_t *); # define glob openbsd_glob # define globfree openbsd_globfree # else /* HAVE_GLOB */ # ifdef HAVE_GLOB_H # include # endif # endif /* ! HAVE_GLOB */ #endif /* NEED_GLOB */ #if defined(NEED_INET_ATON) && !defined(HAVE_INET_ATON) int inet_aton(const char *, struct in_addr *); #endif /* NEED_INET_ATON && ! HAVE_INET_ATON */ #ifdef NEED_MAKEDEV # ifdef MAJOR_IN_MKDEV # include # else # ifdef MAJOR_IN_SYSMACROS # include # endif # endif /* ** On most systems makedev() has two args. ** Some weird systems, like QNX6, have makedev() functions that expect ** an extra first argument for "node", which can be 0 for a local ** machine. */ # ifdef MAKEDEV_THREE_ARGS # define compat_makedev(maj, min) makedev(0, maj, min) # else # define compat_makedev makedev # endif #endif /* NEED_MAKEDEV */ #if defined(NEED_SNPRINTF) && !defined(HAVE_SNPRINTF) int mutt_snprintf(char *, size_t, const char *, ...); int mutt_vsnprintf(char *, size_t, const char *, va_list); #define snprintf mutt_snprintf #define vsnprintf mutt_vsnprintf #endif /* NEED_SNPRINTF && ! HAVE_SNPRINTF */ #if defined(NEED_STRLCAT) && !defined(HAVE_STRLCAT) size_t strlcat(char *, const char *, size_t); #endif /* NEED_STRLCAT && ! HAVE_STRLCAT */ #if defined(NEED_STRLCPY) && !defined(HAVE_STRLCPY) size_t strlcpy(char *, const char *, size_t); #endif /* NEED_STRLCPY && ! HAVE_STRLCPY */ #if defined(NEED_STRDUP) && !defined(HAVE_STRDUP) char *openbsd_strdup(const char *); # define strdup openbsd_strdup #endif /* NEED_STRDUP && ! HAVE_STRDUP */ #if defined(NEED_STRMODE) && !defined(HAVE_STRMODE) void strmode(register mode_t, register char *); #endif /* NEED_STRMODE && ! HAVE_STRMODE */ #if defined(NEED_STRRSTR) && !defined(HAVE_STRRSTR) char *strrstr(char *, char *); #endif /* NEED_STRRSTR && ! HAVE_STRRSTR */ #ifdef NEED_STRSEP # ifdef HAVE_STRSEP # define _LINUX_SOURCE_COMPAT /* needed on AIX 4.3.3 */ # else char *strsep(register char **, register const char *); # endif #endif /* NEED_STRSEP */ libtar/compat/dirname.c000066400000000000000000000050031222530560000153720ustar00rootroot00000000000000/* $OpenBSD: dirname.c,v 1.4 1999/05/30 17:10:30 espie Exp $ */ /* * Copyright (c) 1997 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef lint static char rcsid[] = "$OpenBSD: dirname.c,v 1.4 1999/05/30 17:10:30 espie Exp $"; #endif /* not lint */ #include #include #include char * openbsd_dirname(path) const char *path; { static char bname[MAXPATHLEN]; register const char *endp; /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { (void)strcpy(bname, "."); return(bname); } /* Strip trailing slashes */ endp = path + strlen(path) - 1; while (endp > path && *endp == '/') endp--; /* Find the start of the dir */ while (endp > path && *endp != '/') endp--; /* Either the dir is "/" or there are no slashes */ if (endp == path) { (void)strcpy(bname, *endp == '/' ? "/" : "."); return(bname); } else { do { endp--; } while (endp > path && *endp == '/'); } if (endp - path + 1 > sizeof(bname)) { errno = ENAMETOOLONG; return(NULL); } (void)strncpy(bname, path, endp - path + 1); bname[endp - path + 1] = '\0'; return(bname); } libtar/compat/fnmatch.c000066400000000000000000000150561222530560000154040ustar00rootroot00000000000000/* $OpenBSD: fnmatch.c,v 1.6 1998/03/19 00:29:59 millert Exp $ */ /* * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Guido van Rossum. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94"; #else static char rcsid[] = "$OpenBSD: fnmatch.c,v 1.6 1998/03/19 00:29:59 millert Exp $"; #endif #endif /* LIBC_SCCS and not lint */ /* * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. * Compares a filename or pathname to a pattern. */ #include #include #ifdef STDC_HEADERS # include #endif #ifdef HAVE_CTYPE_H # include #endif #include #define EOS '\0' #define RANGE_MATCH 1 #define RANGE_NOMATCH 0 #define RANGE_ERROR (-1) #ifdef NO_IBM_COMPILER_HORKAGE static int rangematch (const char *, char, int, char **); #else static int rangematch (); #endif int fnmatch(pattern, string, flags) const char *pattern, *string; int flags; { const char *stringstart; char *newp; char c, test; for (stringstart = string;;) switch (c = *pattern++) { case EOS: if ((flags & FNM_LEADING_DIR) && *string == '/') return (0); return (*string == EOS ? 0 : FNM_NOMATCH); case '?': if (*string == EOS) return (FNM_NOMATCH); if (*string == '/' && (flags & FNM_PATHNAME)) return (FNM_NOMATCH); if (*string == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); ++string; break; case '*': c = *pattern; /* Collapse multiple stars. */ while (c == '*') c = *++pattern; if (*string == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); /* Optimize for pattern with * at end or before /. */ if (c == EOS) { if (flags & FNM_PATHNAME) return ((flags & FNM_LEADING_DIR) || strchr(string, '/') == NULL ? 0 : FNM_NOMATCH); else return (0); } else if (c == '/' && (flags & FNM_PATHNAME)) { if ((string = strchr(string, '/')) == NULL) return (FNM_NOMATCH); break; } /* General case, use recursion. */ while ((test = *string) != EOS) { if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)) return (0); if (test == '/' && (flags & FNM_PATHNAME)) break; ++string; } return (FNM_NOMATCH); case '[': if (*string == EOS) return (FNM_NOMATCH); if (*string == '/' && (flags & FNM_PATHNAME)) return (FNM_NOMATCH); if (*string == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); switch (rangematch(pattern, *string, flags, &newp)) { case RANGE_ERROR: /* not a good range, treat as normal text */ goto normal; case RANGE_MATCH: pattern = newp; break; case RANGE_NOMATCH: return (FNM_NOMATCH); } ++string; break; case '\\': if (!(flags & FNM_NOESCAPE)) { if ((c = *pattern++) == EOS) { c = '\\'; --pattern; } } /* FALLTHROUGH */ default: normal: if (c != *string && !((flags & FNM_CASEFOLD) && (tolower((unsigned char)c) == tolower((unsigned char)*string)))) return (FNM_NOMATCH); ++string; break; } /* NOTREACHED */ } static int rangematch(pattern, test, flags, newp) const char *pattern; char test; int flags; char **newp; { int negate, ok; char c, c2; /* * A bracket expression starting with an unquoted circumflex * character produces unspecified results (IEEE 1003.2-1992, * 3.13.2). This implementation treats it like '!', for * consistency with the regular expression syntax. * J.T. Conklin (conklin@ngai.kaleida.com) */ if ((negate = (*pattern == '!' || *pattern == '^'))) ++pattern; if (flags & FNM_CASEFOLD) test = tolower((unsigned char)test); /* * A right bracket shall lose its special meaning and represent * itself in a bracket expression if it occurs first in the list. * -- POSIX.2 2.8.3.2 */ ok = 0; c = *pattern++; do { if (c == '\\' && !(flags & FNM_NOESCAPE)) c = *pattern++; if (c == EOS) return (RANGE_ERROR); if (c == '/' && (flags & FNM_PATHNAME)) return (RANGE_NOMATCH); if ((flags & FNM_CASEFOLD)) c = tolower((unsigned char)c); if (*pattern == '-' && (c2 = *(pattern+1)) != EOS && c2 != ']') { pattern += 2; if (c2 == '\\' && !(flags & FNM_NOESCAPE)) c2 = *pattern++; if (c2 == EOS) return (RANGE_ERROR); if (flags & FNM_CASEFOLD) c2 = tolower((unsigned char)c2); if (c <= test && test <= c2) ok = 1; } else if (c == test) ok = 1; } while ((c = *pattern++) != ']'); *newp = (char *)pattern; return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); } libtar/compat/gethostbyname_r.c000066400000000000000000000016061222530560000171520ustar00rootroot00000000000000/* ** Copyright 2002 University of Illinois Board of Trustees ** Copyright 2002 Mark D. Roth ** All rights reserved. ** ** gethostbyname_r.c - gethostbyname_r() function for compatibility library ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include int compat_gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen, struct hostent **hpp, int *herr) { #if GETHOSTBYNAME_R_NUM_ARGS == 5 *hpp = gethostbyname_r(name, hp, buf, buflen, herr); if (*hpp == NULL) return -1; return 0; #elif GETHOSTBYNAME_R_NUM_ARGS == 3 struct hostent_data hdata; if (gethostbyname_r(name, hp, &hdata) == -1) return -1; *hpp = hp; return 0; #endif /* GETHOSTBYNAME_R_NUM_ARGS == 5 */ } libtar/compat/gethostname.c000066400000000000000000000023341222530560000162750ustar00rootroot00000000000000/* gethostname.c: minimal substitute for missing gethostname() function * created 2000-Mar-02 jmk * requires SVR4 uname() and -lc * * by Jim Knoble * Copyright ? 2000 Jim Knoble * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear in * supporting documentation. * * This software is provided "as is", without warranty of any kind, * express or implied, including but not limited to the warranties of * merchantability, fitness for a particular purpose and * noninfringement. In no event shall the author(s) be liable for any * claim, damages or other liability, whether in an action of contract, * tort or otherwise, arising from, out of or in connection with the * software or the use or other dealings in the software. */ #include #include int gethostname(char *name, size_t len) { struct utsname u; int status = uname(&u); if (-1 != status) { strncpy(name, u.nodename, len); name[len - 1] = '\0'; } return(status); } libtar/compat/getservbyname_r.c000066400000000000000000000016261222530560000171560ustar00rootroot00000000000000/* ** Copyright 2002 University of Illinois Board of Trustees ** Copyright 2002 Mark D. Roth ** All rights reserved. ** ** getservbyname_r.c - getservbyname_r() function for compatibility library ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include int compat_getservbyname_r(const char *name, const char *proto, struct servent *sp, char *buf, size_t buflen, struct servent **spp) { #if GETSERVBYNAME_R_NUM_ARGS == 5 *spp = getservbyname_r(name, proto, sp, buf, buflen); if (*spp == NULL) return -1; return 0; #elif GETSERVBYNAME_R_NUM_ARGS == 4 struct servent_data sdata; if (getservbyname_r(name, proto, sp, &sdata) == -1) return -1; *spp = sp; return 0; #endif /* GETSERVBYNAME_R_NUM_ARGS == 5 */ } libtar/compat/glob.c000066400000000000000000000470251222530560000147100ustar00rootroot00000000000000/* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Guido van Rossum. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; #else static char rcsid[] = "$OpenBSD: glob.c,v 1.8 1998/08/14 21:39:30 deraadt Exp $"; #endif #endif /* LIBC_SCCS and not lint */ /* * glob(3) -- a superset of the one defined in POSIX 1003.2. * * The [!...] convention to negate a range is supported (SysV, Posix, ksh). * * Optional extra services, controlled by flags not defined by POSIX: * * GLOB_QUOTE: * Escaping convention: \ inhibits any special meaning the following * character might have (except \ at end of string is retained). * GLOB_MAGCHAR: * Set in gl_flags if pattern contained a globbing character. * GLOB_NOMAGIC: * Same as GLOB_NOCHECK, but it will only append pattern if it did * not contain any magic characters. [Used in csh style globbing] * GLOB_ALTDIRFUNC: * Use alternately specified directory access functions. * GLOB_TILDE: * expand ~user/foo to the /home/dir/of/user/foo * GLOB_BRACE: * expand {1,2}{a,b} to 1a 1b 2a 2b * gl_matchc: * Number of matches in the current invocation of glob. */ #include #include #include #include #include #include #include #ifdef STDC_HEADERS # include # include #endif #ifdef HAVE_UNISTD_H # include #endif #include #define DOLLAR '$' #define DOT '.' #define EOS '\0' #define LBRACKET '[' #define NOT '!' #define QUESTION '?' #define QUOTE '\\' #define RANGE '-' #define RBRACKET ']' #define SEP '/' #define STAR '*' #define TILDE '~' #define UNDERSCORE '_' #define LBRACE '{' #define RBRACE '}' #define SLASH '/' #define COMMA ',' #ifndef DEBUG #define M_QUOTE 0x8000 #define M_PROTECT 0x4000 #define M_MASK 0xffff #define M_ASCII 0x00ff typedef u_short Char; #else #define M_QUOTE 0x80 #define M_PROTECT 0x40 #define M_MASK 0xff #define M_ASCII 0x7f typedef char Char; #endif #define CHAR(c) ((Char)((c)&M_ASCII)) #define META(c) ((Char)((c)|M_QUOTE)) #define M_ALL META('*') #define M_END META(']') #define M_NOT META('!') #define M_ONE META('?') #define M_RNG META('-') #define M_SET META('[') #define ismeta(c) (((c)&M_QUOTE) != 0) static int compare (const void *, const void *); static void g_Ctoc (const Char *, char *); static int g_lstat (Char *, struct stat *, glob_t *); static DIR *g_opendir (Char *, glob_t *); static Char *g_strchr (Char *, int); #ifdef notdef static Char *g_strcat (Char *, const Char *); #endif static int g_stat (Char *, struct stat *, glob_t *); static int glob0 (const Char *, glob_t *); static int glob1 (Char *, glob_t *); static int glob2 (Char *, Char *, Char *, glob_t *); static int glob3 (Char *, Char *, Char *, Char *, glob_t *); static int globextend (const Char *, glob_t *); static const Char * globtilde (const Char *, Char *, size_t, glob_t *); static int globexp1 (const Char *, glob_t *); static int globexp2 (const Char *, const Char *, glob_t *, int *); static int match (Char *, Char *, Char *); #ifdef DEBUG static void qprintf (const char *, Char *); #endif int openbsd_glob(pattern, flags, errfunc, pglob) const char *pattern; int flags, (*errfunc) __P((const char *, int)); glob_t *pglob; { const u_char *patnext; int c; Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; patnext = (u_char *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; bufnext = patbuf; bufend = bufnext + MAXPATHLEN; if (flags & GLOB_NOESCAPE) while (bufnext < bufend && (c = *patnext++) != EOS) *bufnext++ = c; else { /* Protect the quoted characters. */ while (bufnext < bufend && (c = *patnext++) != EOS) if (c == QUOTE) { if ((c = *patnext++) == EOS) { c = QUOTE; --patnext; } *bufnext++ = c | M_PROTECT; } else *bufnext++ = c; } *bufnext = EOS; if (flags & GLOB_BRACE) return globexp1(patbuf, pglob); else return glob0(patbuf, pglob); } /* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */ static int globexp1(pattern, pglob) const Char *pattern; glob_t *pglob; { const Char* ptr = pattern; int rv; /* Protect a single {}, for find(1), like csh */ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) return glob0(pattern, pglob); while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) if (!globexp2(ptr, pattern, pglob, &rv)) return rv; return glob0(pattern, pglob); } /* * Recursive brace globbing helper. Tries to expand a single brace. * If it succeeds then it invokes globexp1 with the new pattern. * If it fails then it tries to glob the rest of the pattern and returns. */ static int globexp2(ptr, pattern, pglob, rv) const Char *ptr, *pattern; glob_t *pglob; int *rv; { int i; Char *lm, *ls; const Char *pe, *pm, *pl; Char patbuf[MAXPATHLEN + 1]; /* copy part up to the brace */ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) continue; ls = lm; /* Find the balanced brace */ for (i = 0, pe = ++ptr; *pe; pe++) if (*pe == LBRACKET) { /* Ignore everything between [] */ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) continue; if (*pe == EOS) { /* * We could not find a matching RBRACKET. * Ignore and just look for RBRACE */ pe = pm; } } else if (*pe == LBRACE) i++; else if (*pe == RBRACE) { if (i == 0) break; i--; } /* Non matching braces; just glob the pattern */ if (i != 0 || *pe == EOS) { *rv = glob0(patbuf, pglob); return 0; } for (i = 0, pl = pm = ptr; pm <= pe; pm++) switch (*pm) { case LBRACKET: /* Ignore everything between [] */ for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) continue; if (*pm == EOS) { /* * We could not find a matching RBRACKET. * Ignore and just look for RBRACE */ pm = pl; } break; case LBRACE: i++; break; case RBRACE: if (i) { i--; break; } /* FALLTHROUGH */ case COMMA: if (i && *pm == COMMA) break; else { /* Append the current string */ for (lm = ls; (pl < pm); *lm++ = *pl++) continue; /* * Append the rest of the pattern after the * closing brace */ for (pl = pe + 1; (*lm++ = *pl++) != EOS;) continue; /* Expand the current pattern */ #ifdef DEBUG qprintf("globexp2:", patbuf); #endif *rv = globexp1(patbuf, pglob); /* move after the comma, to the next string */ pl = pm + 1; } break; default: break; } *rv = 0; return 0; } /* * expand tilde from the passwd file. */ static const Char * globtilde(pattern, patbuf, patbuf_len, pglob) const Char *pattern; Char *patbuf; size_t patbuf_len; glob_t *pglob; { struct passwd *pwd; char *h; const Char *p; Char *b, *eb; if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) return pattern; /* Copy up to the end of the string or / */ eb = &patbuf[patbuf_len - 1]; for (p = pattern + 1, h = (char *) patbuf; h < (char *)eb && *p && *p != SLASH; *h++ = *p++) continue; *h = EOS; if (((char *) patbuf)[0] == EOS) { /* * handle a plain ~ or ~/ by expanding $HOME * first and then trying the password file */ #ifdef HAVE_ISSETUGID if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { #endif if ((pwd = getpwuid(getuid())) == NULL) return pattern; else h = pwd->pw_dir; #ifdef HAVE_ISSETUGID } #endif } else { /* * Expand a ~user */ if ((pwd = getpwnam((char*) patbuf)) == NULL) return pattern; else h = pwd->pw_dir; } /* Copy the home directory */ for (b = patbuf; b < eb && *h; *b++ = *h++) continue; /* Append the rest of the pattern */ while (b < eb && (*b++ = *p++) != EOS) continue; *b = EOS; return patbuf; } /* * The main glob() routine: compiles the pattern (optionally processing * quotes), calls glob1() to do the real pattern matching, and finally * sorts the list (unless unsorted operation is requested). Returns 0 * if things went well, nonzero if errors occurred. It is not an error * to find no matches. */ static int glob0(pattern, pglob) const Char *pattern; glob_t *pglob; { const Char *qpatnext; int c, err, oldpathc; Char *bufnext, patbuf[MAXPATHLEN+1]; qpatnext = globtilde(pattern, patbuf, sizeof(patbuf) / sizeof(Char), pglob); oldpathc = pglob->gl_pathc; bufnext = patbuf; /* We don't need to check for buffer overflow any more. */ while ((c = *qpatnext++) != EOS) { switch (c) { case LBRACKET: c = *qpatnext; if (c == NOT) ++qpatnext; if (*qpatnext == EOS || g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { *bufnext++ = LBRACKET; if (c == NOT) --qpatnext; break; } *bufnext++ = M_SET; if (c == NOT) *bufnext++ = M_NOT; c = *qpatnext++; do { *bufnext++ = CHAR(c); if (*qpatnext == RANGE && (c = qpatnext[1]) != RBRACKET) { *bufnext++ = M_RNG; *bufnext++ = CHAR(c); qpatnext += 2; } } while ((c = *qpatnext++) != RBRACKET); pglob->gl_flags |= GLOB_MAGCHAR; *bufnext++ = M_END; break; case QUESTION: pglob->gl_flags |= GLOB_MAGCHAR; *bufnext++ = M_ONE; break; case STAR: pglob->gl_flags |= GLOB_MAGCHAR; /* collapse adjacent stars to one, * to avoid exponential behavior */ if (bufnext == patbuf || bufnext[-1] != M_ALL) *bufnext++ = M_ALL; break; default: *bufnext++ = CHAR(c); break; } } *bufnext = EOS; #ifdef DEBUG qprintf("glob0:", patbuf); #endif if ((err = glob1(patbuf, pglob)) != 0) return(err); /* * If there was no match we are going to append the pattern * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified * and the pattern did not contain any magic characters * GLOB_NOMAGIC is there just for compatibility with csh. */ if (pglob->gl_pathc == oldpathc) { if ((pglob->gl_flags & GLOB_NOCHECK) || ((pglob->gl_flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR))) return(globextend(pattern, pglob)); else return(GLOB_NOMATCH); } if (!(pglob->gl_flags & GLOB_NOSORT)) qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, pglob->gl_pathc - oldpathc, sizeof(char *), compare); return(0); } static int compare(p, q) const void *p, *q; { return(strcmp(*(char **)p, *(char **)q)); } static int glob1(pattern, pglob) Char *pattern; glob_t *pglob; { Char pathbuf[MAXPATHLEN+1]; /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ if (*pattern == EOS) return(0); return(glob2(pathbuf, pathbuf, pattern, pglob)); } /* * The functions glob2 and glob3 are mutually recursive; there is one level * of recursion for each segment in the pattern that contains one or more * meta characters. */ static int glob2(pathbuf, pathend, pattern, pglob) Char *pathbuf, *pathend, *pattern; glob_t *pglob; { struct stat sb; Char *p, *q; int anymeta; /* * Loop over pattern segments until end of pattern or until * segment with meta character found. */ for (anymeta = 0;;) { if (*pattern == EOS) { /* End of pattern? */ *pathend = EOS; if (g_lstat(pathbuf, &sb, pglob)) return(0); if (((pglob->gl_flags & GLOB_MARK) && pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || (S_ISLNK(sb.st_mode) && (g_stat(pathbuf, &sb, pglob) == 0) && S_ISDIR(sb.st_mode)))) { *pathend++ = SEP; *pathend = EOS; } ++pglob->gl_matchc; return(globextend(pathbuf, pglob)); } /* Find end of next segment, copy tentatively to pathend. */ q = pathend; p = pattern; while (*p != EOS && *p != SEP) { if (ismeta(*p)) anymeta = 1; *q++ = *p++; } if (!anymeta) { /* No expansion, do next segment. */ pathend = q; pattern = p; while (*pattern == SEP) *pathend++ = *pattern++; } else /* Need expansion, recurse. */ return(glob3(pathbuf, pathend, pattern, p, pglob)); } /* NOTREACHED */ } static int glob3(pathbuf, pathend, pattern, restpattern, pglob) Char *pathbuf, *pathend, *pattern, *restpattern; glob_t *pglob; { register struct dirent *dp; DIR *dirp; int err; char buf[MAXPATHLEN]; /* * The readdirfunc declaration can't be prototyped, because it is * assigned, below, to two functions which are prototyped in glob.h * and dirent.h as taking pointers to differently typed opaque * structures. */ struct dirent *(*readdirfunc)(); *pathend = EOS; errno = 0; if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { /* TODO: don't call for ENOENT or ENOTDIR? */ if (pglob->gl_errfunc) { g_Ctoc(pathbuf, buf); if (pglob->gl_errfunc(buf, errno) || pglob->gl_flags & GLOB_ERR) return (GLOB_ABORTED); } return(0); } err = 0; /* Search directory for matching names. */ if (pglob->gl_flags & GLOB_ALTDIRFUNC) readdirfunc = pglob->gl_readdir; else readdirfunc = readdir; while ((dp = (*readdirfunc)(dirp))) { register u_char *sc; register Char *dc; /* Initial DOT must be matched literally. */ if (dp->d_name[0] == DOT && *pattern != DOT) continue; for (sc = (u_char *) dp->d_name, dc = pathend; (*dc++ = *sc++) != EOS;) continue; if (!match(pathend, pattern, restpattern)) { *pathend = EOS; continue; } err = glob2(pathbuf, --dc, restpattern, pglob); if (err) break; } if (pglob->gl_flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir)(dirp); else closedir(dirp); return(err); } /* * Extend the gl_pathv member of a glob_t structure to accomodate a new item, * add the new item, and update gl_pathc. * * This assumes the BSD realloc, which only copies the block when its size * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic * behavior. * * Return 0 if new item added, error code if memory couldn't be allocated. * * Invariant of the glob_t structure: * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and * gl_pathv points to (gl_offs + gl_pathc + 1) items. */ static int globextend(path, pglob) const Char *path; glob_t *pglob; { register char **pathv; register int i; u_int newsize; char *copy; const Char *p; newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : malloc(newsize); if (pathv == NULL) { if (pglob->gl_pathv) free(pglob->gl_pathv); return(GLOB_NOSPACE); } if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { /* first time around -- clear initial gl_offs items */ pathv += pglob->gl_offs; for (i = pglob->gl_offs; --i >= 0; ) *--pathv = NULL; } pglob->gl_pathv = pathv; for (p = path; *p++;) continue; if ((copy = malloc(p - path)) != NULL) { g_Ctoc(path, copy); pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; } pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; return(copy == NULL ? GLOB_NOSPACE : 0); } /* * pattern matching function for filenames. Each occurrence of the * * pattern causes a recursion level. */ static int match(name, pat, patend) register Char *name, *pat, *patend; { int ok, negate_range; Char c, k; while (pat < patend) { c = *pat++; switch (c & M_MASK) { case M_ALL: if (pat == patend) return(1); do if (match(name, pat, patend)) return(1); while (*name++ != EOS); return(0); case M_ONE: if (*name++ == EOS) return(0); break; case M_SET: ok = 0; if ((k = *name++) == EOS) return(0); if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) ++pat; while (((c = *pat++) & M_MASK) != M_END) if ((*pat & M_MASK) == M_RNG) { if (c <= k && k <= pat[1]) ok = 1; pat += 2; } else if (c == k) ok = 1; if (ok == negate_range) return(0); break; default: if (*name++ != c) return(0); break; } } return(*name == EOS); } /* Free allocated data belonging to a glob_t structure. */ void openbsd_globfree(pglob) glob_t *pglob; { register int i; register char **pp; if (pglob->gl_pathv != NULL) { pp = pglob->gl_pathv + pglob->gl_offs; for (i = pglob->gl_pathc; i--; ++pp) if (*pp) free(*pp); free(pglob->gl_pathv); } } static DIR * g_opendir(str, pglob) register Char *str; glob_t *pglob; { char buf[MAXPATHLEN]; if (!*str) strcpy(buf, "."); else g_Ctoc(str, buf); if (pglob->gl_flags & GLOB_ALTDIRFUNC) return((*pglob->gl_opendir)(buf)); return(opendir(buf)); } static int g_lstat(fn, sb, pglob) register Char *fn; struct stat *sb; glob_t *pglob; { char buf[MAXPATHLEN]; g_Ctoc(fn, buf); if (pglob->gl_flags & GLOB_ALTDIRFUNC) return((*pglob->gl_lstat)(buf, sb)); return(lstat(buf, sb)); } static int g_stat(fn, sb, pglob) register Char *fn; struct stat *sb; glob_t *pglob; { char buf[MAXPATHLEN]; g_Ctoc(fn, buf); if (pglob->gl_flags & GLOB_ALTDIRFUNC) return((*pglob->gl_stat)(buf, sb)); return(stat(buf, sb)); } static Char * g_strchr(str, ch) Char *str; int ch; { do { if (*str == ch) return (str); } while (*str++); return (NULL); } #ifdef notdef static Char * g_strcat(dst, src) Char *dst; const Char* src; { Char *sdst = dst; while (*dst++) continue; --dst; while((*dst++ = *src++) != EOS) continue; return (sdst); } #endif static void g_Ctoc(str, buf) register const Char *str; char *buf; { register char *dc; for (dc = buf; (*dc++ = *str++) != EOS;) continue; } #ifdef DEBUG static void qprintf(str, s) const char *str; register Char *s; { register Char *p; (void)printf("%s:\n", str); for (p = s; *p; p++) (void)printf("%c", CHAR(*p)); (void)printf("\n"); for (p = s; *p; p++) (void)printf("%c", *p & M_PROTECT ? '"' : ' '); (void)printf("\n"); for (p = s; *p; p++) (void)printf("%c", ismeta(*p) ? '_' : ' '); (void)printf("\n"); } #endif libtar/compat/inet_aton.c000066400000000000000000000010371222530560000157360ustar00rootroot00000000000000/* ** Copyright 2002 University of Illinois Board of Trustees ** Copyright 2002 Mark D. Roth ** All rights reserved. ** ** inet_aton.c - inet_aton() function for compatibility library ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include int inet_aton(const char *cp, struct in_addr *inp) { inp->s_addr = inet_addr(cp); if (inp->s_addr == -1) return 0; return 1; } libtar/compat/module.ac000066400000000000000000000334161222530560000154120ustar00rootroot00000000000000# COMPAT_VAR___PROGNAME # --------------------- # Check if libc defines the __progname variable. AC_DEFUN([COMPAT_VAR___PROGNAME], [ AC_CACHE_CHECK([if libc defines __progname], [ac_cv_libc_defines___progname], [AC_TRY_LINK([], [ extern char *__progname; printf("%s", __progname); ], [ac_cv_libc_defines___progname=yes], [ac_cv_libc_defines___progname=no] )] ) if test "$ac_cv_libc_defines___progname" = "yes"; then AC_DEFINE([HAVE___PROGNAME], 1, [Define if libc defines the __progname variable]) fi ]) # COMPAT_FUNC_BASENAME # -------------------- # Check for working basename() function. AC_DEFUN([COMPAT_FUNC_BASENAME], [ AC_DEFINE([NEED_BASENAME], 1, [Define if you want to use the basename function]) AC_CHECK_HEADERS([libgen.h]) AC_CACHE_CHECK([for working basename], [compat_cv_func_basename_works], [AC_TRY_RUN([ #include #ifdef HAVE_LIBGEN_H # include #endif typedef struct { char *test; char *result; } test_t; const test_t tests[] = { { "/usr/local/foo", "foo" }, { "/usr/local/foo/", "foo" }, { NULL, NULL } }; int main() { char test1[1024]; int i; for (i = 0; tests[i].test; i++) { strcpy(test1, tests[i].test); if (strcmp(basename(test1), tests[i].result) || strcmp(test1, tests[i].test)) exit(1); } exit(0); } ], [compat_cv_func_basename_works=yes], [compat_cv_func_basename_works=no], [compat_cv_func_basename_works=no] )] ) if test "$compat_cv_func_basename_works" = "yes"; then AC_DEFINE([HAVE_BASENAME], 1, [Define if your system has a working basename]) else AC_LIBOBJ([basename]) fi ]) # COMPAT_FUNC_DIRNAME # ------------------- # Check for working dirname() function. AC_DEFUN([COMPAT_FUNC_DIRNAME], [ AC_DEFINE([NEED_DIRNAME], 1, [Define if you want to use the dirname function]) AC_CHECK_HEADERS([libgen.h]) AC_CACHE_CHECK([for working dirname], [compat_cv_func_dirname_works], [AC_TRY_RUN([ #include #ifdef HAVE_LIBGEN_H # include #endif typedef struct { char *test; char *result; } test_t; const test_t tests[] = { { "foobar", "." }, { "/usr/local/foo", "/usr/local" }, { "/usr/local/foo/", "/usr/local" }, { "/", "/" }, { "", "." }, { NULL, NULL } }; int main() { char test1[1024]; int i; for (i = 0; tests[i].test; i++) { strcpy(test1, tests[i].test); if (strcmp(dirname(test1), tests[i].result) || strcmp(test1, tests[i].test)) exit(1); } exit(0); } ], [compat_cv_func_dirname_works=yes], [compat_cv_func_dirname_works=no], [compat_cv_func_dirname_works=no] )] ) if test "$compat_cv_func_dirname_works" = "yes"; then AC_DEFINE([HAVE_DIRNAME], 1, [Define if your system has a working dirname]) else AC_LIBOBJ([dirname]) fi ]) # COMPAT_FUNC_FNMATCH # ------------------- # Check for working fnmatch() function. AC_DEFUN([COMPAT_FUNC_FNMATCH], [ AC_DEFINE([NEED_FNMATCH], 1, [Define if you want to use the fnmatch function]) AC_CHECK_HEADERS([fnmatch.h]) if test "$ac_cv_header_fnmatch_h" = "yes"; then AC_FUNC_FNMATCH fi if test "$ac_cv_func_fnmatch_works" != "yes"; then AC_CHECK_HEADERS([ctype.h]) AC_LIBOBJ([fnmatch]) fi ]) # COMPAT_FUNC_GLOB # ---------------- # Check for working glob() function. AC_DEFUN([COMPAT_FUNC_GLOB], [ AC_DEFINE([NEED_GLOB], 1, [Define if you want to use the glob function]) AC_CHECK_HEADERS([glob.h]) AC_CACHE_CHECK([for working glob], [compat_cv_func_glob_works], [AC_TRY_RUN([ #include #ifdef HAVE_GLOB_H # include #endif #ifndef GLOB_ABORTED # define GLOB_ABORTED GLOB_ABEND #endif int main() { glob_t g; int status; status = glob("conf*", 0, NULL, &g); switch (status) { case 0: case GLOB_NOSPACE: case GLOB_ABORTED: case GLOB_NOMATCH: exit(0); break; default: exit(1); break; } } ], [compat_cv_func_glob_works=yes], [compat_cv_func_glob_works=no], [compat_cv_func_glob_works=no] )] ) if test "$compat_cv_func_glob_works" = "yes"; then AC_DEFINE([HAVE_GLOB], 1, [Define if your system has a working glob]) else AC_LIBOBJ([glob]) AC_CHECK_FUNCS([issetugid]) fi ]) # COMPAT_FUNC_MAKEDEV # ------------------- # Check for number of arguments expected by makedev(). AC_DEFUN([COMPAT_FUNC_MAKEDEV], [ AC_REQUIRE([AC_HEADER_MAJOR]) AC_DEFINE([NEED_MAKEDEV], 1, [Define if you want to use the makedev function]) AC_CACHE_CHECK([whether makedev expects three arguments], [compat_cv_func_makedev_three_args], [AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[ #include #ifdef MAJOR_IN_MKDEV # include #else # ifdef MAJOR_IN_SYSMACROS # include # endif #endif ]], [[ dev_t dev; major_t maj = 5; minor_t min = 7; dev = makedev(0, maj, min); if (major(dev) != maj || minor(dev) != min) exit(1); exit(0); ]])], [compat_cv_func_makedev_three_args=yes], [compat_cv_func_makedev_three_args=no] )] ) if test "$compat_cv_func_makedev_three_args" = "yes"; then AC_DEFINE([MAKEDEV_THREE_ARGS], 1, [Define as 1 if makedev expects three arguments]) fi ]) # COMPAT_FUNC_SNPRINTF # -------------------- # Check for working snprintf() function. AC_DEFUN([COMPAT_FUNC_SNPRINTF], [ AC_DEFINE([NEED_SNPRINTF], 1, [Define if you want to use the snprintf function]) AC_CACHE_CHECK([for working snprintf], [compat_cv_func_snprintf_works], [AC_TRY_RUN([ #include typedef struct { int length; char *test; int retval; char *result; } test_t; const test_t tests[] = { { 10, "12345678901234567890", 20, "123456789" }, #if 0 { 0, "12345678901234567890", 20, NULL }, { -1, "12345678901234567890", -1, NULL }, #endif { 0, NULL, 0, NULL } }; int main() { char test1[1024]; int i; for (i = 0; tests[i].test; i++) { memset(test1, 'X', sizeof(test1)); if ((snprintf(test1, tests[i].length, "%s", tests[i].test) != tests[i].retval) || (tests[i].result && strcmp(tests[i].result, test1))) exit(1); } exit(0); } ], [compat_cv_func_snprintf_works=yes], [compat_cv_func_snprintf_works=no], [compat_cv_func_snprintf_works=no] )] ) if test "$compat_cv_func_snprintf_works" = "yes"; then AC_DEFINE([HAVE_SNPRINTF], 1, [Define if your system has a working snprintf]) else AC_LIBOBJ([snprintf]) fi ]) # COMPAT_PROTO_MACRO(FUNCTION, HEADER, MACRO-LIST, [BODY]) # -------------------------------------------------------- # Determine which C preprocessor macro is needed to expose prototype of # FUNCTION in HEADER. First, we try with nothing special defined; then we # try with each macro from MACRO-LIST. We stop as soon as it's found # and adjust $CFLAGS appropriately. AC_DEFUN([COMPAT_PROTO_MACRO], [AC_CACHE_CHECK([what to define for $1 prototype], [compat_cv_proto_]$1[_macro], [AC_TRY_COMPILE( [ #include <$2> ], [ void *funcptr; $4 funcptr = $1; ], [compat_cv_proto_]$1[_macro="none"], [for macro in $3; do AC_TRY_COMPILE( [ #define $macro #include <$2> ], [ void *funcptr; $4 funcptr = $1; ], [ compat_cv_proto_]$1[_macro="$macro" break ], [compat_cv_proto_]$1[_macro="not found"] ) done] )] )] if test -n "$compat_cv_proto_$1_macro" -a "$compat_cv_proto_$1_macro" != "not found" -a "$compat_cv_proto_$1_macro" != "none"; then CFLAGS="${CFLAGS} -D$compat_cv_proto_$1_macro"; fi ) # COMPAT_FUNC_STRTOK_R # -------------------- # Check for working strtok_r(). AC_DEFUN([COMPAT_FUNC_STRTOK_R], [ AC_DEFINE([NEED_STRTOK_R], 1, [Define if you want to use the strtok_r function]) AC_REPLACE_FUNCS([strtok_r]) COMPAT_PROTO_MACRO([strtok_r], [string.h], [_REENTRANT _THREAD_SAFE]) ]) # COMPAT_FUNC_GETPWUID_R # ---------------------- # Check for POSIX-compliant getpwuid_r(). AC_DEFUN([COMPAT_FUNC_GETPWUID_R], [ COMPAT_PROTO_MACRO([getpwuid_r], [pwd.h], [_POSIX_PTHREAD_SEMANTICS _REENTRANT], [ struct passwd pwd, *pwdp; char buf[10240]; getpwuid_r(0, &pwd, buf, sizeof(buf), &pwdp); ] ) if test "$compat_cv_proto_getpwuid_r_macro" != "not found"; then AC_DEFINE([HAVE_GETPWUID_R], 1, [Define if your system has a POSIX-compliant getpwuid_r]) else AC_MSG_WARN([cannot find usable getpwuid_r - resulting libraries will not be thread-safe]) fi ]) # COMPAT_FUNC_GETHOSTBYNAME_R # --------------------------- # Check for gethostbyname_r(). AC_DEFUN([COMPAT_FUNC_GETHOSTBYNAME_R], [ AC_REQUIRE([AC_TYPE_SIZE_T]) AC_DEFINE([NEED_GETHOSTBYNAME_R], 1, [Define if you want to use the gethostbyname_r function]) AC_SEARCH_LIBS([gethostbyname_r], [nsl]) if test "$ac_cv_search_gethostbyname_r" != "no"; then COMPAT_PROTO_MACRO([gethostbyname_r], [netdb.h], [_REENTRANT]) AC_CACHE_CHECK( [for number of arguments to gethostbyname_r], [compat_cv_gethostbyname_r_args], [AC_TRY_COMPILE( [ #include ], [ struct hostent hent; char buf[10240]; int herr; gethostbyname_r("localhost", &hent, buf, sizeof(buf), &herr); ], [compat_cv_gethostbyname_r_args=5], [AC_TRY_COMPILE( [ #include ], [ struct hostent hent, *hp; char buf[10240]; int herr; gethostbyname_r("localhost", &hent, buf, sizeof(buf), &hp, &herr); ], [compat_cv_gethostbyname_r_args=6], [AC_TRY_COMPILE( [ #include ], [ struct hostent hent; struct hostent_data hdata; gethostbyname_r("localhost", &hent, &hdata); ], [compat_cv_gethostbyname_r_args=3], [compat_cv_gethostbyname_r_args=no] )] )] )] ) if test "$compat_cv_gethostbyname_r_args" != "no"; then AC_DEFINE([HAVE_GETHOSTBYNAME_R], 1, [Define if you have the gethostbyname_r function]) AC_DEFINE_UNQUOTED([GETHOSTBYNAME_R_NUM_ARGS], [$compat_cv_gethostbyname_r_args], [Define to number of arguments for gethostbyname_r]) if test "$compat_cv_gethostbyname_r_args" != "6"; then AC_LIBOBJ([gethostbyname_r]) fi else AC_MSG_WARN([unknown form of gethostbyname_r - resulting libraries will not be thread-safe]) fi else AC_MSG_WARN([cannot find gethostbyname_r - resulting libraries will not be thread-safe]) fi ]) # COMPAT_FUNC_GETSERVBYNAME_R # --------------------------- # Check for getservbyname_r(). AC_DEFUN([COMPAT_FUNC_GETSERVBYNAME_R], [ AC_REQUIRE([AC_TYPE_SIZE_T]) AC_DEFINE([NEED_GETSERVBYNAME_R], 1, [Define if you want to use the getservbyname_r function]) AC_SEARCH_LIBS([getservbyname_r], [socket nsl]) if test "$ac_cv_search_getservbyname_r" != "no"; then COMPAT_PROTO_MACRO([getservbyname_r], [netdb.h], [_REENTRANT]) AC_CACHE_CHECK( [for number of arguments to getservbyname_r], [compat_cv_getservbyname_r_args], [AC_TRY_COMPILE( [ #include ], [ struct servent sent; char buf[10240]; getservbyname_r("telnet", "tcp", &sent, buf, sizeof(buf)); ], [compat_cv_getservbyname_r_args=5], [AC_TRY_COMPILE( [ #include ], [ struct servent sent, *sp; char buf[10240]; getservbyname_r("telnet", "tcp", &sent, buf, sizeof(buf), &sp); ], [compat_cv_getservbyname_r_args=6], [AC_TRY_COMPILE( [ #include ], [ struct servent sent; struct servent_data sdata; getservbyname_r("telnet", "tcp", &sent, &sdata); ], [compat_cv_getservbyname_r_args=4], [compat_cv_getservbyname_r_args=no] )] )] )] ) if test "$compat_cv_getservbyname_r_args" != "no"; then AC_DEFINE([HAVE_GETSERVBYNAME_R], 1, [Define if you have the getservbyname_r function]) AC_DEFINE_UNQUOTED([GETSERVBYNAME_R_NUM_ARGS], [$compat_cv_getservbyname_r_args], [Define to number of arguments for getservbyname_r]) if test "$compat_cv_getservbyname_r_args" != "6"; then AC_LIBOBJ([getservbyname_r]) fi else AC_MSG_WARN([unknown form of getservbyname_r - resulting libraries will not be thread-safe]) fi else AC_MSG_WARN([cannot find getservbyname_r - resulting libraries will not be thread-safe]) fi ]) # COMPAT_REPLACE_FUNC(function) # ----------------------------- # Replacement for AC_REPLACE_FUNCS. AC_DEFUN([COMPAT_REPLACE_FUNC], [ AC_DEFINE([NEED_]translit($1,[a-z],[A-Z]), 1, [Define if you want to use the ]$1[ function]) AC_CHECK_FUNC($1, [AC_DEFINE([HAVE_]translit($1,[a-z],[A-Z]), 1, [Define if you have the ]$1[ function])], [AC_LIBOBJ(]$1[)] ) ]) # COMPAT_FUNC_GETHOSTNAME # ----------------------- # Check for gethostname(). AC_DEFUN([COMPAT_FUNC_GETHOSTNAME], [ COMPAT_REPLACE_FUNC([gethostname]) ]) # COMPAT_FUNC_INET_ATON # --------------------- # Check for inet_aton(). AC_DEFUN([COMPAT_FUNC_INET_ATON], [ COMPAT_REPLACE_FUNC([inet_aton]) ]) # COMPAT_FUNC_STRDUP # ------------------ # Check for strdup(). AC_DEFUN([COMPAT_FUNC_STRDUP], [ COMPAT_REPLACE_FUNC([strdup]) ]) # COMPAT_FUNC_STRLCAT # ------------------- # Check for strlcat(). AC_DEFUN([COMPAT_FUNC_STRLCAT], [ COMPAT_REPLACE_FUNC([strlcat]) ]) # COMPAT_FUNC_STRLCPY # ------------------- # Check for strlcpy(). AC_DEFUN([COMPAT_FUNC_STRLCPY], [ COMPAT_REPLACE_FUNC([strlcpy]) ]) # COMPAT_FUNC_STRMODE # ------------------- # Check for strmode(). AC_DEFUN([COMPAT_FUNC_STRMODE], [ COMPAT_REPLACE_FUNC([strmode]) ]) # COMPAT_FUNC_STRRSTR # ------------------- # Check for strrstr(). AC_DEFUN([COMPAT_FUNC_STRRSTR], [ COMPAT_REPLACE_FUNC([strrstr]) ]) # COMPAT_FUNC_STRSEP # ------------------ # Check for strsep(). AC_DEFUN([COMPAT_FUNC_STRSEP], [ COMPAT_REPLACE_FUNC([strsep]) ]) libtar/compat/snprintf.c000066400000000000000000000423321222530560000156240ustar00rootroot00000000000000/************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * A bombproof version of doprnt (dopr) included. * Sigh. This sort of thing is always nasty do deal with. Note that * the version here does not include floating point... * * snprintf() is used instead of sprintf() as it does limit checks * for string length. This covers a nasty loophole. * * The other functions are there to prevent NULL pointers from * causing nast effects. * * More Recently: * Brandon Long 9/15/96 for mutt 0.43 * This was ugly. It is still ugly. I opted out of floating point * numbers, but the formatter understands just about everything * from the normal C string format, at least as far as I can tell from * the Solaris 2.5 printf(3S) man page. * * Brandon Long 10/22/97 for mutt 0.87.1 * Ok, added some minimal floating point support, which means this * probably requires libm on most operating systems. Don't yet * support the exponent (e,E) and sigfig (g,G). Also, fmtint() * was pretty badly broken, it just wasn't being exercised in ways * which showed it, so that's been fixed. Also, formated the code * to mutt conventions, and removed dead code left over from the * original. Also, there is now a builtin-test, just compile with: * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm * and run snprintf for results. * * Thomas Roessler 01/27/98 for mutt 0.89i * The PGP code was using unsigned hexadecimal formats. * Unfortunately, unsigned formats simply didn't work. * * Michael Elkins 03/05/98 for mutt 0.90.8 * The original code assumed that both snprintf() and vsnprintf() were * missing. Some systems only have snprintf() but not vsnprintf(), so * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. * * Chris Frey 2012/09/05 * Removed varargs.h and all dependency on it. * **************************************************************/ #include #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) #include # include #include #include #define VA_LOCAL_DECL va_list ap #define VA_START(f) va_start(ap, f) #define VA_SHIFT(v,t) ; /* no-op for ANSI */ #define VA_END va_end(ap) /*int snprintf (char *str, size_t count, const char *fmt, ...);*/ /*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args); static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max); static void fmtint (char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags); static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, long double fvalue, int min, int max, int flags); static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); /* * dopr(): poor man's version of doprintf */ /* format read states */ #define DP_S_DEFAULT 0 #define DP_S_FLAGS 1 #define DP_S_MIN 2 #define DP_S_DOT 3 #define DP_S_MAX 4 #define DP_S_MOD 5 #define DP_S_CONV 6 #define DP_S_DONE 7 /* format flags - Bits */ #define DP_F_MINUS (1 << 0) #define DP_F_PLUS (1 << 1) #define DP_F_SPACE (1 << 2) #define DP_F_NUM (1 << 3) #define DP_F_ZERO (1 << 4) #define DP_F_UP (1 << 5) #define DP_F_UNSIGNED (1 << 6) /* Conversion Flags */ #define DP_C_SHORT 1 #define DP_C_LONG 2 #define DP_C_LDOUBLE 3 #define char_to_int(p) (p - '0') #define MAX(p,q) ((p >= q) ? p : q) static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) { char ch; long value; long double fvalue; char *strvalue; int min; int max; int state; int flags; int cflags; size_t currlen; state = DP_S_DEFAULT; currlen = flags = cflags = min = 0; max = -1; ch = *format++; while (state != DP_S_DONE) { if ((ch == '\0') || (currlen >= maxlen)) state = DP_S_DONE; switch(state) { case DP_S_DEFAULT: if (ch == '%') state = DP_S_FLAGS; else dopr_outch (buffer, &currlen, maxlen, ch); ch = *format++; break; case DP_S_FLAGS: switch (ch) { case '-': flags |= DP_F_MINUS; ch = *format++; break; case '+': flags |= DP_F_PLUS; ch = *format++; break; case ' ': flags |= DP_F_SPACE; ch = *format++; break; case '#': flags |= DP_F_NUM; ch = *format++; break; case '0': flags |= DP_F_ZERO; ch = *format++; break; default: state = DP_S_MIN; break; } break; case DP_S_MIN: if (isdigit((unsigned char)ch)) { min = 10*min + char_to_int (ch); ch = *format++; } else if (ch == '*') { min = va_arg (args, int); ch = *format++; state = DP_S_DOT; } else state = DP_S_DOT; break; case DP_S_DOT: if (ch == '.') { state = DP_S_MAX; ch = *format++; } else state = DP_S_MOD; break; case DP_S_MAX: if (isdigit((unsigned char)ch)) { if (max < 0) max = 0; max = 10*max + char_to_int (ch); ch = *format++; } else if (ch == '*') { max = va_arg (args, int); ch = *format++; state = DP_S_MOD; } else state = DP_S_MOD; break; case DP_S_MOD: /* Currently, we don't support Long Long, bummer */ switch (ch) { case 'h': cflags = DP_C_SHORT; ch = *format++; break; case 'l': cflags = DP_C_LONG; ch = *format++; break; case 'L': cflags = DP_C_LDOUBLE; ch = *format++; break; default: break; } state = DP_S_CONV; break; case DP_S_CONV: switch (ch) { case 'd': case 'i': if (cflags == DP_C_SHORT) value = va_arg (args, int); else if (cflags == DP_C_LONG) value = va_arg (args, long int); else value = va_arg (args, int); fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'o': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = va_arg (args, unsigned long int); else value = va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); break; case 'u': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = va_arg (args, unsigned long int); else value = va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'X': flags |= DP_F_UP; case 'x': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = va_arg (args, unsigned long int); else value = va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); break; case 'f': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, long double); else fvalue = va_arg (args, double); /* um, floating point? */ fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); break; case 'E': flags |= DP_F_UP; case 'e': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, long double); else fvalue = va_arg (args, double); break; case 'G': flags |= DP_F_UP; case 'g': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, long double); else fvalue = va_arg (args, double); break; case 'c': dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); break; case 's': strvalue = va_arg (args, char *); if (max < 0) max = maxlen; /* ie, no max */ fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); break; case 'p': strvalue = va_arg (args, void *); fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); break; case 'n': if (cflags == DP_C_SHORT) { short int *num; num = va_arg (args, short int *); *num = currlen; } else if (cflags == DP_C_LONG) { long int *num; num = va_arg (args, long int *); *num = currlen; } else { int *num; num = va_arg (args, int *); *num = currlen; } break; case '%': dopr_outch (buffer, &currlen, maxlen, ch); break; case 'w': /* not supported yet, treat as next char */ ch = *format++; break; default: /* Unknown, skip */ break; } ch = *format++; state = DP_S_DEFAULT; flags = cflags = min = 0; max = -1; break; case DP_S_DONE: break; default: /* hmm? */ break; /* some picky compilers need this */ } } if (currlen < maxlen - 1) buffer[currlen] = '\0'; else buffer[maxlen - 1] = '\0'; } static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max) { int padlen, strln; /* amount to pad */ int cnt = 0; if (value == 0) { value = ""; } for (strln = 0; value[strln]; ++strln); /* strlen */ padlen = min - strln; if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justify */ while ((padlen > 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; ++cnt; } while (*value && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, *value++); ++cnt; } while ((padlen < 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; ++cnt; } } /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ static void fmtint (char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags) { int signvalue = 0; unsigned long uvalue; char convert[20]; int place = 0; int spadlen = 0; /* amount to space pad */ int zpadlen = 0; /* amount to zero pad */ int caps = 0; if (max < 0) max = 0; uvalue = value; if(!(flags & DP_F_UNSIGNED)) { if( value < 0 ) { signvalue = '-'; uvalue = -value; } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ signvalue = '+'; else if (flags & DP_F_SPACE) signvalue = ' '; } if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ do { convert[place++] = (caps? "0123456789ABCDEF":"0123456789abcdef") [uvalue % (unsigned)base ]; uvalue = (uvalue / (unsigned)base ); } while(uvalue && (place < 20)); if (place == 20) place--; convert[place] = 0; zpadlen = max - place; spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); if (zpadlen < 0) zpadlen = 0; if (spadlen < 0) spadlen = 0; if (flags & DP_F_ZERO) { zpadlen = MAX(zpadlen, spadlen); spadlen = 0; } if (flags & DP_F_MINUS) spadlen = -spadlen; /* Left Justifty */ #ifdef DEBUG_SNPRINTF dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", zpadlen, spadlen, min, max, place)); #endif /* Spaces */ while (spadlen > 0) { dopr_outch (buffer, currlen, maxlen, ' '); --spadlen; } /* Sign */ if (signvalue) dopr_outch (buffer, currlen, maxlen, signvalue); /* Zeros */ if (zpadlen > 0) { while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } } /* Digits */ while (place > 0) dopr_outch (buffer, currlen, maxlen, convert[--place]); /* Left Justified spaces */ while (spadlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); ++spadlen; } } static long double abs_val (long double value) { long double result = value; if (value < 0) result = -value; return result; } static long double pow10_ (int exp) { long double result = 1; while (exp) { result *= 10; exp--; } return result; } static long round_ (long double value) { long intpart; intpart = value; value = value - intpart; if (value >= 0.5) intpart++; return intpart; } static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, long double fvalue, int min, int max, int flags) { int signvalue = 0; long double ufvalue; char iconvert[20]; char fconvert[20]; int iplace = 0; int fplace = 0; int padlen = 0; /* amount to pad */ int zpadlen = 0; int caps = 0; long intpart; long fracpart; /* * AIX manpage says the default is 0, but Solaris says the default * is 6, and sprintf on AIX defaults to 6 */ if (max < 0) max = 6; ufvalue = abs_val (fvalue); if (fvalue < 0) signvalue = '-'; else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ signvalue = '+'; else if (flags & DP_F_SPACE) signvalue = ' '; #if 0 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ #endif intpart = ufvalue; /* * Sorry, we only support 9 digits past the decimal because of our * conversion method */ if (max > 9) max = 9; /* We "cheat" by converting the fractional part to integer by * multiplying by a factor of 10 */ fracpart = round_ ((pow10_ (max)) * (ufvalue - intpart)); if (fracpart >= pow10_ (max)) { intpart++; fracpart -= pow10_ (max); } #ifdef DEBUG_SNPRINTF dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); #endif /* Convert integer part */ do { iconvert[iplace++] = (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; intpart = (intpart / 10); } while(intpart && (iplace < 20)); if (iplace == 20) iplace--; iconvert[iplace] = 0; /* Convert fractional part */ do { fconvert[fplace++] = (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; fracpart = (fracpart / 10); } while(fracpart && (fplace < 20)); if (fplace == 20) fplace--; fconvert[fplace] = 0; /* -1 for decimal point, another -1 if we are printing a sign */ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); zpadlen = max - fplace; if (zpadlen < 0) zpadlen = 0; if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justifty */ if ((flags & DP_F_ZERO) && (padlen > 0)) { if (signvalue) { dopr_outch (buffer, currlen, maxlen, signvalue); --padlen; signvalue = 0; } while (padlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --padlen; } } while (padlen > 0) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; } if (signvalue) dopr_outch (buffer, currlen, maxlen, signvalue); while (iplace > 0) dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); /* * Decimal point. This should probably use locale to find the correct * char to print out. */ dopr_outch (buffer, currlen, maxlen, '.'); while (fplace > 0) dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } while (padlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; } } static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) { if (*currlen < maxlen) buffer[(*currlen)++] = c; } #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ #ifndef HAVE_VSNPRINTF int mutt_vsnprintf (char *str, size_t count, const char *fmt, va_list args) { str[0] = 0; dopr(str, count, fmt, args); return(strlen(str)); } #endif /* !HAVE_VSNPRINTF */ #ifndef HAVE_SNPRINTF int mutt_snprintf (char *str,size_t count,const char *fmt,...) { VA_LOCAL_DECL; VA_START (fmt); VA_SHIFT (str, char *); VA_SHIFT (count, size_t ); VA_SHIFT (fmt, char *); (void) mutt_vsnprintf(str, count, fmt, ap); VA_END; return(strlen(str)); } #ifdef TEST_SNPRINTF #ifndef LONG_STRING #define LONG_STRING 1024 #endif int main (void) { char buf1[LONG_STRING]; char buf2[LONG_STRING]; char *fp_fmt[] = { "%-1.5f", "%1.5f", "%123.9f", "%10.5f", "% 10.5f", "%+22.9f", "%+4.9f", "%01.3f", "%4f", "%3.1f", "%3.2f", NULL }; double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, 0.9996, 1.996, 4.136, 0}; char *int_fmt[] = { "%-1.5d", "%1.5d", "%123.9d", "%5.5d", "%10.5d", "% 10.5d", "%+22.33d", "%01.3d", "%4d", NULL }; long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; int x, y; int fail = 0; int num = 0; printf ("Testing snprintf format codes against system sprintf...\n"); for (x = 0; fp_fmt[x] != NULL ; x++) for (y = 0; fp_nums[y] != 0 ; y++) { mutt_snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); sprintf (buf2, fp_fmt[x], fp_nums[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", fp_fmt[x], buf1, buf2); fail++; } num++; } for (x = 0; int_fmt[x] != NULL ; x++) for (y = 0; int_nums[y] != 0 ; y++) { mutt_snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]); sprintf (buf2, int_fmt[x], int_nums[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", int_fmt[x], buf1, buf2); fail++; } num++; } printf ("%d tests failed out of %d.\n", fail, num); } #endif /* SNPRINTF_TEST */ #endif /* !HAVE_SNPRINTF */ libtar/compat/strdup.c000066400000000000000000000045651222530560000153100ustar00rootroot00000000000000/* $OpenBSD: strdup.c,v 1.3 1997/08/20 04:18:52 millert Exp $ */ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93"; #else static char *rcsid = "$OpenBSD: strdup.c,v 1.3 1997/08/20 04:18:52 millert Exp $"; #endif #endif /* LIBC_SCCS and not lint */ #include #include #include #include char * openbsd_strdup(str) const char *str; { size_t siz; char *copy; siz = strlen(str) + 1; if ((copy = malloc(siz)) == NULL) return(NULL); (void)memcpy(copy, str, siz); return(copy); } libtar/compat/strlcat.c000066400000000000000000000050051222530560000154310ustar00rootroot00000000000000/* $OpenBSD: strlcat.c,v 1.5 2001/01/13 16:17:24 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char *rcsid = "$OpenBSD: strlcat.c,v 1.5 2001/01/13 16:17:24 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(initial dst) + strlen(src); if retval >= siz, * truncation occurred. */ size_t strlcat(dst, src, siz) char *dst; const char *src; size_t siz; { register char *d = dst; register const char *s = src; register size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return(dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return(dlen + (s - src)); /* count does not include NUL */ } libtar/compat/strlcpy.c000066400000000000000000000046401222530560000154610ustar00rootroot00000000000000/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(dst, src, siz) char *dst; const char *src; size_t siz; { register char *d = dst; register const char *s = src; register size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } libtar/compat/strmode.c000066400000000000000000000072411222530560000154360ustar00rootroot00000000000000/*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char *rcsid = "$OpenBSD: strmode.c,v 1.3 1997/06/13 13:57:20 deraadt Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include #include void strmode(mode, p) register mode_t mode; register char *p; { /* print type */ switch (mode & S_IFMT) { case S_IFDIR: /* directory */ *p++ = 'd'; break; case S_IFCHR: /* character special */ *p++ = 'c'; break; case S_IFBLK: /* block special */ *p++ = 'b'; break; case S_IFREG: /* regular */ *p++ = '-'; break; case S_IFLNK: /* symbolic link */ *p++ = 'l'; break; case S_IFSOCK: /* socket */ *p++ = 's'; break; #ifdef S_IFIFO case S_IFIFO: /* fifo */ *p++ = 'p'; break; #endif #ifdef S_IFWHT case S_IFWHT: /* whiteout */ *p++ = 'w'; break; #endif default: /* unknown */ *p++ = '?'; break; } /* usr */ if (mode & S_IRUSR) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWUSR) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXUSR | S_ISUID)) { case 0: *p++ = '-'; break; case S_IXUSR: *p++ = 'x'; break; case S_ISUID: *p++ = 'S'; break; case S_IXUSR | S_ISUID: *p++ = 's'; break; } /* group */ if (mode & S_IRGRP) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWGRP) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXGRP | S_ISGID)) { case 0: *p++ = '-'; break; case S_IXGRP: *p++ = 'x'; break; case S_ISGID: *p++ = 'S'; break; case S_IXGRP | S_ISGID: *p++ = 's'; break; } /* other */ if (mode & S_IROTH) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWOTH) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXOTH | S_ISVTX)) { case 0: *p++ = '-'; break; case S_IXOTH: *p++ = 'x'; break; case S_ISVTX: *p++ = 'T'; break; case S_IXOTH | S_ISVTX: *p++ = 't'; break; } *p++ = ' '; /* will be a '+' if ACL's implemented */ *p = '\0'; } libtar/compat/strrstr.c000066400000000000000000000014031222530560000154760ustar00rootroot00000000000000/* ** Copyright 1998-2002 University of Illinois Board of Trustees ** Copyright 1998-2002 Mark D. Roth ** All rights reserved. ** ** strrstr.c - strrstr() function for compatibility library ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include /* ** find the last occurrance of find in string */ char * strrstr(char *string, char *find) { size_t stringlen, findlen; char *cp; findlen = strlen(find); stringlen = strlen(string); if (findlen > stringlen) return NULL; for (cp = string + stringlen - findlen; cp >= string; cp--) if (strncmp(cp, find, findlen) == 0) return cp; return NULL; } libtar/compat/strsep.c000066400000000000000000000060431222530560000153000ustar00rootroot00000000000000/* $OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $ */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93"; #else static char *rcsid = "$OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $"; #endif #endif /* LIBC_SCCS and not lint */ #ifndef HAVE_STRSEP /* * Get next token from string *stringp, where tokens are possibly-empty * strings separated by characters from delim. * * Writes NULs into the string at *stringp to end tokens. * delim need not remain constant from call to call. * On return, *stringp points past the last NUL written (if there might * be further tokens), or is NULL (if there are definitely no more tokens). * * If *stringp is NULL, strsep returns NULL. */ char * strsep(stringp, delim) register char **stringp; register const char *delim; { register char *s; register const char *spanp; register int c, sc; char *tok; if ((s = *stringp) == NULL) return (NULL); for (tok = s;;) { c = *s++; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; *stringp = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ } #endif /* ! HAVE_STRSEP */ libtar/configure.ac000066400000000000000000000057011222530560000146170ustar00rootroot00000000000000dnl ### Normal initialization. ###################################### AC_INIT([libtar], [1.2.20]) AC_PREREQ([2.61]) AC_CONFIG_AUX_DIR([autoconf]) AC_CONFIG_HEADERS([config.h]) AC_COPYRIGHT([[ Copyright (c) 1998-2003 University of Illinois Board of Trustees Copyright (c) 1998-2003 Mark D. Roth All rights reserved. ]]) AC_CONFIG_SRCDIR([lib/libtar.h]) AC_CONFIG_MACRO_DIR([autoconf]) AM_INIT_AUTOMAKE([dist-bzip2]) ENCAP_PKG([], [postinstall-encap]) dnl ### Load subdirectory modules. ################################## PSG_MODULE([compat]) PSG_MODULE([listhash], [libtar]) dnl ### Set some option defaults. ################################### if test -z "$CFLAGS"; then CFLAGS="-O" fi MKDIR="mkdir -p -m 755" AC_SUBST([MKDIR]) dnl ### Check for compiler et al. ################################### AC_USE_SYSTEM_EXTENSIONS AC_PROG_CC AC_PROG_LIBTOOL AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET dnl ### Compiler characteristics. ################################## AC_C_CONST AX_TLS if test "$ac_cv_tls" = "none" ; then AC_MSG_NOTICE([ **************************************************************** WARNING: Your compiler does not support TLS __thread keywords, so your version of libtar will not be thread-safe. **************************************************************** ]) fi dnl ### Checks for header files. ################################### AC_HEADER_STDC AC_CHECK_HEADERS([unistd.h]) AC_HEADER_MAJOR PSG_REPLACE_TYPE([major_t], [unsigned int], [ #include #ifdef MAJOR_IN_MKDEV # include #else # ifdef MAJOR_IN_SYSMACROS # include # endif #endif ]) PSG_REPLACE_TYPE([minor_t], [unsigned int], [ #include #ifdef MAJOR_IN_MKDEV # include #else # ifdef MAJOR_IN_SYSMACROS # include # endif #endif ]) PSG_REPLACE_TYPE([dev_t], [unsigned long], [ #include #ifdef MAJOR_IN_MKDEV # include #else # ifdef MAJOR_IN_SYSMACROS # include # endif #endif ]) PSG_REPLACE_TYPE([socklen_t], [unsigned long], [ #include #include ]) PSG_REPLACE_TYPE([uint64_t], [long long]) AC_TYPE_MODE_T AC_TYPE_OFF_T AC_TYPE_SIZE_T AC_TYPE_UID_T PSG_REPLACE_TYPE([nlink_t], [unsigned short]) dnl ### Check for needed functions. ################################ COMPAT_FUNC_BASENAME COMPAT_FUNC_DIRNAME COMPAT_FUNC_FNMATCH AC_CHECK_FUNCS([lchown]) COMPAT_FUNC_MAKEDEV COMPAT_FUNC_SNPRINTF COMPAT_FUNC_STRDUP AC_FUNC_STRFTIME COMPAT_FUNC_STRLCPY COMPAT_FUNC_STRMODE COMPAT_FUNC_STRSEP dnl ### Check for libraries. ####################################### AC_ARG_WITH([zlib], [ --without-zlib Use external gzip binary instead of zlib], [], [with_zlib=yes]) if test "$with_zlib" = "yes"; then AC_CHECK_LIB([z], [gzread]) fi dnl ### Create output files. ####################################### AC_CONFIG_FILES([Makefile lib/Makefile libtar/Makefile doc/Makefile]) AC_OUTPUT libtar/doc/000077500000000000000000000000001222530560000130735ustar00rootroot00000000000000libtar/doc/Makefile.in000066400000000000000000000107331222530560000151440ustar00rootroot00000000000000# @configure_input@ ### Path settings srcdir = @srcdir@ top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ mandir = @mandir@ libdir = @libdir@ includedir = @includedir@ datarootdir = @datarootdir@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ @ENCAP_DEFS@ ### Installation programs and flags INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s INSTALL_DATA = @INSTALL_DATA@ LN_S = @LN_S@ MKDIR = @MKDIR@ @SET_MAKE@ ### Makefile rules - no user-servicable parts below TAR_OPEN_SO = tar_fdopen \ tar_fd \ tar_close TAR_APPEND_FILE_SO = tar_append_eof \ tar_append_regfile TAR_BLOCK_READ_SO = tar_block_write TH_READ_SO = th_write TH_SET_FROM_STAT_SO = th_finish \ th_set_device \ th_set_group \ th_set_link \ th_set_mode \ th_set_path \ th_set_type \ th_set_user TAR_EXTRACT_FILE_SO = tar_extract_blockdev \ tar_extract_chardev \ tar_extract_dir \ tar_extract_fifo \ tar_extract_hardlink \ tar_extract_regfile \ tar_extract_symlink \ tar_skip_regfile \ tar_set_file_perms TH_GET_PATHNAME_SO = TH_ISBLK \ TH_ISCHR \ TH_ISDIR \ TH_ISFIFO \ TH_ISLNK \ TH_ISLONGLINK \ TH_ISLONGNAME \ TH_ISREG \ TH_ISSYM \ th_get_crc \ th_get_devmajor \ th_get_devminor \ th_get_gid \ th_get_linkname \ th_get_mode \ th_get_mtime \ th_get_size \ th_get_uid TH_PRINT_LONG_LS_SO = th_print TAR_EXTRACT_ALL_SO = tar_extract_glob \ tar_append_tree @LISTHASH_PREFIX@_HASH_NEW_SO = \ @LISTHASH_PREFIX@_hash_free \ @LISTHASH_PREFIX@_hash_next \ @LISTHASH_PREFIX@_hash_prev \ @LISTHASH_PREFIX@_hash_search \ @LISTHASH_PREFIX@_hash_add \ @LISTHASH_PREFIX@_hash_getkey \ @LISTHASH_PREFIX@_hash_del @LISTHASH_PREFIX@_LIST_NEW_SO = \ @LISTHASH_PREFIX@_list_free \ @LISTHASH_PREFIX@_list_next \ @LISTHASH_PREFIX@_list_prev \ @LISTHASH_PREFIX@_list_search \ @LISTHASH_PREFIX@_list_add \ @LISTHASH_PREFIX@_list_add_str \ @LISTHASH_PREFIX@_list_del \ @LISTHASH_PREFIX@_list_dup \ @LISTHASH_PREFIX@_list_merge DISTCLEANFILES = ../listhash/@LISTHASH_PREFIX@_hash_new.3 \ ../listhash/@LISTHASH_PREFIX@_list_new.3 all: .PHONY: clean distclean install clean: distclean: clean rm -f Makefile ${DISTCLEANFILES} install: all ${MKDIR} ${DESTDIR}${mandir}/man3 ${INSTALL_DATA} ${srcdir}/tar_open.3 ${DESTDIR}${mandir}/man3 for i in ${TAR_OPEN_SO}; do \ echo ".so man3/tar_open.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done ${INSTALL_DATA} ${srcdir}/tar_append_file.3 ${DESTDIR}${mandir}/man3 for i in ${TAR_APPEND_FILE_SO}; do \ echo ".so man3/tar_append_file.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done ${INSTALL_DATA} ${srcdir}/tar_block_read.3 ${DESTDIR}${mandir}/man3 for i in ${TAR_BLOCK_READ_SO}; do \ echo ".so man3/tar_block_read.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done ${INSTALL_DATA} ${srcdir}/th_read.3 ${DESTDIR}${mandir}/man3 for i in ${TH_READ_SO}; do \ echo ".so man3/th_read.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done ${INSTALL_DATA} ${srcdir}/th_set_from_stat.3 ${DESTDIR}${mandir}/man3 for i in ${TH_SET_FROM_STAT_SO}; do \ echo ".so man3/th_set_from_stat.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done ${INSTALL_DATA} ${srcdir}/tar_extract_file.3 ${DESTDIR}${mandir}/man3 for i in ${TAR_EXTRACT_FILE_SO}; do \ echo ".so man3/tar_extract_file.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done ${INSTALL_DATA} ${srcdir}/th_get_pathname.3 ${DESTDIR}${mandir}/man3 for i in ${TH_GET_PATHNAME_SO}; do \ echo ".so man3/th_get_pathname.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done ${INSTALL_DATA} ${srcdir}/th_print_long_ls.3 ${DESTDIR}${mandir}/man3 for i in ${TH_PRINT_LONG_LS_SO}; do \ echo ".so man3/th_print_long_ls.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done ${INSTALL_DATA} ${srcdir}/tar_extract_all.3 ${DESTDIR}${mandir}/man3 for i in ${TAR_EXTRACT_ALL_SO}; do \ echo ".so man3/tar_extract_all.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done ${INSTALL_DATA} ../listhash/@LISTHASH_PREFIX@_hash_new.3 ${DESTDIR}${mandir}/man3 for i in ${@LISTHASH_PREFIX@_HASH_NEW_SO}; do \ echo ".so man3/@LISTHASH_PREFIX@_hash_new.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done ${INSTALL_DATA} ../listhash/@LISTHASH_PREFIX@_list_new.3 ${DESTDIR}${mandir}/man3 for i in ${@LISTHASH_PREFIX@_LIST_NEW_SO}; do \ echo ".so man3/@LISTHASH_PREFIX@_list_new.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \ done libtar/doc/tar_append_file.3000066400000000000000000000041071222530560000162750ustar00rootroot00000000000000.TH tar_append_file 3 "Jan 2001" "University of Illinois" "C Library Calls" .SH NAME tar_append_file, tar_append_eof, tar_append_regfile \- append data to tar archives .SH SYNOPSIS .B #include .P .BI "int tar_append_file(TAR *" t ", char *" realname "," .BI "char *" savename ");" .BI "int tar_append_regfile(TAR *" t ", char *" realname ");" .BI "int tar_append_eof(TAR *" t ");" .SH VERSION This man page documents version 1.2 of \fBlibtar\fP. .SH DESCRIPTION The \fBtar_append_file\fP() function creates a tar file header block describing the file named by the \fIrealname\fP argument, but with the encoded filename of \fIsavename\fP. It then sets the current header associated with the \fITAR\fP handle \fIt\fP to the newly created header block, and writes this block to the tar archive associated with \fIt\fP. If the file named by \fIrealname\fP is a regular file (and is not encoded as a hard link), \fBtar_append_file\fP() will call \fBtar_append_regfile\fP() to append the contents of the file. The \fBtar_append_regfile\fP() function appends the contents of a regular file to the tar archive associated with \fIt\fP. Since this function is called by \fBtar_append_file\fP(), it should only be necessary for applications that construct and write the tar file header on their own. The \fBtar_append_eof\fP() function writes an EOF marker (two blocks of all zeros) to the tar file associated with \fIt\fP. .SH RETURN VALUES On successful completion, these functions will return 0. On failure, they will return \-1 and set \fIerrno\fP to an appropriate value. .SH ERRORS The \fBtar_append_*\fP() functions will fail if: .IP \fBEINVAL\fP Less than \fBT_BLOCKSIZE\fP bytes were written to the tar archive. .IP \fBEINVAL\fP Less than \fBT_BLOCKSIZE\fP bytes were read from the \fIrealname\fP file. .PP They may also fail if any of the following functions fail: \fBlstat\fP(), \fBmalloc\fP(), \fBopen\fP(), \fBread\fP(), \fBth_write\fP(), or the write function for the file type associated with the \fITAR\fP handle \fIt\fP. .SH SEE ALSO .BR read (2), .BR open (2), .BR lstat (2), .BR th_write (3) libtar/doc/tar_block_read.3000066400000000000000000000014711222530560000161150ustar00rootroot00000000000000.TH tar_block_read 3 "Jan 2001" "University of Illinois" "C Library Calls" .SH NAME tar_block_read, tar_block_write \- macros to call read and write functions for the correct tar archive type .SH SYNOPSIS .B #include .P .BI "int tar_block_read(TAR *" t ", char *" buf ");" .BI "int tar_block_write(TAR *" t ", char *" buf ");" .SH VERSION This man page documents version 1.2 of \fBlibtar\fP. .SH DESCRIPTION The \fBtar_block_read\fP() and \fBtar_block_write\fP() macros call the read and write functions for the tar archive type associated with the \fITAR\fP handle \fIt\fP. This type is set when the \fITAR\fP handle is created using \fBtar_open\fP(). .SH RETURN VALUE These macros return the same values as the corresponding read and write functions. .SH SEE ALSO .BR read (2), .BR write (2), .BR tar_open (3) libtar/doc/tar_extract_all.3000066400000000000000000000032701222530560000163310ustar00rootroot00000000000000.TH tar_extract_all 3 "Jan 2001" "University of Illinois" "C Library Calls" .SH NAME tar_extract_all, tar_extract_glob, tar_append_tree \- high-level tar archive manipulation functions .SH SYNOPSIS .B #include .P .BI "int tar_extract_all(TAR *" t ", char *" prefix ");" .BI "int tar_extract_glob(TAR *" t ", char *" globname "," .BI "char *" prefix ");" .BI "int tar_append_tree(TAR *" t ", char *" realdir "," .BI "char *" savedir ");" .SH VERSION This man page documents version 1.2 of \fBlibtar\fP. .SH DESCRIPTION The \fBtar_extract_all\fP() function extracts all files from the tar archive associated with the \fITAR\fP handle \fIt\fP into the path named by the \fIprefix\fP argument. The \fBtar_extract_glob\fP() function extracts all files matching the given \fIglob\fP pattern from the tar archive associated with the \fITAR\fP handle \fIt\fP into the path named by the \fIprefix\fP argument. The \fBtar_append_tree\fP() function appends all files from the directory tree named by \fIrealdir\fP to the tar archive associated with the \fITAR\fP handle \fIt\fP. The pathnames stored in the tar archive are modified by replacing \fIrealdir\fP with \fIsavedir\fP, so that the files will be extracted into \fIsavedir\fP. .SH RETURN VALUES On successful completion, these functions will return 0. On failure, they will return \-1 and set \fIerrno\fP to an appropriate value. .SH ERRORS These functions will fail under the same conditions that the \fBtar_skip_regfile\fP(), \fBtar_extract_regfile\fP(), \fBopendir\fP(), \fBlstat\fP(), or \fBtar_append_file\fP() functions fail. .SH SEE ALSO .BR opendir (2), .BR lstat (2), .BR tar_skip_regfile (3), .BR tar_extract_regfile (3), .BR tar_append_file (3) libtar/doc/tar_extract_file.3000066400000000000000000000061521222530560000165020ustar00rootroot00000000000000.TH tar_extract_file 3 "Jan 2001" "University of Illinois" "C Library Calls" .SH NAME tar_extract_file, tar_extract_regfile, tar_extract_hardlink, tar_extract_symlink, tar_extract_chardev, tar_extract_blockdev, tar_extract_dir, tar_extract_fifo, tar_skip_regfile, tar_set_file_perms \- extract files from a tar archive .SH SYNOPSIS .B #include .P .BI "int tar_extract_file(TAR *" t ", char *" realname ");" .BI "int tar_extract_regfile(TAR *" t ", char *" realname ");" .BI "int tar_skip_regfile(TAR *" t ");" .BI "int tar_extract_dir(TAR *" t ", char *" realname ");" .BI "int tar_extract_hardlink(TAR *" t ", char *" realname ");" .BI "int tar_extract_symlink(TAR *" t ", char *" realname ");" .BI "int tar_extract_blockdev(TAR *" t ", char *" realname ");" .BI "int tar_extract_chardev(TAR *" t ", char *" realname ");" .BI "int tar_extract_fifo(TAR *" t ", char *" realname ");" .BI "int tar_set_file_perms(TAR *" t ", char *" realname ");" .SH VERSION This man page documents version 1.2 of \fBlibtar\fP. .SH DESCRIPTION The \fBtar_extract_file\fP() function acts as a front-end to the other \fBtar_extract_*\fP() functions. It checks the current tar header associated with the \fITAR\fP handle \fIt\fP (which must be initialized first by calling \fBth_read\fP()) to determine what kind of file the header refers to. It then calls the appropriate \fBtar_extract_*\fP() function to extract that kind of file. The \fBtar_skip_regfile\fP() function skips over the file content blocks and positions the file pointer at the expected location of the next tar header block. The \fBtar_set_file_perms\fP() function sets the attributes of the extracted file to match the encoded values. This includes the file's modification time, mode, owner, and group. This function is automatically called by \fBtar_extract_file\fP(), but applications which call the other \fBtar_extract_*\fP() functions directly will need to call \fBtar_set_file_perms\fP() manually if this behavior is desired. .SH RETURN VALUES On successful completion, the functions documented here will return 0. On failure, they will return \-1 and set \fIerrno\fP to an appropriate value. The \fBtar_extract_dir\fP() function will return 1 if the directory already exists. .SH ERRORS The \fBtar_extract_file\fP() function will fail if: .IP \fBEEXIST\fP If the \fBO_NOOVERWRITE\fP flag is set and the file already exists. .PP The \fBtar_extract_*\fP() functions will fail if: .IP \fBEINVAL\fP An entry could not be added to the internal file hash. .IP \fBEINVAL\fP Less than \fBT_BLOCKSIZE\fP bytes were read from the tar archive. .IP \fBEINVAL\fP The current file header associated with \fIt\fP refers to a kind of file other than the one which the called function knows about. .PP They may also fail if any of the following functions fail: \fBmkdir\fP(), \fBwrite\fP(), \fBlink\fP(), \fBsymlink\fP(), \fBmknod\fP(), \fBmkfifo\fP(), \fButime\fP(), \fBchown\fP(), \fBlchown\fP(), \fBchmod\fP(), or \fBlstat\fP(). .SH SEE ALSO .BR mkdir (2), .BR write (2), .BR link (2), .BR symlink (2), .BR mknod (2), .BR mkfifo (2), .BR utime (2), .BR chown (2), .BR lchown (2), .BR chmod (2), .BR lstat (2) libtar/doc/tar_open.3000066400000000000000000000077051222530560000147770ustar00rootroot00000000000000.TH tar_open 3 "Jan 2001" "University of Illinois" "C Library Calls" .SH NAME tar_open, tar_close \- access a tar archive via a handle .SH SYNOPSIS .B #include .P .BI "int tar_open(TAR **" t ", char *" pathname "," .BI "tartype_t *" type ", int " oflags "," .BI "int " mode ", int " options ");" .BI "int tar_fdopen(TAR **" t ", int " fd "," .BI "char *" pathname ", tartype_t *" type "," .BI "int " oflags ", int " mode "," .BI "int " options ");" .BI "int tar_fd(TAR *" t");" .BI "int tar_close(TAR *" t");" .SH VERSION This man page documents version 1.2 of \fBlibtar\fP. .SH DESCRIPTION The \fBtar_open\fP() function opens a tar archive file corresponding to the filename named by the \fIpathname\fP argument. The \fIoflags\fP argument must be either \fBO_RDONLY\fP or \fBO_WRONLY\fP. The \fItype\fP argument specifies the access methods for the given file type. The \fItartype_t\fP structure has members named \fIopenfunc\fP, \fIclosefunc\fP, \fIreadfunc\fP() and \fIwritefunc\fP(), which are pointers to the functions for opening, closing, reading, and writing the file, respectively. If \fItype\fP is \fINULL\fP, the file type defaults to a normal file, and the standard \fIopen\fP(), \fIclose\fP(), \fIread\fP(), and \fIwrite\fP() functions are used. The \fIoptions\fP argument is a logical-or'ed combination of zero or more of the following: .IP \fBTAR_GNU\fP Use GNU extensions. .IP \fBTAR_VERBOSE\fP Send status messages to \fIstdout\fP. .IP \fBTAR_NOOVERWRITE\fP Do not overwrite pre-existing files. .IP \fBTAR_IGNORE_EOT\fP Skip all-zero blocks instead of treating them as EOT. .IP \fBTAR_IGNORE_MAGIC\fP Do not validate the magic field in file headers. .IP \fBTAR_CHECK_VERSION\fP Check the version field in file headers. (This field is normally ignored.) .IP \fBTAR_IGNORE_CRC\fP Do not validate the CRC of file headers. .PP The \fBtar_open\fP() function allocates memory for a \fITAR\fP handle, and a pointer to the allocated memory is saved in the location specified by \fIt\fP. The \fITAR\fP handle may be passed to other \fIlibtar\fP calls to modify the opened tar archive. The \fITAR\fP handle maintains all of the information about the open tar archive, including the archive \fItype\fP, \fIoptions\fP, and \fIoflags\fP selected when \fBtar_open\fP() was called. The \fITAR\fP handle generated by \fBtar_open\fP() contains a file header structure. When reading a tar archive, this structure contains the last file header read from the tar archive. When writing a tar archive, this structure is used as a staging area to construct the next file header to be written to the archive. In addition, the \fITAR\fP handle contains a hash table which is used to keep track of the device and inode information for each file which gets written to the tar archive. This is used to detect hard links, so that files do not need to be duplicated in the archive. The \fBtar_fdopen\fP() function is identical to the \fBtar_open\fP() function, except that \fIfd\fP is used as the previously-opened file descriptor for the tar file instead of calling \fItype->openfunc\fP() to open the file. The \fBtar_fd\fP() function returns the file descriptor associated with the \fITAR\fP handle \fIt\fP. The \fBtar_close\fP() function closes the file descriptor associated with the \fITAR\fP handle \fIt\fP and frees all dynamically-allocated memory. .SH RETURN VALUE The \fBtar_open\fP(), \fBtar_fdopen\fP(), and \fBtar_close\fP() functions return 0 on success. On failure, they return \-1 and set \fIerrno\fP. The \fBtar_fd\fP() function returns the file descriptor associated with the \fITAR\fP handle \fIt\fP. .SH ERRORS \fBtar_open\fP() will fail if: .IP \fBEINVAL\fP The \fIoflags\fP argument was something other than \fBO_RDONLY\fP or \fBO_WRONLY\fP. .PP In addition, \fBtar_open\fP() and \fBtar_close\fP() may fail if it cannot allocate memory using \fBcalloc\fP(), or if the open or close functions for the specified tar archive \fItype\fP fail. .SH SEE ALSO .BR open (2), .BR close (2), .BR calloc (3) libtar/doc/th_get_pathname.3000066400000000000000000000035471222530560000163170ustar00rootroot00000000000000.TH th_get_pathname 3 "Jan 2001" "University of Illinois" "C Library Calls" .SH NAME th_get_pathname, th_get_uid, th_get_gid, th_get_mode, th_get_crc, th_get_size, th_get_mtime, th_get_devmajor, th_get_devminor, th_get_linkname \- extract individual fields of a tar header TH_ISREG, TH_ISLNK, TH_ISSYM, TH_ISCHR, TH_ISBLK, TH_ISDIR, TH_ISFIFO \- determine what kind of file a tar header refers to TH_ISLONGNAME, TH_ISLONGLINK \- determine whether the GNU extensions are in use .SH SYNOPSIS .B #include .P .BI "char *th_get_linkname(TAR *" t ");" .BI "char *th_get_pathname(TAR *" t ");" .BI "mode_t th_get_mode(TAR *" t ");" .BI "uid_t th_get_uid(TAR *" t ");" .BI "gid_t th_get_gid(TAR *" t ");" .BI "int th_get_crc(TAR *" t ");" .BI "off_t th_get_size(TAR *" t ");" .BI "time_t th_get_mtime(TAR *" t ");" .BI "major_t th_get_devmajor(TAR *" t ");" .BI "minor_t th_get_devminor(TAR *" t ");" .BI "int TH_ISREG(TAR *" t ");" .BI "int TH_ISLNK(TAR *" t ");" .BI "int TH_ISSYM(TAR *" t ");" .BI "int TH_ISCHR(TAR *" t ");" .BI "int TH_ISBLK(TAR *" t ");" .BI "int TH_ISDIR(TAR *" t ");" .BI "int TH_ISFIFO(TAR *" t ");" .BI "int TH_ISLONGNAME(TAR *" t ");" .BI "int TH_ISLONGLINK(TAR *" t ");" .SH VERSION This man page documents version 1.2 of \fBlibtar\fP. .SH DESCRIPTION The \fBth_get_*\fP() functions extract individual fields from the current tar header associated with the \fITAR\fP handle \fIt\fP. The \fBTH_IS*\fP() macros are used to evaluate what kind of file is pointed to by the current tar header associated with the \fITAR\fP handle \fIt\fP. The \fBTH_ISLONGNAME\fP() and \fBTH_ISLONGLINK\fP() macros evaluate whether or not the GNU extensions are used by the current tar header associated with the \fITAR\fP handle \fIt\fP. This is only relevant if the \fBTAR_GNU\fP option was used when \fItar_open\fP() was called. .SH SEE ALSO .BR tar_open (3) libtar/doc/th_print_long_ls.3000066400000000000000000000014651222530560000165310ustar00rootroot00000000000000.TH th_print_long_ls 3 "Jan 2001" "University of Illinois" "C Library Calls" .SH NAME th_print, th_print_long_ls \- print out information about a tar file header .SH SYNOPSIS .B #include .P .BI "void th_print_long_ls(TAR *" t ");" .BI "void th_print(TAR *" t ");" .SH VERSION This man page documents version 1.2 of \fBlibtar\fP. .SH DESCRIPTION The \fBth_print_long_ls\fP() function prints a line to \fIstdout\fP which describes the file pointed to by the current file header associated with the \fITAR\fP handle \fIt\fP. The output is similar to that of "ls \-l". The \fBth_print\fP() function prints the value of each field of the current file header associated with the \fITAR\fP handle \fIt\fP to \fIstdout\fP. This is mainly used for debugging purposes. .SH SEE ALSO .BR tar_open (3), .BR th_read (3) libtar/doc/th_read.3000066400000000000000000000021331222530560000145640ustar00rootroot00000000000000.TH th_read 3 "Jan 2001" "University of Illinois" "C Library Calls" .SH NAME th_read, th_write \- read and write a file header block from a tar archive .SH SYNOPSIS .B #include .P .BI "int th_read(TAR *" t ");" .BI "int th_write(TAR *" t ");" .SH VERSION This man page documents version 1.2 of \fBlibtar\fP. .SH DESCRIPTION The \fBth_read\fP() function reads the next block from the tar archive associated with the \fITAR\fP handle \fIt\fP. It then sets the current tar header associated with \fIt\fP to the contents of the block read. The \fBth_write\fP() function writes the contents of the current tar header associated with \fIt\fP to the tar archive associated with \fIt\fP. .SH RETURN VALUE On successful completion, \fBth_read\fP() and \fBth_write\fP() will return 0. On failure, they will return \-1 and set \fIerrno\fP to an appropriate value. On \fIEOF\fP, \fBth_read\fP() will return 1. .SH ERRORS \fBth_read\fP() and \fBth_write\fP() will fail if: .IP \fBEINVAL\fP Less than \fBT_BLOCKSIZE\fP blocks were read or written. .PP .SH SEE ALSO .BR tar_block_read (3), .BR tar_block_write (3) libtar/doc/th_set_from_stat.3000066400000000000000000000032171222530560000165260ustar00rootroot00000000000000.TH th_set_from_stat 3 "Jan 2001" "University of Illinois" "C Library Calls" .SH NAME th_set_from_stat, th_finish, th_set_type, th_set_path, th_set_link, th_set_device, th_set_user, th_set_group, th_set_mode, th_set_mtime, th_set_size \- set fields of a tar file header .SH SYNOPSIS .B #include .P .BI "void th_set_from_stat(TAR *" t ", struct stat *" s ");" .BI "void th_set_type(TAR *" t ", mode_t " mode ");" .BI "void th_set_path(TAR *" t ", char *" pathname ");" .BI "void th_set_link(TAR *" t ", char *" linkname ");" .BI "void th_set_device(TAR *" t ", dev_t " device ");" .BI "void th_set_user(TAR *" t ", uid_t " uid ");" .BI "void th_set_group(TAR *" t ", gid_t " gid ");" .BI "void th_set_mode(TAR *" t ", mode_t " mode ");" .BI "void th_set_mtime(TAR *" t ", time_t " fmtime ");" .BI "void th_set_size(TAR *" t ", off_t " fsize ");" .BI "void th_finish(TAR *" t ");" .SH VERSION This man page documents version 1.2 of \fBlibtar\fP. .SH DESCRIPTION The \fBth_set_*\fP() functions each set an individual field of the current tar header associated with the \fITAR\fP handle \fIt\fP. The \fBth_set_user\fP() and \fBth_set_group\fP() functions set both the numeric user/group ID fields and the user/group name text fields. The other functions set only the field that they refer to. The \fBth_set_from_stat\fP() function uses the other \fBth_set_*\fP() functions to set all of the fields at once, based on the data passed to it in the argument \fIs\fP. The \fBth_finish\fP() function sets the appropriate constants for the magic and version fields. It then calculates the header checksum and fills in the checksum field. .SH SEE ALSO .BR lstat (2) libtar/lib/000077500000000000000000000000001222530560000130745ustar00rootroot00000000000000libtar/lib/Makefile.in000066400000000000000000000046021222530560000151430ustar00rootroot00000000000000# @configure_input@ ### Path settings srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ includedir = @includedir@ datarootdir = @datarootdir@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ @ENCAP_DEFS@ SHELL = @SHELL@ ### Installation programs and flags INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s INSTALL_DATA = @INSTALL_DATA@ LN_S = @LN_S@ MKDIR = @MKDIR@ ### Compiler and link options CC = @CC@ LIBTOOL = @LIBTOOL@ CPPFLAGS = -I. \ -I.. \ -I${srcdir} \ -I${top_srcdir}/compat \ -I../listhash \ @CPPFLAGS@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ RANLIB = @RANLIB@ @SET_MAKE@ VPATH = @srcdir@:@top_srcdir@/compat:../listhash ### Makefile rules - no user-servicable parts below LIBTAR_OBJS = append.lo \ block.lo \ decode.lo \ encode.lo \ extract.lo \ handle.lo \ libtar_hash.lo \ libtar_list.lo \ output.lo \ util.lo \ wrapper.lo LIBTAR_HDRS = ../config.h \ ${top_srcdir}/compat/compat.h \ ${srcdir}/libtar.h \ ${srcdir}/internal.h \ ../listhash/libtar_listhash.h LIBTAR_LIBS = ./libtar.la ALL = libtar.la LDFLAGS = @LDFLAGS@ CFLAGS = @CFLAGS@ DISTCLEANFILES = ../listhash/libtar_listhash.h \ ../listhash/libtar_list.c \ ../listhash/libtar_hash.c all: ${ALL} .PHONY: clean distclean install libtar.la: ${LIBTAR_OBJS} ${LTLIBOBJS} $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o libtar.la $(LIBTAR_OBJS) $(LTLIBOBJS) -rpath $(libdir) # ${AR} rc libtar.a ${LIBTAR_OBJS} ${LIBOBJS} # ${RANLIB} libtar.a ${LIBTAR_OBJS}: ${LIBTAR_HDRS} %.lo: $(srcdir)/%.c $(LIBTOOL) --mode=compile ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $< %.lo: ../listhash/%.c $(LIBTOOL) --mode=compile ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $< %.lo: ${top_srcdir}/compat/%.c $(LIBTOOL) --mode=compile ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $< clean: rm -rf *~ *.o $(LIBTAR_OBJS) ${ALL} core .libs $(LTLIBOBJS) distclean: clean rm -f Makefile ${DISTCLEANFILES} install: ${ALL} ${MKDIR} ${DESTDIR}${libdir} $(LIBTOOL) --mode=install ${INSTALL_DATA} libtar.la ${DESTDIR}${libdir} ${MKDIR} ${DESTDIR}${includedir} ${INSTALL_DATA} ${srcdir}/libtar.h ${DESTDIR}${includedir} ${INSTALL_DATA} ../listhash/libtar_listhash.h ${DESTDIR}${includedir} libtar/lib/append.c000066400000000000000000000116771222530560000145230ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** append.c - libtar code to append files to a tar archive ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include #include #include #ifdef STDC_HEADERS # include # include #endif #ifdef HAVE_UNISTD_H # include #endif struct tar_dev { dev_t td_dev; libtar_hash_t *td_h; }; typedef struct tar_dev tar_dev_t; struct tar_ino { ino_t ti_ino; char ti_name[MAXPATHLEN]; }; typedef struct tar_ino tar_ino_t; /* free memory associated with a tar_dev_t */ void tar_dev_free(tar_dev_t *tdp) { libtar_hash_free(tdp->td_h, free); free(tdp); } /* appends a file to the tar archive */ int tar_append_file(TAR *t, const char *realname, const char *savename) { struct stat s; int i; libtar_hashptr_t hp; tar_dev_t *td = NULL; tar_ino_t *ti = NULL; char path[MAXPATHLEN]; #ifdef DEBUG printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", " "savename=\"%s\")\n", t, t->pathname, realname, (savename ? savename : "[NULL]")); #endif if (lstat(realname, &s) != 0) { #ifdef DEBUG perror("lstat()"); #endif return -1; } /* set header block */ #ifdef DEBUG puts(" tar_append_file(): setting header block..."); #endif memset(&(t->th_buf), 0, sizeof(struct tar_header)); th_set_from_stat(t, &s); /* set the header path */ #ifdef DEBUG puts(" tar_append_file(): setting header path..."); #endif th_set_path(t, (savename ? savename : realname)); /* check if it's a hardlink */ #ifdef DEBUG puts(" tar_append_file(): checking inode cache for hardlink..."); #endif libtar_hashptr_reset(&hp); if (libtar_hash_getkey(t->h, &hp, &(s.st_dev), (libtar_matchfunc_t)dev_match) != 0) td = (tar_dev_t *)libtar_hashptr_data(&hp); else { #ifdef DEBUG printf("+++ adding hash for device (0x%lx, 0x%lx)...\n", major(s.st_dev), minor(s.st_dev)); #endif td = (tar_dev_t *)calloc(1, sizeof(tar_dev_t)); td->td_dev = s.st_dev; td->td_h = libtar_hash_new(256, (libtar_hashfunc_t)ino_hash); if (td->td_h == NULL) return -1; if (libtar_hash_add(t->h, td) == -1) return -1; } libtar_hashptr_reset(&hp); if (libtar_hash_getkey(td->td_h, &hp, &(s.st_ino), (libtar_matchfunc_t)ino_match) != 0) { ti = (tar_ino_t *)libtar_hashptr_data(&hp); #ifdef DEBUG printf(" tar_append_file(): encoding hard link \"%s\" " "to \"%s\"...\n", realname, ti->ti_name); #endif t->th_buf.typeflag = LNKTYPE; th_set_link(t, ti->ti_name); } else { #ifdef DEBUG printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld " "(\"%s\")...\n", major(s.st_dev), minor(s.st_dev), s.st_ino, realname); #endif ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t)); if (ti == NULL) return -1; ti->ti_ino = s.st_ino; snprintf(ti->ti_name, sizeof(ti->ti_name), "%s", savename ? savename : realname); libtar_hash_add(td->td_h, ti); } /* check if it's a symlink */ if (TH_ISSYM(t)) { i = readlink(realname, path, sizeof(path)); if (i == -1) return -1; if (i >= MAXPATHLEN) i = MAXPATHLEN - 1; path[i] = '\0'; #ifdef DEBUG printf(" tar_append_file(): encoding symlink \"%s\" -> " "\"%s\"...\n", realname, path); #endif th_set_link(t, path); } /* print file info */ if (t->options & TAR_VERBOSE) th_print_long_ls(t); #ifdef DEBUG puts(" tar_append_file(): writing header"); #endif /* write header */ if (th_write(t) != 0) { #ifdef DEBUG printf("t->fd = %d\n", t->fd); #endif return -1; } #ifdef DEBUG puts(" tar_append_file(): back from th_write()"); #endif /* if it's a regular file, write the contents as well */ if (TH_ISREG(t) && tar_append_regfile(t, realname) != 0) return -1; return 0; } /* write EOF indicator */ int tar_append_eof(TAR *t) { int i, j; char block[T_BLOCKSIZE]; memset(&block, 0, T_BLOCKSIZE); for (j = 0; j < 2; j++) { i = tar_block_write(t, &block); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } } return 0; } /* add file contents to a tarchive */ int tar_append_regfile(TAR *t, const char *realname) { char block[T_BLOCKSIZE]; int filefd; int i, j; size_t size; filefd = open(realname, O_RDONLY); if (filefd == -1) { #ifdef DEBUG perror("open()"); #endif return -1; } size = th_get_size(t); for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE) { j = read(filefd, &block, T_BLOCKSIZE); if (j != T_BLOCKSIZE) { if (j != -1) errno = EINVAL; return -1; } if (tar_block_write(t, &block) == -1) return -1; } if (i > 0) { j = read(filefd, &block, i); if (j == -1) return -1; memset(&(block[i]), 0, T_BLOCKSIZE - i); if (tar_block_write(t, &block) == -1) return -1; } close(filefd); return 0; } libtar/lib/block.c000066400000000000000000000176351222530560000143460ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** block.c - libtar code to handle tar archive header blocks ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #ifdef STDC_HEADERS # include # include #endif #define BIT_ISSET(bitmask, bit) ((bitmask) & (bit)) /* read a header block */ int th_read_internal(TAR *t) { int i; int num_zero_blocks = 0; #ifdef DEBUG printf("==> th_read_internal(TAR=\"%s\")\n", t->pathname); #endif while ((i = tar_block_read(t, &(t->th_buf))) == T_BLOCKSIZE) { /* two all-zero blocks mark EOF */ if (t->th_buf.name[0] == '\0') { num_zero_blocks++; if (!BIT_ISSET(t->options, TAR_IGNORE_EOT) && num_zero_blocks >= 2) return 0; /* EOF */ else continue; } /* verify magic and version */ if (BIT_ISSET(t->options, TAR_CHECK_MAGIC) && strncmp(t->th_buf.magic, TMAGIC, TMAGLEN - 1) != 0) { #ifdef DEBUG puts("!!! unknown magic value in tar header"); #endif return -2; } if (BIT_ISSET(t->options, TAR_CHECK_VERSION) && strncmp(t->th_buf.version, TVERSION, TVERSLEN) != 0) { #ifdef DEBUG puts("!!! unknown version value in tar header"); #endif return -2; } /* check chksum */ if (!BIT_ISSET(t->options, TAR_IGNORE_CRC) && !th_crc_ok(t)) { #ifdef DEBUG puts("!!! tar header checksum error"); #endif return -2; } break; } #ifdef DEBUG printf("<== th_read_internal(): returning %d\n", i); #endif return i; } /* wrapper function for th_read_internal() to handle GNU extensions */ int th_read(TAR *t) { int i; size_t sz, j, blocks; char *ptr; #ifdef DEBUG printf("==> th_read(t=0x%lx)\n", t); #endif if (t->th_buf.gnu_longname != NULL) free(t->th_buf.gnu_longname); if (t->th_buf.gnu_longlink != NULL) free(t->th_buf.gnu_longlink); memset(&(t->th_buf), 0, sizeof(struct tar_header)); i = th_read_internal(t); if (i == 0) return 1; else if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } /* check for GNU long link extention */ if (TH_ISLONGLINK(t)) { sz = th_get_size(t); blocks = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0); if (blocks > ((size_t)-1 / T_BLOCKSIZE)) { errno = E2BIG; return -1; } #ifdef DEBUG printf(" th_read(): GNU long linkname detected " "(%ld bytes, %d blocks)\n", sz, blocks); #endif t->th_buf.gnu_longlink = (char *)malloc(blocks * T_BLOCKSIZE); if (t->th_buf.gnu_longlink == NULL) return -1; for (j = 0, ptr = t->th_buf.gnu_longlink; j < blocks; j++, ptr += T_BLOCKSIZE) { #ifdef DEBUG printf(" th_read(): reading long linkname " "(%d blocks left, ptr == %ld)\n", blocks-j, ptr); #endif i = tar_block_read(t, ptr); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } #ifdef DEBUG printf(" th_read(): read block == \"%s\"\n", ptr); #endif } #ifdef DEBUG printf(" th_read(): t->th_buf.gnu_longlink == \"%s\"\n", t->th_buf.gnu_longlink); #endif i = th_read_internal(t); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } } /* check for GNU long name extention */ if (TH_ISLONGNAME(t)) { sz = th_get_size(t); blocks = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0); if (blocks > ((size_t)-1 / T_BLOCKSIZE)) { errno = E2BIG; return -1; } #ifdef DEBUG printf(" th_read(): GNU long filename detected " "(%ld bytes, %d blocks)\n", sz, blocks); #endif t->th_buf.gnu_longname = (char *)malloc(blocks * T_BLOCKSIZE); if (t->th_buf.gnu_longname == NULL) return -1; for (j = 0, ptr = t->th_buf.gnu_longname; j < blocks; j++, ptr += T_BLOCKSIZE) { #ifdef DEBUG printf(" th_read(): reading long filename " "(%d blocks left, ptr == %ld)\n", blocks-j, ptr); #endif i = tar_block_read(t, ptr); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } #ifdef DEBUG printf(" th_read(): read block == \"%s\"\n", ptr); #endif } #ifdef DEBUG printf(" th_read(): t->th_buf.gnu_longname == \"%s\"\n", t->th_buf.gnu_longname); #endif i = th_read_internal(t); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } } #if 0 /* ** work-around for old archive files with broken typeflag fields ** NOTE: I fixed this in the TH_IS*() macros instead */ /* ** (directories are signified with a trailing '/') */ if (t->th_buf.typeflag == AREGTYPE && t->th_buf.name[strlen(t->th_buf.name) - 1] == '/') t->th_buf.typeflag = DIRTYPE; /* ** fallback to using mode bits */ if (t->th_buf.typeflag == AREGTYPE) { mode = (mode_t)oct_to_int(t->th_buf.mode); if (S_ISREG(mode)) t->th_buf.typeflag = REGTYPE; else if (S_ISDIR(mode)) t->th_buf.typeflag = DIRTYPE; else if (S_ISFIFO(mode)) t->th_buf.typeflag = FIFOTYPE; else if (S_ISCHR(mode)) t->th_buf.typeflag = CHRTYPE; else if (S_ISBLK(mode)) t->th_buf.typeflag = BLKTYPE; else if (S_ISLNK(mode)) t->th_buf.typeflag = SYMTYPE; } #endif return 0; } /* write a header block */ int th_write(TAR *t) { int i, j; char type2; size_t sz, sz2; char *ptr; char buf[T_BLOCKSIZE]; #ifdef DEBUG printf("==> th_write(TAR=\"%s\")\n", t->pathname); th_print(t); #endif if ((t->options & TAR_GNU) && t->th_buf.gnu_longlink != NULL) { #ifdef DEBUG printf("th_write(): using gnu_longlink (\"%s\")\n", t->th_buf.gnu_longlink); #endif /* save old size and type */ type2 = t->th_buf.typeflag; sz2 = th_get_size(t); /* write out initial header block with fake size and type */ t->th_buf.typeflag = GNU_LONGLINK_TYPE; sz = strlen(t->th_buf.gnu_longlink); th_set_size(t, sz); th_finish(t); i = tar_block_write(t, &(t->th_buf)); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } /* write out extra blocks containing long name */ for (j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0), ptr = t->th_buf.gnu_longlink; j > 1; j--, ptr += T_BLOCKSIZE) { i = tar_block_write(t, ptr); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } } memset(buf, 0, T_BLOCKSIZE); strncpy(buf, ptr, T_BLOCKSIZE); i = tar_block_write(t, &buf); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } /* reset type and size to original values */ t->th_buf.typeflag = type2; th_set_size(t, sz2); } if ((t->options & TAR_GNU) && t->th_buf.gnu_longname != NULL) { #ifdef DEBUG printf("th_write(): using gnu_longname (\"%s\")\n", t->th_buf.gnu_longname); #endif /* save old size and type */ type2 = t->th_buf.typeflag; sz2 = th_get_size(t); /* write out initial header block with fake size and type */ t->th_buf.typeflag = GNU_LONGNAME_TYPE; sz = strlen(t->th_buf.gnu_longname); th_set_size(t, sz); th_finish(t); i = tar_block_write(t, &(t->th_buf)); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } /* write out extra blocks containing long name */ for (j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0), ptr = t->th_buf.gnu_longname; j > 1; j--, ptr += T_BLOCKSIZE) { i = tar_block_write(t, ptr); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } } memset(buf, 0, T_BLOCKSIZE); strncpy(buf, ptr, T_BLOCKSIZE); i = tar_block_write(t, &buf); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } /* reset type and size to original values */ t->th_buf.typeflag = type2; th_set_size(t, sz2); } th_finish(t); #ifdef DEBUG /* print tar header */ th_print(t); #endif i = tar_block_write(t, &(t->th_buf)); if (i != T_BLOCKSIZE) { if (i != -1) errno = EINVAL; return -1; } #ifdef DEBUG puts("th_write(): returning 0"); #endif return 0; } libtar/lib/decode.c000066400000000000000000000036451222530560000144730ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** decode.c - libtar code to decode tar header blocks ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include #include #ifdef STDC_HEADERS # include #endif /* determine full path name */ char * th_get_pathname(TAR *t) { static TLS_THREAD char filename[MAXPATHLEN]; if (t->th_buf.gnu_longname) return t->th_buf.gnu_longname; if (t->th_buf.prefix[0] != '\0') { snprintf(filename, sizeof(filename), "%.155s/%.100s", t->th_buf.prefix, t->th_buf.name); return filename; } snprintf(filename, sizeof(filename), "%.100s", t->th_buf.name); return filename; } uid_t th_get_uid(TAR *t) { int uid; struct passwd *pw; pw = getpwnam(t->th_buf.uname); if (pw != NULL) return pw->pw_uid; /* if the password entry doesn't exist */ sscanf(t->th_buf.uid, "%o", &uid); return uid; } gid_t th_get_gid(TAR *t) { int gid; struct group *gr; gr = getgrnam(t->th_buf.gname); if (gr != NULL) return gr->gr_gid; /* if the group entry doesn't exist */ sscanf(t->th_buf.gid, "%o", &gid); return gid; } mode_t th_get_mode(TAR *t) { mode_t mode; mode = (mode_t)oct_to_int(t->th_buf.mode); if (! (mode & S_IFMT)) { switch (t->th_buf.typeflag) { case SYMTYPE: mode |= S_IFLNK; break; case CHRTYPE: mode |= S_IFCHR; break; case BLKTYPE: mode |= S_IFBLK; break; case DIRTYPE: mode |= S_IFDIR; break; case FIFOTYPE: mode |= S_IFIFO; break; case AREGTYPE: if (t->th_buf.name[strlen(t->th_buf.name) - 1] == '/') { mode |= S_IFDIR; break; } /* FALLTHROUGH */ case LNKTYPE: case REGTYPE: default: mode |= S_IFREG; } } return mode; } libtar/lib/encode.c000066400000000000000000000105111222530560000144730ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** encode.c - libtar code to encode tar header blocks ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include #include #ifdef STDC_HEADERS # include # include #endif /* magic, version, and checksum */ void th_finish(TAR *t) { if (t->options & TAR_GNU) { /* we're aiming for this result, but must do it in * two calls to avoid FORTIFY segfaults on some Linux * systems: * strncpy(t->th_buf.magic, "ustar ", 8); */ strncpy(t->th_buf.magic, "ustar ", 6); strncpy(t->th_buf.version, " ", 2); } else { strncpy(t->th_buf.version, TVERSION, TVERSLEN); strncpy(t->th_buf.magic, TMAGIC, TMAGLEN); } int_to_oct(th_crc_calc(t), t->th_buf.chksum, 8); } /* map a file mode to a typeflag */ void th_set_type(TAR *t, mode_t mode) { if (S_ISLNK(mode)) t->th_buf.typeflag = SYMTYPE; if (S_ISREG(mode)) t->th_buf.typeflag = REGTYPE; if (S_ISDIR(mode)) t->th_buf.typeflag = DIRTYPE; if (S_ISCHR(mode)) t->th_buf.typeflag = CHRTYPE; if (S_ISBLK(mode)) t->th_buf.typeflag = BLKTYPE; if (S_ISFIFO(mode) || S_ISSOCK(mode)) t->th_buf.typeflag = FIFOTYPE; } /* encode file path */ void th_set_path(TAR *t, const char *pathname) { char suffix[2] = ""; char *tmp; #ifdef DEBUG printf("in th_set_path(th, pathname=\"%s\")\n", pathname); #endif if (t->th_buf.gnu_longname != NULL) free(t->th_buf.gnu_longname); t->th_buf.gnu_longname = NULL; if (pathname[strlen(pathname) - 1] != '/' && TH_ISDIR(t)) strcpy(suffix, "/"); if (strlen(pathname) > T_NAMELEN-1 && (t->options & TAR_GNU)) { /* GNU-style long name */ t->th_buf.gnu_longname = strdup(pathname); strncpy(t->th_buf.name, t->th_buf.gnu_longname, T_NAMELEN); } else if (strlen(pathname) > T_NAMELEN) { /* POSIX-style prefix field */ tmp = strchr(&(pathname[strlen(pathname) - T_NAMELEN - 1]), '/'); if (tmp == NULL) { printf("!!! '/' not found in \"%s\"\n", pathname); return; } snprintf(t->th_buf.name, 100, "%s%s", &(tmp[1]), suffix); snprintf(t->th_buf.prefix, ((tmp - pathname + 1) < 155 ? (tmp - pathname + 1) : 155), "%s", pathname); } else /* classic tar format */ snprintf(t->th_buf.name, 100, "%s%s", pathname, suffix); #ifdef DEBUG puts("returning from th_set_path()..."); #endif } /* encode link path */ void th_set_link(TAR *t, const char *linkname) { #ifdef DEBUG printf("==> th_set_link(th, linkname=\"%s\")\n", linkname); #endif if (strlen(linkname) > T_NAMELEN-1 && (t->options & TAR_GNU)) { /* GNU longlink format */ t->th_buf.gnu_longlink = strdup(linkname); strcpy(t->th_buf.linkname, "././@LongLink"); } else { /* classic tar format */ strlcpy(t->th_buf.linkname, linkname, sizeof(t->th_buf.linkname)); if (t->th_buf.gnu_longlink != NULL) free(t->th_buf.gnu_longlink); t->th_buf.gnu_longlink = NULL; } } /* encode device info */ void th_set_device(TAR *t, dev_t device) { #ifdef DEBUG printf("th_set_device(): major = %d, minor = %d\n", major(device), minor(device)); #endif int_to_oct(major(device), t->th_buf.devmajor, 8); int_to_oct(minor(device), t->th_buf.devminor, 8); } /* encode user info */ void th_set_user(TAR *t, uid_t uid) { struct passwd *pw; pw = getpwuid(uid); if (pw != NULL) strlcpy(t->th_buf.uname, pw->pw_name, sizeof(t->th_buf.uname)); int_to_oct(uid, t->th_buf.uid, 8); } /* encode group info */ void th_set_group(TAR *t, gid_t gid) { struct group *gr; gr = getgrgid(gid); if (gr != NULL) strlcpy(t->th_buf.gname, gr->gr_name, sizeof(t->th_buf.gname)); int_to_oct(gid, t->th_buf.gid, 8); } /* encode file mode */ void th_set_mode(TAR *t, mode_t fmode) { if (S_ISSOCK(fmode)) { fmode &= ~S_IFSOCK; fmode |= S_IFIFO; } int_to_oct(fmode, (t)->th_buf.mode, 8); } void th_set_from_stat(TAR *t, struct stat *s) { th_set_type(t, s->st_mode); if (S_ISCHR(s->st_mode) || S_ISBLK(s->st_mode)) th_set_device(t, s->st_rdev); th_set_user(t, s->st_uid); th_set_group(t, s->st_gid); th_set_mode(t, s->st_mode); th_set_mtime(t, s->st_mtime); if (S_ISREG(s->st_mode)) th_set_size(t, s->st_size); else th_set_size(t, 0); } libtar/lib/extract.c000066400000000000000000000212571222530560000147210ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** extract.c - libtar code to extract a file from a tar archive ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include #include #include #include #include #ifdef STDC_HEADERS # include #endif #ifdef HAVE_UNISTD_H # include #endif static int tar_set_file_perms(TAR *t, char *realname) { mode_t mode; uid_t uid; gid_t gid; struct utimbuf ut; char *filename; filename = (realname ? realname : th_get_pathname(t)); mode = th_get_mode(t); uid = th_get_uid(t); gid = th_get_gid(t); ut.modtime = ut.actime = th_get_mtime(t); /* change owner/group */ if (geteuid() == 0) #ifdef HAVE_LCHOWN if (lchown(filename, uid, gid) == -1) { # ifdef DEBUG fprintf(stderr, "lchown(\"%s\", %d, %d): %s\n", filename, uid, gid, strerror(errno)); # endif #else /* ! HAVE_LCHOWN */ if (!TH_ISSYM(t) && chown(filename, uid, gid) == -1) { # ifdef DEBUG fprintf(stderr, "chown(\"%s\", %d, %d): %s\n", filename, uid, gid, strerror(errno)); # endif #endif /* HAVE_LCHOWN */ return -1; } /* change access/modification time */ if (!TH_ISSYM(t) && utime(filename, &ut) == -1) { #ifdef DEBUG perror("utime()"); #endif return -1; } /* change permissions */ if (!TH_ISSYM(t) && chmod(filename, mode) == -1) { #ifdef DEBUG perror("chmod()"); #endif return -1; } return 0; } /* switchboard */ int tar_extract_file(TAR *t, char *realname) { int i; char *lnp; int pathname_len; int realname_len; if (t->options & TAR_NOOVERWRITE) { struct stat s; if (lstat(realname, &s) == 0 || errno != ENOENT) { errno = EEXIST; return -1; } } if (TH_ISDIR(t)) { i = tar_extract_dir(t, realname); if (i == 1) i = 0; } else if (TH_ISLNK(t)) i = tar_extract_hardlink(t, realname); else if (TH_ISSYM(t)) i = tar_extract_symlink(t, realname); else if (TH_ISCHR(t)) i = tar_extract_chardev(t, realname); else if (TH_ISBLK(t)) i = tar_extract_blockdev(t, realname); else if (TH_ISFIFO(t)) i = tar_extract_fifo(t, realname); else /* if (TH_ISREG(t)) */ i = tar_extract_regfile(t, realname); if (i != 0) return i; i = tar_set_file_perms(t, realname); if (i != 0) return i; pathname_len = strlen(th_get_pathname(t)) + 1; realname_len = strlen(realname) + 1; lnp = (char *)calloc(1, pathname_len + realname_len); if (lnp == NULL) return -1; strcpy(&lnp[0], th_get_pathname(t)); strcpy(&lnp[pathname_len], realname); #ifdef DEBUG printf("tar_extract_file(): calling libtar_hash_add(): key=\"%s\", " "value=\"%s\"\n", th_get_pathname(t), realname); #endif if (libtar_hash_add(t->h, lnp) != 0) return -1; return 0; } /* extract regular file */ int tar_extract_regfile(TAR *t, char *realname) { mode_t mode; size_t size; uid_t uid; gid_t gid; int fdout; int i, k; char buf[T_BLOCKSIZE]; char *filename; #ifdef DEBUG printf("==> tar_extract_regfile(t=0x%lx, realname=\"%s\")\n", t, realname); #endif if (!TH_ISREG(t)) { errno = EINVAL; return -1; } filename = (realname ? realname : th_get_pathname(t)); mode = th_get_mode(t); size = th_get_size(t); uid = th_get_uid(t); gid = th_get_gid(t); if (mkdirhier(dirname(filename)) == -1) return -1; #ifdef DEBUG printf(" ==> extracting: %s (mode %04o, uid %d, gid %d, %d bytes)\n", filename, mode, uid, gid, size); #endif fdout = open(filename, O_WRONLY | O_CREAT | O_TRUNC #ifdef O_BINARY | O_BINARY #endif , 0666); if (fdout == -1) { #ifdef DEBUG perror("open()"); #endif return -1; } #if 0 /* change the owner. (will only work if run as root) */ if (fchown(fdout, uid, gid) == -1 && errno != EPERM) { #ifdef DEBUG perror("fchown()"); #endif return -1; } /* make sure the mode isn't inheritted from a file we're overwriting */ if (fchmod(fdout, mode & 07777) == -1) { #ifdef DEBUG perror("fchmod()"); #endif return -1; } #endif /* extract the file */ for (i = size; i > 0; i -= T_BLOCKSIZE) { k = tar_block_read(t, buf); if (k != T_BLOCKSIZE) { if (k != -1) errno = EINVAL; return -1; } /* write block to output file */ if (write(fdout, buf, ((i > T_BLOCKSIZE) ? T_BLOCKSIZE : i)) == -1) return -1; } /* close output file */ if (close(fdout) == -1) return -1; #ifdef DEBUG printf("### done extracting %s\n", filename); #endif return 0; } /* skip regfile */ int tar_skip_regfile(TAR *t) { int i, k; size_t size; char buf[T_BLOCKSIZE]; if (!TH_ISREG(t)) { errno = EINVAL; return -1; } size = th_get_size(t); for (i = size; i > 0; i -= T_BLOCKSIZE) { k = tar_block_read(t, buf); if (k != T_BLOCKSIZE) { if (k != -1) errno = EINVAL; return -1; } } return 0; } /* hardlink */ int tar_extract_hardlink(TAR * t, char *realname) { char *filename; char *linktgt = NULL; char *lnp; libtar_hashptr_t hp; if (!TH_ISLNK(t)) { errno = EINVAL; return -1; } filename = (realname ? realname : th_get_pathname(t)); if (mkdirhier(dirname(filename)) == -1) return -1; libtar_hashptr_reset(&hp); if (libtar_hash_getkey(t->h, &hp, th_get_linkname(t), (libtar_matchfunc_t)libtar_str_match) != 0) { lnp = (char *)libtar_hashptr_data(&hp); linktgt = &lnp[strlen(lnp) + 1]; } else linktgt = th_get_linkname(t); #ifdef DEBUG printf(" ==> extracting: %s (link to %s)\n", filename, linktgt); #endif if (link(linktgt, filename) == -1) { #ifdef DEBUG perror("link()"); #endif return -1; } return 0; } /* symlink */ int tar_extract_symlink(TAR *t, char *realname) { char *filename; if (!TH_ISSYM(t)) { errno = EINVAL; return -1; } filename = (realname ? realname : th_get_pathname(t)); if (mkdirhier(dirname(filename)) == -1) return -1; if (unlink(filename) == -1 && errno != ENOENT) return -1; #ifdef DEBUG printf(" ==> extracting: %s (symlink to %s)\n", filename, th_get_linkname(t)); #endif if (symlink(th_get_linkname(t), filename) == -1) { #ifdef DEBUG perror("symlink()"); #endif return -1; } return 0; } /* character device */ int tar_extract_chardev(TAR *t, char *realname) { mode_t mode; unsigned long devmaj, devmin; char *filename; if (!TH_ISCHR(t)) { errno = EINVAL; return -1; } filename = (realname ? realname : th_get_pathname(t)); mode = th_get_mode(t); devmaj = th_get_devmajor(t); devmin = th_get_devminor(t); if (mkdirhier(dirname(filename)) == -1) return -1; #ifdef DEBUG printf(" ==> extracting: %s (character device %ld,%ld)\n", filename, devmaj, devmin); #endif if (mknod(filename, mode | S_IFCHR, compat_makedev(devmaj, devmin)) == -1) { #ifdef DEBUG perror("mknod()"); #endif return -1; } return 0; } /* block device */ int tar_extract_blockdev(TAR *t, char *realname) { mode_t mode; unsigned long devmaj, devmin; char *filename; if (!TH_ISBLK(t)) { errno = EINVAL; return -1; } filename = (realname ? realname : th_get_pathname(t)); mode = th_get_mode(t); devmaj = th_get_devmajor(t); devmin = th_get_devminor(t); if (mkdirhier(dirname(filename)) == -1) return -1; #ifdef DEBUG printf(" ==> extracting: %s (block device %ld,%ld)\n", filename, devmaj, devmin); #endif if (mknod(filename, mode | S_IFBLK, compat_makedev(devmaj, devmin)) == -1) { #ifdef DEBUG perror("mknod()"); #endif return -1; } return 0; } /* directory */ int tar_extract_dir(TAR *t, char *realname) { mode_t mode; char *filename; if (!TH_ISDIR(t)) { errno = EINVAL; return -1; } filename = (realname ? realname : th_get_pathname(t)); mode = th_get_mode(t); if (mkdirhier(dirname(filename)) == -1) return -1; #ifdef DEBUG printf(" ==> extracting: %s (mode %04o, directory)\n", filename, mode); #endif if (mkdir(filename, mode) == -1) { if (errno == EEXIST) { if (chmod(filename, mode) == -1) { #ifdef DEBUG perror("chmod()"); #endif return -1; } else { #ifdef DEBUG puts(" *** using existing directory"); #endif return 1; } } else { #ifdef DEBUG perror("mkdir()"); #endif return -1; } } return 0; } /* FIFO */ int tar_extract_fifo(TAR *t, char *realname) { mode_t mode; char *filename; if (!TH_ISFIFO(t)) { errno = EINVAL; return -1; } filename = (realname ? realname : th_get_pathname(t)); mode = th_get_mode(t); if (mkdirhier(dirname(filename)) == -1) return -1; #ifdef DEBUG printf(" ==> extracting: %s (fifo)\n", filename); #endif if (mkfifo(filename, mode) == -1) { #ifdef DEBUG perror("mkfifo()"); #endif return -1; } return 0; } libtar/lib/handle.c000066400000000000000000000042751222530560000145030ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** handle.c - libtar code for initializing a TAR handle ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef STDC_HEADERS # include #endif const char libtar_version[] = PACKAGE_VERSION; static tartype_t default_type = { open, close, read, write }; static int tar_init(TAR **t, const char *pathname, tartype_t *type, int oflags, int mode, int options) { if ((oflags & O_ACCMODE) == O_RDWR) { errno = EINVAL; return -1; } *t = (TAR *)calloc(1, sizeof(TAR)); if (*t == NULL) return -1; (*t)->pathname = pathname; (*t)->options = options; (*t)->type = (type ? type : &default_type); (*t)->oflags = oflags; if ((oflags & O_ACCMODE) == O_RDONLY) (*t)->h = libtar_hash_new(256, (libtar_hashfunc_t)path_hashfunc); else (*t)->h = libtar_hash_new(16, (libtar_hashfunc_t)dev_hash); if ((*t)->h == NULL) { free(*t); return -1; } return 0; } /* open a new tarfile handle */ int tar_open(TAR **t, const char *pathname, tartype_t *type, int oflags, int mode, int options) { if (tar_init(t, pathname, type, oflags, mode, options) == -1) return -1; if ((options & TAR_NOOVERWRITE) && (oflags & O_CREAT)) oflags |= O_EXCL; #ifdef O_BINARY oflags |= O_BINARY; #endif (*t)->fd = (*((*t)->type->openfunc))(pathname, oflags, mode); if ((*t)->fd == -1) { free(*t); return -1; } return 0; } int tar_fdopen(TAR **t, int fd, const char *pathname, tartype_t *type, int oflags, int mode, int options) { if (tar_init(t, pathname, type, oflags, mode, options) == -1) return -1; (*t)->fd = fd; return 0; } int tar_fd(TAR *t) { return t->fd; } /* close tarfile handle */ int tar_close(TAR *t) { int i; i = (*(t->type->closefunc))(t->fd); if (t->h != NULL) libtar_hash_free(t->h, ((t->oflags & O_ACCMODE) == O_RDONLY ? free : (libtar_freefunc_t)tar_dev_free)); free(t); return i; } libtar/lib/internal.h000066400000000000000000000007131222530560000150620ustar00rootroot00000000000000/* ** Copyright 2002-2003 University of Illinois Board of Trustees ** Copyright 2002-2003 Mark D. Roth ** All rights reserved. ** ** internal.h - internal header file for libtar ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #ifdef TLS #define TLS_THREAD TLS #else #define TLS_THREAD #endif libtar/lib/libtar.h000066400000000000000000000207531222530560000145310ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** libtar.h - header file for libtar library ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #ifndef LIBTAR_H #define LIBTAR_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* useful constants */ #define T_BLOCKSIZE 512 #define T_NAMELEN 100 #define T_PREFIXLEN 155 #define T_MAXPATHLEN (T_NAMELEN + T_PREFIXLEN) /* GNU extensions for typeflag */ #define GNU_LONGNAME_TYPE 'L' #define GNU_LONGLINK_TYPE 'K' /* our version of the tar header structure */ struct tar_header { char name[100]; char mode[8]; char uid[8]; char gid[8]; char size[12]; char mtime[12]; char chksum[8]; char typeflag; char linkname[100]; char magic[6]; char version[2]; char uname[32]; char gname[32]; char devmajor[8]; char devminor[8]; char prefix[155]; char padding[12]; char *gnu_longname; char *gnu_longlink; }; /***** handle.c ************************************************************/ typedef int (*openfunc_t)(const char *, int, ...); typedef int (*closefunc_t)(int); typedef ssize_t (*readfunc_t)(int, void *, size_t); typedef ssize_t (*writefunc_t)(int, const void *, size_t); typedef struct { openfunc_t openfunc; closefunc_t closefunc; readfunc_t readfunc; writefunc_t writefunc; } tartype_t; typedef struct { tartype_t *type; char *pathname; long fd; int oflags; int options; struct tar_header th_buf; libtar_hash_t *h; } TAR; /* constant values for the TAR options field */ #define TAR_GNU 1 /* use GNU extensions */ #define TAR_VERBOSE 2 /* output file info to stdout */ #define TAR_NOOVERWRITE 4 /* don't overwrite existing files */ #define TAR_IGNORE_EOT 8 /* ignore double zero blocks as EOF */ #define TAR_CHECK_MAGIC 16 /* check magic in file header */ #define TAR_CHECK_VERSION 32 /* check version in file header */ #define TAR_IGNORE_CRC 64 /* ignore CRC in file header */ /* this is obsolete - it's here for backwards-compatibility only */ #define TAR_IGNORE_MAGIC 0 extern const char libtar_version[]; /* open a new tarfile handle */ int tar_open(TAR **t, const char *pathname, tartype_t *type, int oflags, int mode, int options); /* make a tarfile handle out of a previously-opened descriptor */ int tar_fdopen(TAR **t, int fd, const char *pathname, tartype_t *type, int oflags, int mode, int options); /* returns the descriptor associated with t */ int tar_fd(TAR *t); /* close tarfile handle */ int tar_close(TAR *t); /***** append.c ************************************************************/ /* forward declaration to appease the compiler */ struct tar_dev; /* cleanup function */ void tar_dev_free(struct tar_dev *tdp); /* Appends a file to the tar archive. * Arguments: * t = TAR handle to append to * realname = path of file to append * savename = name to save the file under in the archive */ int tar_append_file(TAR *t, const char *realname, const char *savename); /* write EOF indicator */ int tar_append_eof(TAR *t); /* add file contents to a tarchive */ int tar_append_regfile(TAR *t, const char *realname); /***** block.c *************************************************************/ /* macros for reading/writing tarchive blocks */ #define tar_block_read(t, buf) \ (*((t)->type->readfunc))((t)->fd, (char *)(buf), T_BLOCKSIZE) #define tar_block_write(t, buf) \ (*((t)->type->writefunc))((t)->fd, (char *)(buf), T_BLOCKSIZE) /* read/write a header block */ int th_read(TAR *t); int th_write(TAR *t); /***** decode.c ************************************************************/ /* determine file type */ #define TH_ISREG(t) ((t)->th_buf.typeflag == REGTYPE \ || (t)->th_buf.typeflag == AREGTYPE \ || (t)->th_buf.typeflag == CONTTYPE \ || (S_ISREG((mode_t)oct_to_int((t)->th_buf.mode)) \ && (t)->th_buf.typeflag != LNKTYPE)) #define TH_ISLNK(t) ((t)->th_buf.typeflag == LNKTYPE) #define TH_ISSYM(t) ((t)->th_buf.typeflag == SYMTYPE \ || S_ISLNK((mode_t)oct_to_int((t)->th_buf.mode))) #define TH_ISCHR(t) ((t)->th_buf.typeflag == CHRTYPE \ || S_ISCHR((mode_t)oct_to_int((t)->th_buf.mode))) #define TH_ISBLK(t) ((t)->th_buf.typeflag == BLKTYPE \ || S_ISBLK((mode_t)oct_to_int((t)->th_buf.mode))) #define TH_ISDIR(t) ((t)->th_buf.typeflag == DIRTYPE \ || S_ISDIR((mode_t)oct_to_int((t)->th_buf.mode)) \ || ((t)->th_buf.typeflag == AREGTYPE \ && ((t)->th_buf.name[strlen((t)->th_buf.name) - 1] == '/'))) #define TH_ISFIFO(t) ((t)->th_buf.typeflag == FIFOTYPE \ || S_ISFIFO((mode_t)oct_to_int((t)->th_buf.mode))) #define TH_ISLONGNAME(t) ((t)->th_buf.typeflag == GNU_LONGNAME_TYPE) #define TH_ISLONGLINK(t) ((t)->th_buf.typeflag == GNU_LONGLINK_TYPE) /* decode tar header info */ #define th_get_crc(t) oct_to_int((t)->th_buf.chksum) #define th_get_size(t) oct_to_int((t)->th_buf.size) #define th_get_mtime(t) oct_to_int((t)->th_buf.mtime) #define th_get_devmajor(t) oct_to_int((t)->th_buf.devmajor) #define th_get_devminor(t) oct_to_int((t)->th_buf.devminor) #define th_get_linkname(t) ((t)->th_buf.gnu_longlink \ ? (t)->th_buf.gnu_longlink \ : (t)->th_buf.linkname) char *th_get_pathname(TAR *t); mode_t th_get_mode(TAR *t); uid_t th_get_uid(TAR *t); gid_t th_get_gid(TAR *t); /***** encode.c ************************************************************/ /* encode file info in th_header */ void th_set_type(TAR *t, mode_t mode); void th_set_path(TAR *t, const char *pathname); void th_set_link(TAR *t, const char *linkname); void th_set_device(TAR *t, dev_t device); void th_set_user(TAR *t, uid_t uid); void th_set_group(TAR *t, gid_t gid); void th_set_mode(TAR *t, mode_t fmode); #define th_set_mtime(t, fmtime) \ int_to_oct_nonull((fmtime), (t)->th_buf.mtime, 12) #define th_set_size(t, fsize) \ int_to_oct_nonull((fsize), (t)->th_buf.size, 12) /* encode everything at once (except the pathname and linkname) */ void th_set_from_stat(TAR *t, struct stat *s); /* encode magic, version, and crc - must be done after everything else is set */ void th_finish(TAR *t); /***** extract.c ***********************************************************/ /* sequentially extract next file from t */ int tar_extract_file(TAR *t, char *realname); /* extract different file types */ int tar_extract_dir(TAR *t, char *realname); int tar_extract_hardlink(TAR *t, char *realname); int tar_extract_symlink(TAR *t, char *realname); int tar_extract_chardev(TAR *t, char *realname); int tar_extract_blockdev(TAR *t, char *realname); int tar_extract_fifo(TAR *t, char *realname); /* for regfiles, we need to extract the content blocks as well */ int tar_extract_regfile(TAR *t, char *realname); int tar_skip_regfile(TAR *t); /***** output.c ************************************************************/ /* print the tar header */ void th_print(TAR *t); /* print "ls -l"-like output for the file described by th */ void th_print_long_ls(TAR *t); /***** util.c *************************************************************/ /* hashing function for pathnames */ int path_hashfunc(char *key, int numbuckets); /* matching function for dev_t's */ int dev_match(dev_t *dev1, dev_t *dev2); /* matching function for ino_t's */ int ino_match(ino_t *ino1, ino_t *ino2); /* hashing function for dev_t's */ int dev_hash(dev_t *dev); /* hashing function for ino_t's */ int ino_hash(ino_t *inode); /* create any necessary dirs */ int mkdirhier(char *path); /* calculate header checksum */ int th_crc_calc(TAR *t); /* calculate a signed header checksum */ int th_signed_crc_calc(TAR *t); /* compare checksums in a forgiving way */ #define th_crc_ok(t) (th_get_crc(t) == th_crc_calc(t) || th_get_crc(t) == th_signed_crc_calc(t)) /* string-octal to integer conversion */ int oct_to_int(char *oct); /* integer to NULL-terminated string-octal conversion */ #define int_to_oct(num, oct, octlen) \ snprintf((oct), (octlen), "%*lo ", (octlen) - 2, (unsigned long)(num)) /* integer to string-octal conversion, no NULL */ void int_to_oct_nonull(int num, char *oct, size_t octlen); /***** wrapper.c **********************************************************/ /* extract groups of files */ int tar_extract_glob(TAR *t, char *globname, char *prefix); int tar_extract_all(TAR *t, char *prefix); /* add a whole tree of files */ int tar_append_tree(TAR *t, char *realdir, char *savedir); #ifdef __cplusplus } #endif #endif /* ! LIBTAR_H */ libtar/lib/output.c000066400000000000000000000067071222530560000146120ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** output.c - libtar code to print out tar header blocks ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include #include #include #include #ifdef STDC_HEADERS # include #endif #ifndef _POSIX_LOGIN_NAME_MAX # define _POSIX_LOGIN_NAME_MAX 9 #endif void th_print(TAR *t) { puts("\nPrinting tar header:"); printf(" name = \"%.100s\"\n", t->th_buf.name); printf(" mode = \"%.8s\"\n", t->th_buf.mode); printf(" uid = \"%.8s\"\n", t->th_buf.uid); printf(" gid = \"%.8s\"\n", t->th_buf.gid); printf(" size = \"%.12s\"\n", t->th_buf.size); printf(" mtime = \"%.12s\"\n", t->th_buf.mtime); printf(" chksum = \"%.8s\"\n", t->th_buf.chksum); printf(" typeflag = \'%c\'\n", t->th_buf.typeflag); printf(" linkname = \"%.100s\"\n", t->th_buf.linkname); printf(" magic = \"%.6s\"\n", t->th_buf.magic); /*printf(" version = \"%.2s\"\n", t->th_buf.version); */ printf(" version[0] = \'%c\',version[1] = \'%c\'\n", t->th_buf.version[0], t->th_buf.version[1]); printf(" uname = \"%.32s\"\n", t->th_buf.uname); printf(" gname = \"%.32s\"\n", t->th_buf.gname); printf(" devmajor = \"%.8s\"\n", t->th_buf.devmajor); printf(" devminor = \"%.8s\"\n", t->th_buf.devminor); printf(" prefix = \"%.155s\"\n", t->th_buf.prefix); printf(" padding = \"%.12s\"\n", t->th_buf.padding); printf(" gnu_longname = \"%s\"\n", (t->th_buf.gnu_longname ? t->th_buf.gnu_longname : "[NULL]")); printf(" gnu_longlink = \"%s\"\n", (t->th_buf.gnu_longlink ? t->th_buf.gnu_longlink : "[NULL]")); } void th_print_long_ls(TAR *t) { char modestring[12]; struct passwd *pw; struct group *gr; uid_t uid; gid_t gid; char username[_POSIX_LOGIN_NAME_MAX]; char groupname[_POSIX_LOGIN_NAME_MAX]; time_t mtime; struct tm *mtm; #ifdef HAVE_STRFTIME char timebuf[18]; #else const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; #endif uid = th_get_uid(t); pw = getpwuid(uid); if (pw == NULL) snprintf(username, sizeof(username), "%d", uid); else strlcpy(username, pw->pw_name, sizeof(username)); gid = th_get_gid(t); gr = getgrgid(gid); if (gr == NULL) snprintf(groupname, sizeof(groupname), "%d", gid); else strlcpy(groupname, gr->gr_name, sizeof(groupname)); strmode(th_get_mode(t), modestring); printf("%.10s %-8.8s %-8.8s ", modestring, username, groupname); if (TH_ISCHR(t) || TH_ISBLK(t)) printf(" %3d, %3d ", th_get_devmajor(t), th_get_devminor(t)); else printf("%9ld ", (long)th_get_size(t)); mtime = th_get_mtime(t); mtm = localtime(&mtime); #ifdef HAVE_STRFTIME strftime(timebuf, sizeof(timebuf), "%h %e %H:%M %Y", mtm); printf("%s", timebuf); #else printf("%.3s %2d %2d:%02d %4d", months[mtm->tm_mon], mtm->tm_mday, mtm->tm_hour, mtm->tm_min, mtm->tm_year + 1900); #endif printf(" %s", th_get_pathname(t)); if (TH_ISSYM(t) || TH_ISLNK(t)) { if (TH_ISSYM(t)) printf(" -> "); else printf(" link to "); if ((t->options & TAR_GNU) && t->th_buf.gnu_longlink != NULL) printf("%s", t->th_buf.gnu_longlink); else printf("%.100s", t->th_buf.linkname); } putchar('\n'); } libtar/lib/util.c000066400000000000000000000051001222530560000142110ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** util.c - miscellaneous utility code for libtar ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include #ifdef STDC_HEADERS # include #endif /* hashing function for pathnames */ int path_hashfunc(char *key, int numbuckets) { char buf[MAXPATHLEN]; char *p; strcpy(buf, key); p = basename(buf); return (((unsigned int)p[0]) % numbuckets); } /* matching function for dev_t's */ int dev_match(dev_t *dev1, dev_t *dev2) { return !memcmp(dev1, dev2, sizeof(dev_t)); } /* matching function for ino_t's */ int ino_match(ino_t *ino1, ino_t *ino2) { return !memcmp(ino1, ino2, sizeof(ino_t)); } /* hashing function for dev_t's */ int dev_hash(dev_t *dev) { return *dev % 16; } /* hashing function for ino_t's */ int ino_hash(ino_t *inode) { return *inode % 256; } /* ** mkdirhier() - create all directories in a given path ** returns: ** 0 success ** 1 all directories already exist ** -1 (and sets errno) error */ int mkdirhier(char *path) { char src[MAXPATHLEN], dst[MAXPATHLEN] = ""; char *dirp, *nextp = src; int retval = 1; if (strlcpy(src, path, sizeof(src)) > sizeof(src)) { errno = ENAMETOOLONG; return -1; } if (path[0] == '/') strcpy(dst, "/"); while ((dirp = strsep(&nextp, "/")) != NULL) { if (*dirp == '\0') continue; if (dst[0] != '\0') strcat(dst, "/"); strcat(dst, dirp); if (mkdir(dst, 0777) == -1) { if (errno != EEXIST) return -1; } else retval = 0; } return retval; } /* calculate header checksum */ int th_crc_calc(TAR *t) { int i, sum = 0; for (i = 0; i < T_BLOCKSIZE; i++) sum += ((unsigned char *)(&(t->th_buf)))[i]; for (i = 0; i < 8; i++) sum += (' ' - (unsigned char)t->th_buf.chksum[i]); return sum; } /* calculate a signed header checksum */ int th_signed_crc_calc(TAR *t) { int i, sum = 0; for (i = 0; i < T_BLOCKSIZE; i++) sum += ((signed char *)(&(t->th_buf)))[i]; for (i = 0; i < 8; i++) sum += (' ' - (signed char)t->th_buf.chksum[i]); return sum; } /* string-octal to integer conversion */ int oct_to_int(char *oct) { int i; sscanf(oct, "%o", &i); return i; } /* integer to string-octal conversion, no NULL */ void int_to_oct_nonull(int num, char *oct, size_t octlen) { snprintf(oct, octlen, "%*lo", octlen - 1, (unsigned long)num); oct[octlen - 1] = ' '; } libtar/lib/wrapper.c000066400000000000000000000056031222530560000147240ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** wrapper.c - libtar high-level wrapper code ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include #include #ifdef STDC_HEADERS # include #endif int tar_extract_glob(TAR *t, char *globname, char *prefix) { char *filename; char buf[MAXPATHLEN]; int i; while ((i = th_read(t)) == 0) { filename = th_get_pathname(t); if (fnmatch(globname, filename, FNM_PATHNAME | FNM_PERIOD)) { if (TH_ISREG(t) && tar_skip_regfile(t)) return -1; continue; } if (t->options & TAR_VERBOSE) th_print_long_ls(t); if (prefix != NULL) snprintf(buf, sizeof(buf), "%s/%s", prefix, filename); else strlcpy(buf, filename, sizeof(buf)); if (tar_extract_file(t, buf) != 0) return -1; } return (i == 1 ? 0 : -1); } int tar_extract_all(TAR *t, char *prefix) { char *filename; char buf[MAXPATHLEN]; int i; #ifdef DEBUG printf("==> tar_extract_all(TAR *t, \"%s\")\n", (prefix ? prefix : "(null)")); #endif while ((i = th_read(t)) == 0) { #ifdef DEBUG puts(" tar_extract_all(): calling th_get_pathname()"); #endif filename = th_get_pathname(t); if (t->options & TAR_VERBOSE) th_print_long_ls(t); if (prefix != NULL) snprintf(buf, sizeof(buf), "%s/%s", prefix, filename); else strlcpy(buf, filename, sizeof(buf)); #ifdef DEBUG printf(" tar_extract_all(): calling tar_extract_file(t, " "\"%s\")\n", buf); #endif if (tar_extract_file(t, buf) != 0) return -1; } return (i == 1 ? 0 : -1); } int tar_append_tree(TAR *t, char *realdir, char *savedir) { char realpath[MAXPATHLEN]; char savepath[MAXPATHLEN]; struct dirent *dent; DIR *dp; struct stat s; #ifdef DEBUG printf("==> tar_append_tree(0x%lx, \"%s\", \"%s\")\n", t, realdir, (savedir ? savedir : "[NULL]")); #endif if (tar_append_file(t, realdir, savedir) != 0) return -1; #ifdef DEBUG puts(" tar_append_tree(): done with tar_append_file()..."); #endif dp = opendir(realdir); if (dp == NULL) { if (errno == ENOTDIR) return 0; return -1; } while ((dent = readdir(dp)) != NULL) { if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue; snprintf(realpath, MAXPATHLEN, "%s/%s", realdir, dent->d_name); if (savedir) snprintf(savepath, MAXPATHLEN, "%s/%s", savedir, dent->d_name); if (lstat(realpath, &s) != 0) return -1; if (S_ISDIR(s.st_mode)) { if (tar_append_tree(t, realpath, (savedir ? savepath : NULL)) != 0) return -1; continue; } if (tar_append_file(t, realpath, (savedir ? savepath : NULL)) != 0) return -1; } closedir(dp); return 0; } libtar/libtar/000077500000000000000000000000001222530560000136035ustar00rootroot00000000000000libtar/libtar/Makefile.in000066400000000000000000000031331222530560000156500ustar00rootroot00000000000000# @configure_input@ ### Path settings srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ includedir = @includedir@ datarootdir = @datarootdir@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ @ENCAP_DEFS@ SHELL = @SHELL@ ### Installation programs and flags INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s INSTALL_DATA = @INSTALL_DATA@ LN_S = @LN_S@ MKDIR = @MKDIR@ ### Compiler and link options CC = @CC@ LIBTOOL = @LIBTOOL@ CPPFLAGS = -I.. \ -I../lib \ -I../listhash \ -I${top_srcdir}/lib \ -I${top_srcdir}/compat \ @CPPFLAGS@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ -ltar LIBOBJS = @LIBOBJS@ RANLIB = @RANLIB@ @SET_MAKE@ VPATH = @srcdir@ ### Makefile rules - no user-servicable parts below LIBTAR_OBJS = libtar.lo LIBTAR_HDRS = ../config.h \ ${top_srcdir}/compat/compat.h \ ${top_srcdir}/lib/libtar.h \ ../listhash/libtar_listhash.h LIBTAR_LIBS = $(top_builddir)/lib ALL = libtar all: ${ALL} .PHONY: clean distclean install libtar: ${LIBTAR_OBJS} ${LIBTAR_LIBS} ${LIBTAR_HDRS} $(LIBTOOL) --mode=link ${CC} ${CFLAGS} ${LDFLAGS} -o libtar $(LIBTAR_OBJS) -L${LIBTAR_LIBS} ${LIBS} ${LIBTAR_OBJS}: ${LIBTAR_HDRS} %.lo: %.c $(LIBTOOL) --mode=compile ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $< clean: rm -rf *~ *.o ${ALL} $(LIBTAR_OBJS) core .libs distclean: clean rm -f Makefile install: ${ALL} ${MKDIR} ${DESTDIR}${bindir} $(LIBTOOL) --mode=install ${INSTALL_PROGRAM} libtar ${DESTDIR}${bindir} libtar/libtar/libtar.c000066400000000000000000000142011222530560000152220ustar00rootroot00000000000000/* ** Copyright 1998-2003 University of Illinois Board of Trustees ** Copyright 1998-2003 Mark D. Roth ** All rights reserved. ** ** libtar.c - demo driver program for libtar ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include #include #include #include #include #ifdef STDC_HEADERS # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef DEBUG # include #endif #ifdef HAVE_LIBZ # include #endif #include char *progname; int verbose = 0; int use_gnu = 0; #ifdef DEBUG void segv_handler(int sig) { puts("OOPS! Caught SIGSEGV, bailing out..."); fflush(stdout); fflush(stderr); } #endif #ifdef HAVE_LIBZ int use_zlib = 0; int gzopen_frontend(char *pathname, int oflags, int mode) { char *gzoflags; gzFile gzf; int fd; switch (oflags & O_ACCMODE) { case O_WRONLY: gzoflags = "wb"; break; case O_RDONLY: gzoflags = "rb"; break; default: case O_RDWR: errno = EINVAL; return -1; } fd = open(pathname, oflags, mode); if (fd == -1) return -1; if ((oflags & O_CREAT) && fchmod(fd, mode)) return -1; gzf = gzdopen(fd, gzoflags); if (!gzf) { errno = ENOMEM; return -1; } /* This is a bad thing to do on big-endian lp64 systems, where the size and placement of integers is different than pointers. However, to fix the problem 4 wrapper functions would be needed and an extra bit of data associating GZF with the wrapper functions. */ return (int)gzf; } tartype_t gztype = { (openfunc_t) gzopen_frontend, (closefunc_t) gzclose, (readfunc_t) gzread, (writefunc_t) gzwrite }; #endif /* HAVE_LIBZ */ int create(char *tarfile, char *rootdir, libtar_list_t *l) { TAR *t; char *pathname; char buf[MAXPATHLEN]; libtar_listptr_t lp; if (tar_open(&t, tarfile, #ifdef HAVE_LIBZ (use_zlib ? &gztype : NULL), #else NULL, #endif O_WRONLY | O_CREAT, 0644, (verbose ? TAR_VERBOSE : 0) | (use_gnu ? TAR_GNU : 0)) == -1) { fprintf(stderr, "tar_open(): %s\n", strerror(errno)); return -1; } libtar_listptr_reset(&lp); while (libtar_list_next(l, &lp) != 0) { pathname = (char *)libtar_listptr_data(&lp); if (pathname[0] != '/' && rootdir != NULL) snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname); else strlcpy(buf, pathname, sizeof(buf)); if (tar_append_tree(t, buf, pathname) != 0) { fprintf(stderr, "tar_append_tree(\"%s\", \"%s\"): %s\n", buf, pathname, strerror(errno)); tar_close(t); return -1; } } if (tar_append_eof(t) != 0) { fprintf(stderr, "tar_append_eof(): %s\n", strerror(errno)); tar_close(t); return -1; } if (tar_close(t) != 0) { fprintf(stderr, "tar_close(): %s\n", strerror(errno)); return -1; } return 0; } int list(char *tarfile) { TAR *t; int i; if (tar_open(&t, tarfile, #ifdef HAVE_LIBZ (use_zlib ? &gztype : NULL), #else NULL, #endif O_RDONLY, 0, (verbose ? TAR_VERBOSE : 0) | (use_gnu ? TAR_GNU : 0)) == -1) { fprintf(stderr, "tar_open(): %s\n", strerror(errno)); return -1; } while ((i = th_read(t)) == 0) { th_print_long_ls(t); #ifdef DEBUG th_print(t); #endif if (TH_ISREG(t) && tar_skip_regfile(t) != 0) { fprintf(stderr, "tar_skip_regfile(): %s\n", strerror(errno)); return -1; } } #ifdef DEBUG printf("th_read() returned %d\n", i); printf("EOF mark encountered after %ld bytes\n", # ifdef HAVE_LIBZ (use_zlib ? gzseek((gzFile) t->fd, 0, SEEK_CUR) : # endif lseek(t->fd, 0, SEEK_CUR) # ifdef HAVE_LIBZ ) # endif ); #endif if (tar_close(t) != 0) { fprintf(stderr, "tar_close(): %s\n", strerror(errno)); return -1; } return 0; } int extract(char *tarfile, char *rootdir) { TAR *t; #ifdef DEBUG puts("opening tarfile..."); #endif if (tar_open(&t, tarfile, #ifdef HAVE_LIBZ (use_zlib ? &gztype : NULL), #else NULL, #endif O_RDONLY, 0, (verbose ? TAR_VERBOSE : 0) | (use_gnu ? TAR_GNU : 0)) == -1) { fprintf(stderr, "tar_open(): %s\n", strerror(errno)); return -1; } #ifdef DEBUG puts("extracting tarfile..."); #endif if (tar_extract_all(t, rootdir) != 0) { fprintf(stderr, "tar_extract_all(): %s\n", strerror(errno)); return -1; } #ifdef DEBUG puts("closing tarfile..."); #endif if (tar_close(t) != 0) { fprintf(stderr, "tar_close(): %s\n", strerror(errno)); return -1; } return 0; } void usage() { printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n", progname); printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n", progname); exit(-1); } #define MODE_LIST 1 #define MODE_CREATE 2 #define MODE_EXTRACT 3 int main(int argc, char *argv[]) { char *tarfile = NULL; char *rootdir = NULL; int c; int mode = 0; libtar_list_t *l; progname = basename(argv[0]); while ((c = getopt(argc, argv, "cC:gtvVxz")) != -1) switch (c) { case 'V': printf("libtar %s by Mark D. Roth \n", libtar_version); break; case 'C': rootdir = strdup(optarg); break; case 'v': verbose = 1; break; case 'g': use_gnu = 1; break; case 'c': if (mode) usage(); mode = MODE_CREATE; break; case 'x': if (mode) usage(); mode = MODE_EXTRACT; break; case 't': if (mode) usage(); mode = MODE_LIST; break; #ifdef HAVE_LIBZ case 'z': use_zlib = 1; break; #endif /* HAVE_LIBZ */ default: usage(); } if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1))) { #ifdef DEBUG printf("argc - optind == %d\tmode == %d\n", argc - optind, mode); #endif usage(); } #ifdef DEBUG signal(SIGSEGV, segv_handler); #endif switch (mode) { case MODE_EXTRACT: return extract(argv[optind], rootdir); case MODE_CREATE: tarfile = argv[optind]; l = libtar_list_new(LIST_QUEUE, NULL); for (c = optind + 1; c < argc; c++) libtar_list_add(l, argv[c]); return create(tarfile, rootdir, l); case MODE_LIST: return list(argv[optind]); default: break; } /* NOTREACHED */ return -2; } libtar/listhash/000077500000000000000000000000001222530560000141455ustar00rootroot00000000000000libtar/listhash/ChangeLog000066400000000000000000000010331222530560000157140ustar00rootroot000000000000002002-12-09 added list_empty() and hash_empty() functions 2002-09-12 fixed list_iterate function to return -1 if it gets an invalid argument include and from source files, not from header file, since header file is sometimes installed as part of a user-visible API (those APIs should eventually be redesigned without the listhash code being publicly visible, but for now we need to accomodate this) 2002-07-07 modified list iterate function to return int (returns -1 if plugin function returns -1) libtar/listhash/TODO000066400000000000000000000011251222530560000146340ustar00rootroot00000000000000Functionality: -------------- * add list mode to allow nodes to be inserted in any arbitrary location * add "*_hash_iterate()" function * add flags argument to *_list_del() that allows the listptr to be set to the previous or next element * add a generic pointer type to replace *_listptr_t and *_hashptr_t ??? Code Cleanup: ------------- * rename functions: *_list_next => *_listptr_next() *_list_prev => *_listptr_prev() *_hash_next => *_hashptr_next() * start using "*_list_t" and "*_hash_t" instead of "*_list_t *" and "*_hash_t *" ? * add prefixes to structure member field names libtar/listhash/hash.c.in000066400000000000000000000163531222530560000156510ustar00rootroot00000000000000/* @configure_input@ */ /* ** Copyright 1998-2002 University of Illinois Board of Trustees ** Copyright 1998-2002 Mark D. Roth ** All rights reserved. ** ** @LISTHASH_PREFIX@_hash.c - hash table routines ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include <@LISTHASH_PREFIX@_listhash.h> #include #include #ifdef STDC_HEADERS # include #endif /* ** @LISTHASH_PREFIX@_hashptr_reset() - reset a hash pointer */ void @LISTHASH_PREFIX@_hashptr_reset(@LISTHASH_PREFIX@_hashptr_t *hp) { @LISTHASH_PREFIX@_listptr_reset(&(hp->node)); hp->bucket = -1; } /* ** @LISTHASH_PREFIX@_hashptr_data() - retrieve the data being pointed to */ void * @LISTHASH_PREFIX@_hashptr_data(@LISTHASH_PREFIX@_hashptr_t *hp) { return @LISTHASH_PREFIX@_listptr_data(&(hp->node)); } /* ** @LISTHASH_PREFIX@_str_hashfunc() - default hash function, optimized for ** 7-bit strings */ unsigned int @LISTHASH_PREFIX@_str_hashfunc(char *key, unsigned int num_buckets) { #if 0 register unsigned result = 0; register int i; if (key == NULL) return 0; for (i = 0; *key != '\0' && i < 32; i++) result = result * 33U + *key++; return (result % num_buckets); #else if (key == NULL) return 0; return (key[0] % num_buckets); #endif } /* ** @LISTHASH_PREFIX@_hash_nents() - return number of elements from hash */ unsigned int @LISTHASH_PREFIX@_hash_nents(@LISTHASH_PREFIX@_hash_t *h) { return h->nents; } /* ** @LISTHASH_PREFIX@_hash_new() - create a new hash */ @LISTHASH_PREFIX@_hash_t * @LISTHASH_PREFIX@_hash_new(int num, @LISTHASH_PREFIX@_hashfunc_t hashfunc) { @LISTHASH_PREFIX@_hash_t *hash; hash = (@LISTHASH_PREFIX@_hash_t *)calloc(1, sizeof(@LISTHASH_PREFIX@_hash_t)); if (hash == NULL) return NULL; hash->numbuckets = num; if (hashfunc != NULL) hash->hashfunc = hashfunc; else hash->hashfunc = (@LISTHASH_PREFIX@_hashfunc_t)@LISTHASH_PREFIX@_str_hashfunc; hash->table = (@LISTHASH_PREFIX@_list_t **)calloc(num, sizeof(@LISTHASH_PREFIX@_list_t *)); if (hash->table == NULL) { free(hash); return NULL; } return hash; } /* ** @LISTHASH_PREFIX@_hash_next() - get next element in hash ** returns: ** 1 data found ** 0 end of list */ int @LISTHASH_PREFIX@_hash_next(@LISTHASH_PREFIX@_hash_t *h, @LISTHASH_PREFIX@_hashptr_t *hp) { #ifdef DS_DEBUG printf("==> @LISTHASH_PREFIX@_hash_next(h=0x%lx, hp={%d,0x%lx})\n", h, hp->bucket, hp->node); #endif if (hp->bucket >= 0 && hp->node != NULL && @LISTHASH_PREFIX@_list_next(h->table[hp->bucket], &(hp->node)) != 0) { #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_hash_next(): found additional " "data in current bucket (%d), returing 1\n", hp->bucket); #endif return 1; } #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_hash_next(): done with bucket %d\n", hp->bucket); #endif for (hp->bucket++; hp->bucket < h->numbuckets; hp->bucket++) { #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_hash_next(): " "checking bucket %d\n", hp->bucket); #endif hp->node = NULL; if (h->table[hp->bucket] != NULL && @LISTHASH_PREFIX@_list_next(h->table[hp->bucket], &(hp->node)) != 0) { #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_hash_next(): " "found data in bucket %d, returing 1\n", hp->bucket); #endif return 1; } } if (hp->bucket == h->numbuckets) { #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_hash_next(): hash pointer " "wrapped to 0\n"); #endif hp->bucket = -1; hp->node = NULL; } #ifdef DS_DEBUG printf("<== @LISTHASH_PREFIX@_hash_next(): no more data, " "returning 0\n"); #endif return 0; } /* ** @LISTHASH_PREFIX@_hash_del() - delete an entry from the hash ** returns: ** 0 success ** -1 (and sets errno) failure */ int @LISTHASH_PREFIX@_hash_del(@LISTHASH_PREFIX@_hash_t *h, @LISTHASH_PREFIX@_hashptr_t *hp) { if (hp->bucket < 0 || hp->bucket >= h->numbuckets || h->table[hp->bucket] == NULL || hp->node == NULL) { errno = EINVAL; return -1; } @LISTHASH_PREFIX@_list_del(h->table[hp->bucket], &(hp->node)); h->nents--; return 0; } /* ** @LISTHASH_PREFIX@_hash_empty() - empty the hash */ void @LISTHASH_PREFIX@_hash_empty(@LISTHASH_PREFIX@_hash_t *h, @LISTHASH_PREFIX@_freefunc_t freefunc) { int i; for (i = 0; i < h->numbuckets; i++) if (h->table[i] != NULL) @LISTHASH_PREFIX@_list_empty(h->table[i], freefunc); h->nents = 0; } /* ** @LISTHASH_PREFIX@_hash_free() - delete all of the nodes in the hash */ void @LISTHASH_PREFIX@_hash_free(@LISTHASH_PREFIX@_hash_t *h, @LISTHASH_PREFIX@_freefunc_t freefunc) { int i; for (i = 0; i < h->numbuckets; i++) if (h->table[i] != NULL) @LISTHASH_PREFIX@_list_free(h->table[i], freefunc); free(h->table); free(h); } /* ** @LISTHASH_PREFIX@_hash_search() - iterative search for an element in a hash ** returns: ** 1 match found ** 0 no match */ int @LISTHASH_PREFIX@_hash_search(@LISTHASH_PREFIX@_hash_t *h, @LISTHASH_PREFIX@_hashptr_t *hp, void *data, @LISTHASH_PREFIX@_matchfunc_t matchfunc) { while (@LISTHASH_PREFIX@_hash_next(h, hp) != 0) if ((*matchfunc)(data, @LISTHASH_PREFIX@_listptr_data(&(hp->node))) != 0) return 1; return 0; } /* ** @LISTHASH_PREFIX@_hash_getkey() - hash-based search for an element in a hash ** returns: ** 1 match found ** 0 no match */ int @LISTHASH_PREFIX@_hash_getkey(@LISTHASH_PREFIX@_hash_t *h, @LISTHASH_PREFIX@_hashptr_t *hp, void *key, @LISTHASH_PREFIX@_matchfunc_t matchfunc) { #ifdef DS_DEBUG printf("==> @LISTHASH_PREFIX@_hash_getkey(h=0x%lx, hp={%d,0x%lx}, " "key=0x%lx, matchfunc=0x%lx)\n", h, hp->bucket, hp->node, key, matchfunc); #endif if (hp->bucket == -1) { hp->bucket = (*(h->hashfunc))(key, h->numbuckets); #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_hash_getkey(): hp->bucket " "set to %d\n", hp->bucket); #endif } if (h->table[hp->bucket] == NULL) { #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_hash_getkey(): no list " "for bucket %d, returning 0\n", hp->bucket); #endif hp->bucket = -1; return 0; } #ifdef DS_DEBUG printf("<== @LISTHASH_PREFIX@_hash_getkey(): " "returning @LISTHASH_PREFIX@_list_search()\n"); #endif return @LISTHASH_PREFIX@_list_search(h->table[hp->bucket], &(hp->node), key, matchfunc); } /* ** @LISTHASH_PREFIX@_hash_add() - add an element to the hash ** returns: ** 0 success ** -1 (and sets errno) failure */ int @LISTHASH_PREFIX@_hash_add(@LISTHASH_PREFIX@_hash_t *h, void *data) { int bucket, i; #ifdef DS_DEBUG printf("==> @LISTHASH_PREFIX@_hash_add(h=0x%lx, data=0x%lx)\n", h, data); #endif bucket = (*(h->hashfunc))(data, h->numbuckets); #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_hash_add(): inserting in bucket %d\n", bucket); #endif if (h->table[bucket] == NULL) { #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_hash_add(): creating new list\n"); #endif h->table[bucket] = @LISTHASH_PREFIX@_list_new(LIST_QUEUE, NULL); } #ifdef DS_DEBUG printf("<== @LISTHASH_PREFIX@_hash_add(): " "returning @LISTHASH_PREFIX@_list_add()\n"); #endif i = @LISTHASH_PREFIX@_list_add(h->table[bucket], data); if (i == 0) h->nents++; return i; } libtar/listhash/hash_new.3.in000066400000000000000000000072261222530560000164410ustar00rootroot00000000000000.TH @LISTHASH_PREFIX@_hash_new 3 "Jan 2000" "University of Illinois" "C Library Calls" \" @configure_input@ .SH NAME @LISTHASH_PREFIX@_hash_new, @LISTHASH_PREFIX@_hash_free, @LISTHASH_PREFIX@_hash_next, @LISTHASH_PREFIX@_hash_prev, @LISTHASH_PREFIX@_hash_getkey, @LISTHASH_PREFIX@_hash_search, @LISTHASH_PREFIX@_hash_add, @LISTHASH_PREFIX@_hash_del \- hash table routines .SH SYNOPSIS .B #include <@LISTHASH_PREFIX@.h> .P .BI "@LISTHASH_PREFIX@_hash_t *@LISTHASH_PREFIX@_hash_new(int " num ", int (*" hashfunc ")());" .br .BI "void @LISTHASH_PREFIX@_hash_free(@LISTHASH_PREFIX@_hash_t *" h ", void (*" freefunc ")());" .br .BI "int @LISTHASH_PREFIX@_hash_next(@LISTHASH_PREFIX@_hash_t *" h ", @LISTHASH_PREFIX@_hashptr_t *" hp ");" .br .BI "int @LISTHASH_PREFIX@_hash_prev(@LISTHASH_PREFIX@_hash_t *" h ", @LISTHASH_PREFIX@_hashptr_t *" hp ");" .br .BI "int @LISTHASH_PREFIX@_hash_search(@LISTHASH_PREFIX@_hash_t *" h ", @LISTHASH_PREFIX@_hashptr_t *" hp "," .BI "void *" data ", int (*" matchfunc ")());" .br .BI "int @LISTHASH_PREFIX@_hash_getkey(@LISTHASH_PREFIX@_hash_t *" h ", @LISTHASH_PREFIX@_hashptr_t *" hp "," .BI "void *" data ", int (*" matchfunc ")());" .br .BI "int @LISTHASH_PREFIX@_hash_add(@LISTHASH_PREFIX@_hash_t *" h ", void *" data ");" .br .BI "int @LISTHASH_PREFIX@_hash_del(@LISTHASH_PREFIX@_hash_t *" h ", @LISTHASH_PREFIX@_hashptr_t *" hp ");" .SH DESCRIPTION The \fB@LISTHASH_PREFIX@_hash_new\fP() function creates a new hash with \fInum\fP buckets and using hash function pointed to by \fIhashfunc\fP. If \fIhashfunc\fP is \fINULL\fP, a default hash function designed for 7-bit ASCII strings is used. The \fB@LISTHASH_PREFIX@_hash_free\fP() function deallocates all memory associated with the hash structure \fIh\fP. If \fIfreefunc\fP is not \fINULL\fP, it is called to free memory associated with each node in the hash. The \fB@LISTHASH_PREFIX@_hash_next\fP() and \fB@LISTHASH_PREFIX@_hash_prev\fP() functions are used to iterate through the hash. The \fI@LISTHASH_PREFIX@_hashptr_t\fP structure has two fields: \fIbucket\fP, which indicates the current bucket in the hash, and \fInode\fP, which is a pointer to the current node in the current bucket. To start at the beginning or end of the hash, the caller should initialize \fIhp.bucket\fP to \-1 and \fIhp.node\fP to \fINULL\fP. The \fB@LISTHASH_PREFIX@_hash_search\fP() function searches iteratively through the hash \fIh\fP until it finds a node whose contents match \fIdata\fP using the matching function \fImatchfunc\fP. Searching begins at the location pointed to by \fIhp\fP. The \fB@LISTHASH_PREFIX@_hash_getkey\fP() function uses the hash function associated with \fIh\fP to determine which bucket \fIdata\fP should be in, and searches only that bucket for a matching node using \fImatchfunc\fP. Searching begins at the location pointed to by \fIhp\fP. The \fB@LISTHASH_PREFIX@_hash_add\fP() function adds \fIdata\fP into hash \fIh\fP. The \fB@LISTHASH_PREFIX@_hash_del\fP() function removes the node referenced by \fIhp\fP. .SH RETURN VALUE The \fB@LISTHASH_PREFIX@_hash_new\fP() function returns a pointer to the new hash structure, or \fINULL\fP on error. The \fB@LISTHASH_PREFIX@_hash_next\fP() and \fB@LISTHASH_PREFIX@_hash_prev\fP() functions return 1 when valid data is returned, and 0 at the end of the hash. The \fB@LISTHASH_PREFIX@_hash_getkey\fP() and \fB@LISTHASH_PREFIX@_hash_search\fP() functions return 1 when a match is found, or 0 otherwise. The \fB@LISTHASH_PREFIX@_hash_add\fP() function returns 0 on success, or \-1 on error (and sets \fIerrno\fP). The \fB@LISTHASH_PREFIX@_hash_del\fP() function returns 0 on success, or \-1 on error (and sets \fIerrno\fP). .SH SEE ALSO .BR @LISTHASH_PREFIX@_list_new (3) libtar/listhash/list.c.in000066400000000000000000000215701222530560000156760ustar00rootroot00000000000000/* @configure_input@ */ /* ** Copyright 1998-2002 University of Illinois Board of Trustees ** Copyright 1998-2002 Mark D. Roth ** All rights reserved. ** ** @LISTHASH_PREFIX@_list.c - linked list routines ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #include #include #include <@LISTHASH_PREFIX@_listhash.h> #include #include #include #ifdef STDC_HEADERS # include # include #endif /* ** @LISTHASH_PREFIX@_listptr_reset() - reset a list pointer */ void @LISTHASH_PREFIX@_listptr_reset(@LISTHASH_PREFIX@_listptr_t *lp) { *lp = NULL; } /* ** @LISTHASH_PREFIX@_listptr_data() - retrieve the data pointed to by lp */ void * @LISTHASH_PREFIX@_listptr_data(@LISTHASH_PREFIX@_listptr_t *lp) { return (*lp)->data; } /* ** @LISTHASH_PREFIX@_list_new() - create a new, empty list */ @LISTHASH_PREFIX@_list_t * @LISTHASH_PREFIX@_list_new(int flags, @LISTHASH_PREFIX@_cmpfunc_t cmpfunc) { @LISTHASH_PREFIX@_list_t *newlist; #ifdef DS_DEBUG printf("in @LISTHASH_PREFIX@_list_new(%d, 0x%lx)\n", flags, cmpfunc); #endif if (flags != LIST_USERFUNC && flags != LIST_STACK && flags != LIST_QUEUE) { errno = EINVAL; return NULL; } newlist = (@LISTHASH_PREFIX@_list_t *)calloc(1, sizeof(@LISTHASH_PREFIX@_list_t)); if (cmpfunc != NULL) newlist->cmpfunc = cmpfunc; else newlist->cmpfunc = (@LISTHASH_PREFIX@_cmpfunc_t)strcmp; newlist->flags = flags; return newlist; } /* ** @LISTHASH_PREFIX@_list_iterate() - call a function for every element ** in a list */ int @LISTHASH_PREFIX@_list_iterate(@LISTHASH_PREFIX@_list_t *l, @LISTHASH_PREFIX@_iterate_func_t plugin, void *state) { @LISTHASH_PREFIX@_listptr_t n; if (l == NULL) return -1; for (n = l->first; n != NULL; n = n->next) { if ((*plugin)(n->data, state) == -1) return -1; } return 0; } /* ** @LISTHASH_PREFIX@_list_empty() - empty the list */ void @LISTHASH_PREFIX@_list_empty(@LISTHASH_PREFIX@_list_t *l, @LISTHASH_PREFIX@_freefunc_t freefunc) { @LISTHASH_PREFIX@_listptr_t n; for (n = l->first; n != NULL; n = l->first) { l->first = n->next; if (freefunc != NULL) (*freefunc)(n->data); free(n); } l->nents = 0; } /* ** @LISTHASH_PREFIX@_list_free() - remove and free() the whole list */ void @LISTHASH_PREFIX@_list_free(@LISTHASH_PREFIX@_list_t *l, @LISTHASH_PREFIX@_freefunc_t freefunc) { @LISTHASH_PREFIX@_list_empty(l, freefunc); free(l); } /* ** @LISTHASH_PREFIX@_list_nents() - return number of elements in the list */ unsigned int @LISTHASH_PREFIX@_list_nents(@LISTHASH_PREFIX@_list_t *l) { return l->nents; } /* ** @LISTHASH_PREFIX@_list_add() - adds an element to the list ** returns: ** 0 success ** -1 (and sets errno) failure */ int @LISTHASH_PREFIX@_list_add(@LISTHASH_PREFIX@_list_t *l, void *data) { @LISTHASH_PREFIX@_listptr_t n, m; #ifdef DS_DEBUG printf("==> @LISTHASH_PREFIX@_list_add(\"%s\")\n", (char *)data); #endif n = (@LISTHASH_PREFIX@_listptr_t)malloc(sizeof(struct @LISTHASH_PREFIX@_node)); if (n == NULL) return -1; n->data = data; l->nents++; #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_list_add(): allocated data\n"); #endif /* if the list is empty */ if (l->first == NULL) { l->last = l->first = n; n->next = n->prev = NULL; #ifdef DS_DEBUG printf("<== @LISTHASH_PREFIX@_list_add(): list was empty; " "added first element and returning 0\n"); #endif return 0; } #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_list_add(): list not empty\n"); #endif if (l->flags == LIST_STACK) { n->prev = NULL; n->next = l->first; if (l->first != NULL) l->first->prev = n; l->first = n; #ifdef DS_DEBUG printf("<== @LISTHASH_PREFIX@_list_add(): LIST_STACK set; " "added in front\n"); #endif return 0; } if (l->flags == LIST_QUEUE) { n->prev = l->last; n->next = NULL; if (l->last != NULL) l->last->next = n; l->last = n; #ifdef DS_DEBUG printf("<== @LISTHASH_PREFIX@_list_add(): LIST_QUEUE set; " "added at end\n"); #endif return 0; } for (m = l->first; m != NULL; m = m->next) if ((*(l->cmpfunc))(data, m->data) < 0) { /* ** if we find one that's bigger, ** insert data before it */ #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_list_add(): gotcha..." "inserting data\n"); #endif if (m == l->first) { l->first = n; n->prev = NULL; m->prev = n; n->next = m; #ifdef DS_DEBUG printf("<== @LISTHASH_PREFIX@_list_add(): " "added first, returning 0\n"); #endif return 0; } m->prev->next = n; n->prev = m->prev; m->prev = n; n->next = m; #ifdef DS_DEBUG printf("<== @LISTHASH_PREFIX@_list_add(): added middle," " returning 0\n"); #endif return 0; } #ifdef DS_DEBUG printf(" @LISTHASH_PREFIX@_list_add(): new data larger than current " "list elements\n"); #endif /* if we get here, data is bigger than everything in the list */ l->last->next = n; n->prev = l->last; l->last = n; n->next = NULL; #ifdef DS_DEBUG printf("<== @LISTHASH_PREFIX@_list_add(): added end, returning 0\n"); #endif return 0; } /* ** @LISTHASH_PREFIX@_list_del() - remove the element pointed to by n ** from the list l */ void @LISTHASH_PREFIX@_list_del(@LISTHASH_PREFIX@_list_t *l, @LISTHASH_PREFIX@_listptr_t *n) { @LISTHASH_PREFIX@_listptr_t m; #ifdef DS_DEBUG printf("==> @LISTHASH_PREFIX@_list_del()\n"); #endif l->nents--; m = (*n)->next; if ((*n)->prev) (*n)->prev->next = (*n)->next; else l->first = (*n)->next; if ((*n)->next) (*n)->next->prev = (*n)->prev; else l->last = (*n)->prev; free(*n); *n = m; } /* ** @LISTHASH_PREFIX@_list_next() - get the next element in the list ** returns: ** 1 success ** 0 end of list */ int @LISTHASH_PREFIX@_list_next(@LISTHASH_PREFIX@_list_t *l, @LISTHASH_PREFIX@_listptr_t *n) { if (*n == NULL) *n = l->first; else *n = (*n)->next; return (*n != NULL ? 1 : 0); } /* ** @LISTHASH_PREFIX@_list_prev() - get the previous element in the list ** returns: ** 1 success ** 0 end of list */ int @LISTHASH_PREFIX@_list_prev(@LISTHASH_PREFIX@_list_t *l, @LISTHASH_PREFIX@_listptr_t *n) { if (*n == NULL) *n = l->last; else *n = (*n)->prev; return (*n != NULL ? 1 : 0); } /* ** @LISTHASH_PREFIX@_str_match() - string matching function ** returns: ** 1 match ** 0 no match */ int @LISTHASH_PREFIX@_str_match(char *check, char *data) { return !strcmp(check, data); } /* ** @LISTHASH_PREFIX@_list_add_str() - splits string str into delim-delimited ** elements and adds them to list l ** returns: ** 0 success ** -1 (and sets errno) failure */ int @LISTHASH_PREFIX@_list_add_str(@LISTHASH_PREFIX@_list_t *l, char *str, char *delim) { char tmp[10240]; char *tokp, *nextp = tmp; strlcpy(tmp, str, sizeof(tmp)); while ((tokp = strsep(&nextp, delim)) != NULL) { if (*tokp == '\0') continue; if (@LISTHASH_PREFIX@_list_add(l, strdup(tokp))) return -1; } return 0; } /* ** @LISTHASH_PREFIX@_list_search() - find an entry in a list ** returns: ** 1 match found ** 0 no match */ int @LISTHASH_PREFIX@_list_search(@LISTHASH_PREFIX@_list_t *l, @LISTHASH_PREFIX@_listptr_t *n, void *data, @LISTHASH_PREFIX@_matchfunc_t matchfunc) { #ifdef DS_DEBUG printf("==> @LISTHASH_PREFIX@_list_search(l=0x%lx, n=0x%lx, \"%s\")\n", l, n, (char *)data); #endif if (matchfunc == NULL) matchfunc = (@LISTHASH_PREFIX@_matchfunc_t)@LISTHASH_PREFIX@_str_match; if (*n == NULL) *n = l->first; else *n = (*n)->next; for (; *n != NULL; *n = (*n)->next) { #ifdef DS_DEBUG printf("checking against \"%s\"\n", (char *)(*n)->data); #endif if ((*(matchfunc))(data, (*n)->data) != 0) return 1; } #ifdef DS_DEBUG printf("no matches found\n"); #endif return 0; } /* ** @LISTHASH_PREFIX@_list_dup() - copy an existing list */ @LISTHASH_PREFIX@_list_t * @LISTHASH_PREFIX@_list_dup(@LISTHASH_PREFIX@_list_t *l) { @LISTHASH_PREFIX@_list_t *newlist; @LISTHASH_PREFIX@_listptr_t n; newlist = @LISTHASH_PREFIX@_list_new(l->flags, l->cmpfunc); for (n = l->first; n != NULL; n = n->next) @LISTHASH_PREFIX@_list_add(newlist, n->data); #ifdef DS_DEBUG printf("returning from @LISTHASH_PREFIX@_list_dup()\n"); #endif return newlist; } /* ** @LISTHASH_PREFIX@_list_merge() - merge two lists into a new list */ @LISTHASH_PREFIX@_list_t * @LISTHASH_PREFIX@_list_merge(@LISTHASH_PREFIX@_cmpfunc_t cmpfunc, int flags, @LISTHASH_PREFIX@_list_t *list1, @LISTHASH_PREFIX@_list_t *list2) { @LISTHASH_PREFIX@_list_t *newlist; @LISTHASH_PREFIX@_listptr_t n; newlist = @LISTHASH_PREFIX@_list_new(flags, cmpfunc); n = NULL; while (@LISTHASH_PREFIX@_list_next(list1, &n) != 0) @LISTHASH_PREFIX@_list_add(newlist, n->data); n = NULL; while (@LISTHASH_PREFIX@_list_next(list2, &n) != 0) @LISTHASH_PREFIX@_list_add(newlist, n->data); return newlist; } libtar/listhash/list_new.3.in000066400000000000000000000101611222530560000164610ustar00rootroot00000000000000.TH @LISTHASH_PREFIX@_list_new 3 "Jan 2000" "University of Illinois" "C Library Calls" \" @configure_input@ .SH NAME @LISTHASH_PREFIX@_list_new, @LISTHASH_PREFIX@_list_free, @LISTHASH_PREFIX@_list_next, @LISTHASH_PREFIX@_list_prev, @LISTHASH_PREFIX@_list_add, @LISTHASH_PREFIX@_list_del, @LISTHASH_PREFIX@_list_search, @LISTHASH_PREFIX@_list_dup, @LISTHASH_PREFIX@_list_merge, @LISTHASH_PREFIX@_list_add_str \- linked list routines .SH SYNOPSIS .B #include <@LISTHASH_PREFIX@.h> .P .BI "@LISTHASH_PREFIX@_list_t *@LISTHASH_PREFIX@_list_new(int " flags "," .BI "int (*" cmpfunc ")());" .br .BI "void @LISTHASH_PREFIX@_list_free(@LISTHASH_PREFIX@_list_t *" l ", void (*" freefunc ")());" .br .BI "int @LISTHASH_PREFIX@_list_add_str(@LISTHASH_PREFIX@_list_t *" l ", char *" str "," .BI "char *" delim ");" .br .BI "int @LISTHASH_PREFIX@_list_add(@LISTHASH_PREFIX@_list_t *" l ", void *" data ");" .br .BI "void @LISTHASH_PREFIX@_list_del(@LISTHASH_PREFIX@_list_t *" l ", @LISTHASH_PREFIX@_node_t **" n ");" .br .BI "int @LISTHASH_PREFIX@_list_search(@LISTHASH_PREFIX@_list_t *" l ", @LISTHASH_PREFIX@_node_t **" n "," .BI "void *" data ", int (*" matchfunc ")());" .br .BI "int @LISTHASH_PREFIX@_list_next(@LISTHASH_PREFIX@_list_t *" l ", @LISTHASH_PREFIX@_node_t **" n ");" .br .BI "int @LISTHASH_PREFIX@_list_prev(@LISTHASH_PREFIX@_list_t *" l ", @LISTHASH_PREFIX@_node_t **" n ");" .br .BI "@LISTHASH_PREFIX@_list_t *@LISTHASH_PREFIX@_list_dup(@LISTHASH_PREFIX@_list_t *" l ");" .br .BI "@LISTHASH_PREFIX@_list_t *@LISTHASH_PREFIX@_list_merge(int (*" cmpfunc ")(), int " flags "," .BI "@LISTHASH_PREFIX@_list_t *" list1 ", @LISTHASH_PREFIX@_list_t *" list2 ");" .SH DESCRIPTION The \fB@LISTHASH_PREFIX@_list_new\fP() function creates a new list. The \fIflags\fP argument must be one of the following values: .IP \fBLIST_USERFUNC\fP The \fIcmpfunc\fP argument points to a user-supplied function which determines the ordering of the list. .IP \fBLIST_STACK\fP Use the list as a stack. New elements are added to the front of the list. .IP \fBLIST_QUEUE\fP Use the list as a queue. New elements are added to the end of the list. .PP The \fB@LISTHASH_PREFIX@_list_free\fP() function deallocates all memory associated with the list \fIl\fP. If \fIfreefunc\fP is not \fINULL\fP, it is called to free memory associated with each node in the list. The \fB@LISTHASH_PREFIX@_list_add\fP() function adds the element pointed to by \fIdata\fP to the list \fIl\fP. The position of the new element will be determined by the flags passed to \fB@LISTHASH_PREFIX@_list_new\fP() when the list was created. The \fB@LISTHASH_PREFIX@_list_add_str\fP() function tokenizes the string \fIstr\fP using the delimiter characters in the string \fIdelim\fP. The resulting tokens are added to list \fIl\fP using \fB@LISTHASH_PREFIX@_list_add\fP(). The \fB@LISTHASH_PREFIX@_list_search\fP() function searches for an element which matches \fIdata\fP using the matching function \fImatchfunc\fP. If \fImatchfunc\fP is \fINULL\fP, a default matching function designed for ASCII strings is used. Searching begins from the node pointed to by \fIn\fP. The \fB@LISTHASH_PREFIX@_list_del\fP() function removes the entry pointed to by \fIn\fP from the list pointed to by \fIl\fP. The \fB@LISTHASH_PREFIX@_list_dup\fP() function creates a copy of the list \fIl\fP using dynamically allocated memory. The \fB@LISTHASH_PREFIX@_list_merge\fP() function creates a new list with \fIflags\fP and \fIcmpfunc\fP, in the same way as \fB@LISTHASH_PREFIX@_list_new\fP(). It then adds all elements from \fIlist1\fP and \fIlist2\fP using \fB@LISTHASH_PREFIX@_list_add\fP(). .SH RETURN VALUE The \fB@LISTHASH_PREFIX@_list_new\fP(), \fB@LISTHASH_PREFIX@_list_dup\fP(), and \fB@LISTHASH_PREFIX@_list_merge\fP() functions return a pointer to the new list structure, or \fINULL\fP on error. The \fB@LISTHASH_PREFIX@_list_next\fP(), \fB@LISTHASH_PREFIX@_list_prev\fP(), and \fB@LISTHASH_PREFIX@_list_search\fP() functions return 1 when valid data is returned, or 0 otherwise. The \fB@LISTHASH_PREFIX@_list_add\fP() and \fB@LISTHASH_PREFIX@_list_add_str\fP() functions return 0 on success, or \-1 on error. .SH SEE ALSO .BR @LISTHASH_PREFIX@_hash_new (3) libtar/listhash/listhash.h.in000066400000000000000000000141611222530560000165450ustar00rootroot00000000000000/* @configure_input@ */ /* ** Copyright 1998-2002 University of Illinois Board of Trustees ** Copyright 1998-2002 Mark D. Roth ** All rights reserved. ** ** @LISTHASH_PREFIX@_listhash.h - header file for listhash module ** ** Mark D. Roth ** Campus Information Technologies and Educational Services ** University of Illinois at Urbana-Champaign */ #ifndef @LISTHASH_PREFIX@_LISTHASH_H #define @LISTHASH_PREFIX@_LISTHASH_H #ifdef __cplusplus extern "C" { #endif /***** list.c **********************************************************/ /* ** Comparison function (used to determine order of elements in a list) ** returns less than, equal to, or greater than 0 ** if data1 is less than, equal to, or greater than data2 */ typedef int (*@LISTHASH_PREFIX@_cmpfunc_t)(void *, void *); /* ** Free function (for freeing allocated memory in each element) */ typedef void (*@LISTHASH_PREFIX@_freefunc_t)(void *); /* ** Plugin function for @LISTHASH_PREFIX@_list_iterate() */ typedef int (*@LISTHASH_PREFIX@_iterate_func_t)(void *, void *); /* ** Matching function (used to find elements in a list) ** first argument is the data to search for ** second argument is the list element it's being compared to ** returns 0 if no match is found, non-zero otherwise */ typedef int (*@LISTHASH_PREFIX@_matchfunc_t)(void *, void *); struct @LISTHASH_PREFIX@_node { void *data; struct @LISTHASH_PREFIX@_node *next; struct @LISTHASH_PREFIX@_node *prev; }; typedef struct @LISTHASH_PREFIX@_node *@LISTHASH_PREFIX@_listptr_t; struct @LISTHASH_PREFIX@_list { @LISTHASH_PREFIX@_listptr_t first; @LISTHASH_PREFIX@_listptr_t last; @LISTHASH_PREFIX@_cmpfunc_t cmpfunc; int flags; unsigned int nents; }; typedef struct @LISTHASH_PREFIX@_list @LISTHASH_PREFIX@_list_t; /* values for flags */ #define LIST_USERFUNC 0 /* use cmpfunc() to order */ #define LIST_STACK 1 /* new elements go in front */ #define LIST_QUEUE 2 /* new elements go at the end */ /* reset a list pointer */ void @LISTHASH_PREFIX@_listptr_reset(@LISTHASH_PREFIX@_listptr_t *); /* retrieve the data being pointed to */ void *@LISTHASH_PREFIX@_listptr_data(@LISTHASH_PREFIX@_listptr_t *); /* creates a new, empty list */ @LISTHASH_PREFIX@_list_t *@LISTHASH_PREFIX@_list_new(int, @LISTHASH_PREFIX@_cmpfunc_t); /* call a function for every element in a list */ int @LISTHASH_PREFIX@_list_iterate(@LISTHASH_PREFIX@_list_t *, @LISTHASH_PREFIX@_iterate_func_t, void *); /* empty the list */ void @LISTHASH_PREFIX@_list_empty(@LISTHASH_PREFIX@_list_t *, @LISTHASH_PREFIX@_freefunc_t); /* remove and free() the entire list */ void @LISTHASH_PREFIX@_list_free(@LISTHASH_PREFIX@_list_t *, @LISTHASH_PREFIX@_freefunc_t); /* add elements */ int @LISTHASH_PREFIX@_list_add(@LISTHASH_PREFIX@_list_t *, void *); /* removes an element from the list - returns -1 on error */ void @LISTHASH_PREFIX@_list_del(@LISTHASH_PREFIX@_list_t *, @LISTHASH_PREFIX@_listptr_t *); /* returns 1 when valid data is returned, or 0 at end of list */ int @LISTHASH_PREFIX@_list_next(@LISTHASH_PREFIX@_list_t *, @LISTHASH_PREFIX@_listptr_t *); /* returns 1 when valid data is returned, or 0 at end of list */ int @LISTHASH_PREFIX@_list_prev(@LISTHASH_PREFIX@_list_t *, @LISTHASH_PREFIX@_listptr_t *); /* return 1 if the data matches a list entry, 0 otherwise */ int @LISTHASH_PREFIX@_list_search(@LISTHASH_PREFIX@_list_t *, @LISTHASH_PREFIX@_listptr_t *, void *, @LISTHASH_PREFIX@_matchfunc_t); /* return number of elements from list */ unsigned int @LISTHASH_PREFIX@_list_nents(@LISTHASH_PREFIX@_list_t *); /* adds elements from a string delimited by delim */ int @LISTHASH_PREFIX@_list_add_str(@LISTHASH_PREFIX@_list_t *, char *, char *); /* string matching function */ int @LISTHASH_PREFIX@_str_match(char *, char *); /***** hash.c **********************************************************/ /* ** Hashing function (determines which bucket the given key hashes into) ** first argument is the key to hash ** second argument is the total number of buckets ** returns the bucket number */ typedef unsigned int (*@LISTHASH_PREFIX@_hashfunc_t)(void *, unsigned int); struct @LISTHASH_PREFIX@_hashptr { int bucket; @LISTHASH_PREFIX@_listptr_t node; }; typedef struct @LISTHASH_PREFIX@_hashptr @LISTHASH_PREFIX@_hashptr_t; struct @LISTHASH_PREFIX@_hash { int numbuckets; @LISTHASH_PREFIX@_list_t **table; @LISTHASH_PREFIX@_hashfunc_t hashfunc; unsigned int nents; }; typedef struct @LISTHASH_PREFIX@_hash @LISTHASH_PREFIX@_hash_t; /* reset a hash pointer */ void @LISTHASH_PREFIX@_hashptr_reset(@LISTHASH_PREFIX@_hashptr_t *); /* retrieve the data being pointed to */ void *@LISTHASH_PREFIX@_hashptr_data(@LISTHASH_PREFIX@_hashptr_t *); /* default hash function, optimized for 7-bit strings */ unsigned int @LISTHASH_PREFIX@_str_hashfunc(char *, unsigned int); /* return number of elements from hash */ unsigned int @LISTHASH_PREFIX@_hash_nents(@LISTHASH_PREFIX@_hash_t *); /* create a new hash */ @LISTHASH_PREFIX@_hash_t *@LISTHASH_PREFIX@_hash_new(int, @LISTHASH_PREFIX@_hashfunc_t); /* empty the hash */ void @LISTHASH_PREFIX@_hash_empty(@LISTHASH_PREFIX@_hash_t *, @LISTHASH_PREFIX@_freefunc_t); /* delete all the @LISTHASH_PREFIX@_nodes of the hash and clean up */ void @LISTHASH_PREFIX@_hash_free(@LISTHASH_PREFIX@_hash_t *, @LISTHASH_PREFIX@_freefunc_t); /* returns 1 when valid data is returned, or 0 at end of list */ int @LISTHASH_PREFIX@_hash_next(@LISTHASH_PREFIX@_hash_t *, @LISTHASH_PREFIX@_hashptr_t *); /* return 1 if the data matches a list entry, 0 otherwise */ int @LISTHASH_PREFIX@_hash_search(@LISTHASH_PREFIX@_hash_t *, @LISTHASH_PREFIX@_hashptr_t *, void *, @LISTHASH_PREFIX@_matchfunc_t); /* return 1 if the key matches a list entry, 0 otherwise */ int @LISTHASH_PREFIX@_hash_getkey(@LISTHASH_PREFIX@_hash_t *, @LISTHASH_PREFIX@_hashptr_t *, void *, @LISTHASH_PREFIX@_matchfunc_t); /* inserting data */ int @LISTHASH_PREFIX@_hash_add(@LISTHASH_PREFIX@_hash_t *, void *); /* delete an entry */ int @LISTHASH_PREFIX@_hash_del(@LISTHASH_PREFIX@_hash_t *, @LISTHASH_PREFIX@_hashptr_t *); #ifdef __cplusplus } #endif #endif /* ! @LISTHASH_PREFIX@_LISTHASH_H */ libtar/listhash/module.ac000066400000000000000000000011561222530560000157420ustar00rootroot00000000000000AC_DEFUN(subdir[_INIT], [ AC_REQUIRE([COMPAT_FUNC_STRLCPY]) AC_REQUIRE([COMPAT_FUNC_STRSEP]) if test -z "$2"; then LISTHASH_PREFIX="${PACKAGE_NAME}"; else LISTHASH_PREFIX="$2"; fi AC_SUBST([LISTHASH_PREFIX]) LISTHASH_DIR="$1"; AC_SUBST([LISTHASH_DIR]) AC_CONFIG_FILES([$1/${LISTHASH_PREFIX}_listhash.h:$1/listhash.h.in]) AC_CONFIG_FILES([$1/${LISTHASH_PREFIX}_list.c:$1/list.c.in]) AC_CONFIG_FILES([$1/${LISTHASH_PREFIX}_hash.c:$1/hash.c.in]) AC_CONFIG_FILES([$1/${LISTHASH_PREFIX}_list_new.3:$1/list_new.3.in]) AC_CONFIG_FILES([$1/${LISTHASH_PREFIX}_hash_new.3:$1/hash_new.3.in]) ])