diff options
author | Andy Cedilnik <andy.cedilnik@kitware.com> | 2005-12-28 15:18:37 (GMT) |
---|---|---|
committer | Andy Cedilnik <andy.cedilnik@kitware.com> | 2005-12-28 15:18:37 (GMT) |
commit | bc1548b236515514c138da8b59f61af2efbfc4a5 (patch) | |
tree | ab8ab5b2bceca941f363ca7064248ece6779b617 /Utilities/cmtar | |
parent | 552842d11f845ad53e4f34be549aa4007737564b (diff) | |
download | CMake-bc1548b236515514c138da8b59f61af2efbfc4a5.zip CMake-bc1548b236515514c138da8b59f61af2efbfc4a5.tar.gz CMake-bc1548b236515514c138da8b59f61af2efbfc4a5.tar.bz2 |
ENH: Initial import
Diffstat (limited to 'Utilities/cmtar')
38 files changed, 7705 insertions, 0 deletions
diff --git a/Utilities/cmtar/CMakeLists.txt b/Utilities/cmtar/CMakeLists.txt new file mode 100644 index 0000000..dd50316 --- /dev/null +++ b/Utilities/cmtar/CMakeLists.txt @@ -0,0 +1,360 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.0) +PROJECT(LIBTAR C) +INCLUDE_REGULAR_EXPRESSION("^.*\\.h$") + +# We need ansi c-flags, especially on HP +SET(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}") +SET(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS}) + +# If we are on AIX, do the _ALL_SOURCE magic +IF(${CMAKE_SYSTEM_NAME} MATCHES AIX) + SET(_ALL_SOURCE 1) +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES AIX) + +# Include all the necessary files for macros +#SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake") +# Include all the necessary files for macros +INCLUDE (CheckIncludeFiles) +INCLUDE (CheckFunctionExists) +INCLUDE (CheckTypeSize) +INCLUDE (CheckSymbolExists) +INCLUDE (TestBigEndian) + +MACRO(MANGLE_VARIABLE_NAME str var prefix) + STRING(TOUPPER "${str}" mangle_variable_name_var) + STRING(REGEX REPLACE "[/. ]" "_" mangle_variable_name_var "${mangle_variable_name_var}") + SET(${var} "${prefix}${mangle_variable_name_var}") +ENDMACRO(MANGLE_VARIABLE_NAME str var) + +# Check if header file exists and add it to the list. +MACRO(CHECK_INCLUDE_FILE_CONCAT FILE) + MANGLE_VARIABLE_NAME("${FILE}" "CHECK_INCLUDE_FILE_CONCAT_VAR" "HAVE_") + CHECK_INCLUDE_FILES("${HEADER_INCLUDES};${FILE}" ${CHECK_INCLUDE_FILE_CONCAT_VAR}) + IF(${CHECK_INCLUDE_FILE_CONCAT_VAR}) + SET(HEADER_INCLUDES ${HEADER_INCLUDES} ${FILE}) + ENDIF(${CHECK_INCLUDE_FILE_CONCAT_VAR}) +ENDMACRO(CHECK_INCLUDE_FILE_CONCAT) + +MACRO(CHECK_FUNCTION_EXISTS_EX FUNC) + MANGLE_VARIABLE_NAME("${FUNC}" "CHECK_FUNCTION_EXISTS_EX_VAR" "HAVE_") + CHECK_FUNCTION_EXISTS("${FUNC}" "${CHECK_FUNCTION_EXISTS_EX_VAR}") +ENDMACRO(CHECK_FUNCTION_EXISTS_EX) + +MACRO(CHECK_SYMBOL_EXISTS_EX SYM) + MANGLE_VARIABLE_NAME("${SYM}" "CHECK_SYMBOL_EXISTS_EX_VAR" "HAVE_") + CHECK_SYMBOL_EXISTS("${SYM}" "${HEADER_INCLUDES}" "${CHECK_SYMBOL_EXISTS_EX_VAR}") +ENDMACRO(CHECK_SYMBOL_EXISTS_EX) + +#MACRO(CHECK_TYPE_SIZE_EX type defualt_size) +# MANGLE_VARIABLE_NAME("${type}" "check_type_size_var" "") +# CHECK_TYPE_SIZE("${type}" "SIZEOF_${check_type_size_var}") +# IF(HAVE_${check_type_size_var}) +# SET("HAVE_${check_type_size_var}" 1) +# ELSE(HAVE_${check_type_size_var}) +# ENDIF(HAVE_${check_type_size_var}) +#ENDMACRO(CHECK_TYPE_SIZE_EX) + + + +INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}") +INCLUDE_DIRECTORIES(${CURL_SPECIAL_LIBZ_INCLUDES}) + +#check for stdc headers +CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS) + +#check for other headers used by the program +FOREACH(file + "ctype.h" + "fnmatch.h" + "inttypes.h" + "libgen.h" + "memory.h" + "stdint.h" + "stdlib.h" + "stdio.h" + "string.h" + "strings.h" + "sys/types.h" + "sys/stat.h" + "unistd.h" + "glob.h" + ) + CHECK_INCLUDE_FILE_CONCAT("${file}") +ENDFOREACH(file) + +#check for the functions used by the program +FOREACH(func + basename + dirname + fnmatch + lchown + snprintf + strlcpy + strmode + strsep + strdup + strftime + glob + ) + CHECK_SYMBOL_EXISTS_EX("${func}") +ENDFOREACH(func) + +CHECK_TYPE_SIZE("dev_t" SIZEOF_DEV_T) +IF(HAVE_SIZEOF_DEV_T) + SET (HAVE_DEV_T 1) +ELSE(HAVE_SIZEOF_DEV_T) + SET (HAVE_DEV_T 0) + SET (dev_t "unsigned long") +ENDIF(HAVE_SIZEOF_DEV_T) + +CHECK_TYPE_SIZE("major_t" SIZEOF_MAJOR_T) +IF(HAVE_SIZEOF_MAJOR_T) + SET (HAVE_MAJOR_T 1) +ELSE(HAVE_SIZEOF_MAJOR_T) + SET (HAVE_MAJOR_T 0) + SET (major_t "unsigned int") +ENDIF(HAVE_SIZEOF_MAJOR_T) + +CHECK_TYPE_SIZE("minor_t" SIZEOF_MINOR_T) +IF(HAVE_SIZEOF_MINOR_T) + SET (HAVE_MINOR_T 1) +ELSE(HAVE_SIZEOF_MINOR_T) + SET (HAVE_MINOR_T 0) + SET (minor_t "unsigned int") +ENDIF(HAVE_SIZEOF_MINOR_T) + +CHECK_TYPE_SIZE("nlink_t" SIZEOF_NLINK_T) +IF(HAVE_SIZEOF_NLINK_T) + SET (HAVE_NLINK_T 1) +ELSE(HAVE_SIZEOF_NLINK_T) + SET (HAVE_NLINK_T 0) + SET (nlink_t "unsigned short") +ENDIF(HAVE_SIZEOF_NLINK_T) + +CHECK_TYPE_SIZE("uint64_t" SIZEOF_UINT64_T) +IF(HAVE_SIZEOF_UINT64_T) + SET (HAVE_UINT64_T 1) +ELSE(HAVE_SIZEOF_UINT64_T) + SET (HAVE_UINT64_T 0) + SET (uint64_t "long long") +ENDIF(HAVE_SIZEOF_UINT64_T) + +CHECK_TYPE_SIZE("socklen_t" SIZEOF_SOCKLEN_T) +IF(HAVE_SIZEOF_SOCKLEN_T) + SET (HAVE_SOCKLEN_T 1) +ELSE(HAVE_SIZEOF_SOCKLEN_T) + SET (HAVE_SOCKLEN_T 0) + SET (socklen_t "unsigned long") +ENDIF(HAVE_SIZEOF_SOCKLEN_T) + +CHECK_TYPE_SIZE("gid_t" SIZEOF_GID_T) +IF(HAVE_SIZEOF_GID_T) + SET (HAVE_GID_T 1) +ELSE(HAVE_SIZEOF_GID_T) + SET (HAVE_GID_T 0) + SET (gid_t "int") +ENDIF(HAVE_SIZEOF_GID_T) + +CHECK_TYPE_SIZE("mode_t" SIZEOF_MODE_T) +IF(HAVE_SIZEOF_MODE_T) + SET (HAVE_MODE_T 1) +ELSE(HAVE_SIZEOF_MODE_T) + SET (HAVE_MODE_T 0) + SET (mode_t "int") +ENDIF(HAVE_SIZEOF_MODE_T) + +CHECK_TYPE_SIZE("off_t" SIZEOF_OFF_T) +IF(HAVE_SIZEOF_OFF_T) + SET (HAVE_OFF_T 1) +ELSE(HAVE_SIZEOF_OFF_T) + SET (HAVE_OFF_T 0) + SET (off_t "long") +ENDIF(HAVE_SIZEOF_OFF_T) + +CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T) +IF(HAVE_SIZEOF_SIZE_T) + SET (HAVE_SIZE_T 1) +ELSE(HAVE_SIZEOF_SIZE_T) + SET (HAVE_SIZE_T 0) + SET (size_t "unsigned") +ENDIF(HAVE_SIZEOF_SIZE_T) + +CHECK_TYPE_SIZE("ssize_t" SIZEOF_SSIZE_T) +IF(HAVE_SIZEOF_SSIZE_T) + SET (HAVE_SSIZE_T 1) +ELSE(HAVE_SIZEOF_SSIZE_T) + SET (HAVE_SSIZE_T 0) + SET (ssize_t "int") +ENDIF(HAVE_SIZEOF_SSIZE_T) + +CHECK_TYPE_SIZE("uid_t" SIZEOF_UID_T) +IF(HAVE_SIZEOF_UID_T) + SET (HAVE_UID_T 1) +ELSE(HAVE_SIZEOF_UID_T) + SET (HAVE_UID_T 0) + SET (uid_t "int") +ENDIF(HAVE_SIZEOF_UID_T) + +#SET (HAVE_BASENAME 0) +#SET (HAVE_CTYPE_H 0) +#SET (HAVE_DEV_T 1) +#SET (HAVE_DIRNAME 0) +#SET (HAVE_FNMATCH 1) +#SET (HAVE_FNMATCH_H 1) +#SET (HAVE_INTTYPES_H 1) +#SET (HAVE_LCHOWN 1) +#SET (HAVE_LIBGEN_H 1) +SET (HAVE_LIBZ 1) +#SET (HAVE_MAJOR_T 0) +#SET (HAVE_MEMORY_H 1) +#SET (HAVE_MINOR_T 0) +#SET (HAVE_NLINK_T 1) +#SET (HAVE_SNPRINTF 1) +#SET (HAVE_SOCKLEN_T 1) +#SET (HAVE_STDINT_H 1) +#SET (HAVE_STDLIB_H 1) +#SET (HAVE_STRDUP 1) +#SET (HAVE_STRFTIME 1) +#SET (HAVE_STRINGS_H 1) +#SET (HAVE_STRING_H 1) +#SET (HAVE_STRLCPY 0) +#SET (HAVE_STRMODE 0) +#SET (HAVE_STRSEP 1) +#SET (HAVE_SYS_STAT_H 1) +#SET (HAVE_SYS_TYPES_H 1) +#SET (HAVE_UINT64_T 1) +#SET (HAVE_UNISTD_H 1) +SET (MAJOR_IN_MKDEV 0) +SET (MAJOR_IN_SYSMACROS 0) +SET (MAKEDEV_THREE_ARGS 0) +#SET (NEED_BASENAME 0) +#SET (NEED_DIRNAME 0) +#SET (NEED_FNMATCH 1) +#SET (NEED_MAKEDEV 1) +#SET (NEED_SNPRINTF 0) +#SET (NEED_STRDUP 0) +#SET (NEED_STRLCPY 0) +#SET (NEED_STRMODE 1) +#SET (NEED_STRSEP 0) +SET (PACKAGE_BUGREPORT "") +SET (PACKAGE_NAME "\"libtar\"") +SET (PACKAGE_STRING "\"libtar 1.2.11\"") +SET (PACKAGE_TARNAME "\"libtar\"") +SET (PACKAGE_VERSION "\"1.2.11\"") +#SET (STDC_HEADERS 1) +SET (const 0) +#SET (dev_t 0) +#SET (gid_t 0) +#SET (major_t "unsigned int") +#SET (minor_t "unsigned int") +#SET (mode_t 0) +#SET (nlink_t 0) +#SET (off_t 0) +#SET (size_t 0) +#SET (socklen_t 0) +#SET (uid_t 0) +#SET (uint64_t 0) +SET (LISTHASH_PREFIX "libtar") + +CONFIGURE_FILE(${LIBTAR_SOURCE_DIR}/listhash/listhash.h.in + ${LIBTAR_BINARY_DIR}/libtar/libtar_listhash.h @ONLY IMMEDIATE) +CONFIGURE_FILE(${LIBTAR_SOURCE_DIR}/listhash/list.c.in + ${LIBTAR_BINARY_DIR}/listhash/libtar_list.c @ONLY IMMEDIATE) +CONFIGURE_FILE(${LIBTAR_SOURCE_DIR}/listhash/hash.c.in + ${LIBTAR_BINARY_DIR}/listhash/libtar_hash.c @ONLY IMMEDIATE) + +FOREACH(hfile libtar.h tar.h compat/compat.h) + GET_FILENAME_COMPONENT(outname "${hfile}" NAME) + CONFIGURE_FILE(${LIBTAR_SOURCE_DIR}/${hfile} + ${LIBTAR_BINARY_DIR}/libtar/${outname} @ONLY IMMEDIATE) +ENDFOREACH(hfile) + +CONFIGURE_FILE(${LIBTAR_SOURCE_DIR}/internal.h + ${LIBTAR_BINARY_DIR}/libtarint/internal.h @ONLY IMMEDIATE) + +SET(libtar_SRC + append.c + block.c + decode.c + encode.c + extract.c + handle.c + ${LIBTAR_BINARY_DIR}/listhash/libtar_hash.c + ${LIBTAR_BINARY_DIR}/listhash/libtar_list.c + output.c + util.c + wrapper.c + filesystem.c filesystem.h + internal.h + ${LIBTAR_BINARY_DIR}/libtar/config.h + config.h.in + tar.h + libtar.h + compat/compat.h + +# compat/strlcpy.c +# compat/basename.c +# compat/dirname.c +# compat/strmode.c +# compat/strsep.c +) + +IF(NOT HAVE_STRLCPY) +SET(libtar_SRC ${libtar_SRC} compat/strlcpy.c) +SET(NEED_STRLCPY 1) +ENDIF(NOT HAVE_STRLCPY) + +IF(NOT HAVE_STRMODE) +SET(libtar_SRC ${libtar_SRC} compat/strmode.c) +SET(NEED_STRMODE 1) +ENDIF(NOT HAVE_STRMODE) + +IF(WIN32) +IF(NOT HAVE_SNPRINTF) +SET(libtar_SRC ${libtar_SRC} compat/snprintf.c) +SET(NEED_SNPRINTF 1) +ENDIF(NOT HAVE_SNPRINTF) +ENDIF(WIN32) + +IF(NOT HAVE_DIRNAME) +SET(libtar_SRC ${libtar_SRC} compat/dirname.c) +SET(NEED_DIRNAME 1) +ENDIF(NOT HAVE_DIRNAME) + + +IF(NOT HAVE_STRSEP) +SET(libtar_SRC ${libtar_SRC} compat/strsep.c) +SET(NEED_STRSEP 1) +ENDIF(NOT HAVE_STRSEP) + + +IF(NOT HAVE_BASENAME) +SET(libtar_SRC ${libtar_SRC} compat/basename.c) +SET(NEED_BASENAME 1) +ENDIF(NOT HAVE_BASENAME) + +IF(NOT HAVE_FNMATCH) +SET(libtar_SRC ${libtar_SRC} compat/fnmatch.c) +SET(NEED_FNMATCH 1) +ENDIF(NOT HAVE_FNMATCH) + +#IF(NOT HAVE_GLOB) +#SET(libtar_SRC ${libtar_SRC} compat/glob.c) +#SET(NEED_GLOB 1) +#ENDIF(NOT HAVE_GLOB) + + +IF(WIN32) +SET(NEED_MAKEDEV 0) +ELSE(WIN32) +SET(NEED_MAKEDEV 1) +ENDIF(WIN32) + + +CONFIGURE_FILE(${LIBTAR_SOURCE_DIR}/config.h.in + ${LIBTAR_BINARY_DIR}/libtar/config.h) + +ADD_LIBRARY(tar STATIC ${libtar_SRC}) +ADD_EXECUTABLE(tartest libtar.c) +TARGET_LINK_LIBRARIES(tartest tar ${CMAKE_ZLIB_LIBRARIES}) + diff --git a/Utilities/cmtar/COPYRIGHT b/Utilities/cmtar/COPYRIGHT new file mode 100644 index 0000000..2471ec0 --- /dev/null +++ b/Utilities/cmtar/COPYRIGHT @@ -0,0 +1,35 @@ +Copyright (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. + diff --git a/Utilities/cmtar/append.c b/Utilities/cmtar/append.c new file mode 100644 index 0000000..4350745 --- /dev/null +++ b/Utilities/cmtar/append.c @@ -0,0 +1,272 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <libtarint/internal.h> + +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#ifdef _MSC_VER +# include <libtar/compat.h> +#else +# include <sys/param.h> +#endif +#include <libtar/compat.h> +#include <sys/types.h> + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef _MSC_VER +#include <io.h> +#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, char *realname, 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 + +#ifdef WIN32 + if (stat(realname, &s) != 0) +#else + if (lstat(realname, &s) != 0) +#endif + { +#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); + } + +#ifndef WIN32 + /* check if it's a symlink */ + if (TH_ISSYM(t)) + { +#ifdef WIN32 + i = -1; +#else + i = readlink(realname, path, sizeof(path)); +#endif + 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); + } +#endif + /* 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, 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; +} + + diff --git a/Utilities/cmtar/block.c b/Utilities/cmtar/block.c new file mode 100644 index 0000000..f47f7ba --- /dev/null +++ b/Utilities/cmtar/block.c @@ -0,0 +1,384 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <libtarint/internal.h> + +#include <errno.h> + +#ifdef STDC_HEADERS +# include <string.h> +# include <stdlib.h> +#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, j; + size_t sz; + 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); + j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0); +#ifdef DEBUG + printf(" th_read(): GNU long linkname detected " + "(%ld bytes, %d blocks)\n", sz, j); +#endif + t->th_buf.gnu_longlink = (char *)malloc(j * T_BLOCKSIZE); + if (t->th_buf.gnu_longlink == NULL) + return -1; + + for (ptr = t->th_buf.gnu_longlink; j > 0; + j--, ptr += T_BLOCKSIZE) + { +#ifdef DEBUG + printf(" th_read(): reading long linkname " + "(%d blocks left, ptr == %ld)\n", 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); + j = (sz / T_BLOCKSIZE) + (sz % T_BLOCKSIZE ? 1 : 0); +#ifdef DEBUG + printf(" th_read(): GNU long filename detected " + "(%ld bytes, %d blocks)\n", sz, j); +#endif + t->th_buf.gnu_longname = (char *)malloc(j * T_BLOCKSIZE); + if (t->th_buf.gnu_longname == NULL) + return -1; + + for (ptr = t->th_buf.gnu_longname; j > 0; + j--, ptr += T_BLOCKSIZE) + { +#ifdef DEBUG + printf(" th_read(): reading long filename " + "(%d blocks left, ptr == %ld)\n", 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; +} + + diff --git a/Utilities/cmtar/compat/README b/Utilities/cmtar/compat/README new file mode 100644 index 0000000..fd23ced --- /dev/null +++ b/Utilities/cmtar/compat/README @@ -0,0 +1,12 @@ +Compatibility 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. + diff --git a/Utilities/cmtar/compat/basename.c b/Utilities/cmtar/compat/basename.c new file mode 100644 index 0000000..21cc13d --- /dev/null +++ b/Utilities/cmtar/compat/basename.c @@ -0,0 +1,75 @@ +/* $OpenBSD: basename.c,v 1.4 1999/05/30 17:10:30 espie Exp $ */ + +/* + * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> + * 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 <errno.h> +#include <string.h> +//#include <sys/param.h> +#include <compat.h> + +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); +} diff --git a/Utilities/cmtar/compat/compat.h b/Utilities/cmtar/compat/compat.h new file mode 100644 index 0000000..880f54b --- /dev/null +++ b/Utilities/cmtar/compat/compat.h @@ -0,0 +1,314 @@ +/* prototypes for borrowed "compatibility" code */ + +#include <libtar/config.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef STDC_HEADERS +# include <stdarg.h> +# include <stddef.h> +#else +# include <varargs.h> +#endif + +#ifdef HAVE_LIBGEN_H +# include <libgen.h> +#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 /<tail> 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 <fnmatch.h> +# endif + +# endif /* ! HAVE_FNMATCH */ +#endif /* NEED_FNMATCH */ + + +#ifdef NEED_GETHOSTBYNAME_R + +# include <netdb.h> + +# 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 <netdb.h> + +# 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 <glob.h> +# 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 <sys/mkdev.h> +# else +# ifdef MAJOR_IN_SYSMACROS +# include <sys/sysmacros.h> +# 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 */ + +#ifdef _MSC_VER //compile snprintf only onwin32 +//#if defined(NEED_SNPRINTF) && !defined(HAVE_SNPRINTF) +#if !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 */ +#endif + +#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 */ + +#ifdef _MSC_VER +#include <stdlib.h> +#define MAXPATHLEN _MAX_PATH +#ifndef O_ACCMODE +# define O_ACCMODE 0x0003 +#endif +#endif + + + + +#ifndef S_ISREG +#ifndef S_IFREG +#ifndef _S_IFREG +#define S_IFREG (-1) +#else +#define S_IFREG _S_IFREG +#endif +#endif +#define S_ISREG(m) (((m)&S_IFREG)==S_IFREG) +#endif + + +#ifndef S_ISDIR +#ifndef S_IFDIR +#ifndef _S_IFDIR +#define S_IFDIR (-1) +#else +#define S_IFDIR _S_IFDIR +#endif +#endif +#define S_ISDIR(m) (((m)&S_IFDIR)==S_IFDIR) +#endif + +#ifndef S_ISBLK +#ifndef S_IFBLK +#ifndef _S_IFBLK +#define S_IFBLK (-1) +#else +#define S_IFBLK _S_IFBLK +#endif +#endif +#define S_ISBLK(m) (((m)&S_IFBLK)==S_IFBLK) +#endif + +#ifndef S_ISFIFO +#ifndef S_IFFIFO +#ifndef _S_IFFIFO +#define S_IFFIFO (-1) +#else +#define S_IFFIFO _S_IFFIFO +#endif +#endif +#define S_ISFIFO(m) (((m)&S_IFFIFO)==S_IFFIFO) +#endif diff --git a/Utilities/cmtar/compat/dirname.c b/Utilities/cmtar/compat/dirname.c new file mode 100644 index 0000000..63455a9 --- /dev/null +++ b/Utilities/cmtar/compat/dirname.c @@ -0,0 +1,78 @@ +/* $OpenBSD: dirname.c,v 1.4 1999/05/30 17:10:30 espie Exp $ */ + +/* + * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> + * 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 <errno.h> +#include <string.h> +//#include <sys/param.h> +#include <compat.h> + +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); +} diff --git a/Utilities/cmtar/compat/fnmatch.c b/Utilities/cmtar/compat/fnmatch.c new file mode 100644 index 0000000..f1c5da1 --- /dev/null +++ b/Utilities/cmtar/compat/fnmatch.c @@ -0,0 +1,237 @@ +/* $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 <config.h> + +#include <stdio.h> + +#ifdef STDC_HEADERS +# include <string.h> +#endif + +#ifdef HAVE_CTYPE_H +# include <ctype.h> +#endif + +#include <compat.h> + + +#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); +} diff --git a/Utilities/cmtar/compat/gethostbyname_r.c b/Utilities/cmtar/compat/gethostbyname_r.c new file mode 100644 index 0000000..1b88bad --- /dev/null +++ b/Utilities/cmtar/compat/gethostbyname_r.c @@ -0,0 +1,41 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <config.h> + +#include <stdio.h> +#include <sys/types.h> +#include <netdb.h> + + +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 */ +} + + diff --git a/Utilities/cmtar/compat/gethostname.c b/Utilities/cmtar/compat/gethostname.c new file mode 100644 index 0000000..1abaae1 --- /dev/null +++ b/Utilities/cmtar/compat/gethostname.c @@ -0,0 +1,36 @@ +/* gethostname.c: minimal substitute for missing gethostname() function + * created 2000-Mar-02 jmk + * requires SVR4 uname() and -lc + * + * by Jim Knoble <jmknoble@pobox.com> + * 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 <string.h> +#include <sys/utsname.h> + +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); +} + diff --git a/Utilities/cmtar/compat/getservbyname_r.c b/Utilities/cmtar/compat/getservbyname_r.c new file mode 100644 index 0000000..3afedf0 --- /dev/null +++ b/Utilities/cmtar/compat/getservbyname_r.c @@ -0,0 +1,41 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <config.h> + +#include <stdio.h> +#include <sys/types.h> +#include <netdb.h> + + +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 */ +} + + diff --git a/Utilities/cmtar/compat/glob.c b/Utilities/cmtar/compat/glob.c new file mode 100644 index 0000000..939d76f --- /dev/null +++ b/Utilities/cmtar/compat/glob.c @@ -0,0 +1,874 @@ +/* + * 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 <config.h> + +//#include <sys/param.h> +#include <compat.h> +#include <sys/stat.h> + +//#include <dirent.h> +#include <errno.h> +#include <pwd.h> +#include <stdio.h> + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include <compat.h> + + +#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 diff --git a/Utilities/cmtar/compat/inet_aton.c b/Utilities/cmtar/compat/inet_aton.c new file mode 100644 index 0000000..cc1e507 --- /dev/null +++ b/Utilities/cmtar/compat/inet_aton.c @@ -0,0 +1,27 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + + +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; +} + + diff --git a/Utilities/cmtar/compat/snprintf.c b/Utilities/cmtar/compat/snprintf.c new file mode 100644 index 0000000..a6d8c05 --- /dev/null +++ b/Utilities/cmtar/compat/snprintf.c @@ -0,0 +1,788 @@ +/************************************************************** + * 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 <blong@fiction.net> 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 <blong@fiction.net> 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 <roessler@guug.de> 01/27/98 for mutt 0.89i + * The PGP code was using unsigned hexadecimal formats. + * Unfortunately, unsigned formats simply didn't work. + * + * Michael Elkins <me@cs.hmc.edu> 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. + * + **************************************************************/ + +#include <config.h> + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) + +#include <string.h> +# include <ctype.h> +#include <sys/types.h> + +/* Define this as a fall through, HAVE_STDARG_H is probably already set */ + +#define HAVE_VARARGS_H + +/* varargs declarations: */ + +#if defined(HAVE_STDARG_H) +# include <stdarg.h> +# define HAVE_STDARGS /* let's hope that works everywhere (mj) */ +# 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) +#else +# if defined(HAVE_VARARGS_H) +# include <varargs.h> +# undef HAVE_STDARGS +# define VA_LOCAL_DECL va_list ap +# define VA_START(f) va_start(ap) /* f is ignored! */ +# define VA_SHIFT(v,t) v = va_arg(ap,t) +# define VA_END va_end(ap) +# else +/*XX ** NO VARARGS ** XX*/ +# endif +#endif + +/*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, short 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 short 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 short 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 short 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 = "<NULL>"; + } + + 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 +/* VARARGS3 */ +#ifdef HAVE_STDARGS +int mutt_snprintf (char *str,size_t count,const char *fmt,...) +#else +int mutt_snprintf (va_alist) va_dcl +#endif +{ +#ifndef HAVE_STDARGS + char *str; + size_t count; + char *fmt; +#endif + 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 */ diff --git a/Utilities/cmtar/compat/strdup.c b/Utilities/cmtar/compat/strdup.c new file mode 100644 index 0000000..9dabf37 --- /dev/null +++ b/Utilities/cmtar/compat/strdup.c @@ -0,0 +1,62 @@ +/* $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 <sys/types.h> + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +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); +} diff --git a/Utilities/cmtar/compat/strlcat.c b/Utilities/cmtar/compat/strlcat.c new file mode 100644 index 0000000..e8945c1 --- /dev/null +++ b/Utilities/cmtar/compat/strlcat.c @@ -0,0 +1,72 @@ +/* $OpenBSD: strlcat.c,v 1.5 2001/01/13 16:17:24 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * 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 <sys/types.h> +#include <string.h> + +/* + * 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 */ +} diff --git a/Utilities/cmtar/compat/strlcpy.c b/Utilities/cmtar/compat/strlcpy.c new file mode 100644 index 0000000..f85c71b --- /dev/null +++ b/Utilities/cmtar/compat/strlcpy.c @@ -0,0 +1,68 @@ +/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * 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 <sys/types.h> +#include <string.h> + +/* + * 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 */ +} diff --git a/Utilities/cmtar/compat/strmode.c b/Utilities/cmtar/compat/strmode.c new file mode 100644 index 0000000..832b0e7 --- /dev/null +++ b/Utilities/cmtar/compat/strmode.c @@ -0,0 +1,185 @@ +/*- + * 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 <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <libtar/compat.h> + +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; +#ifdef S_IFLNK + case S_IFLNK: /* symbolic link */ + *p++ = 'l'; + break; +#endif +#ifdef S_IFSOCK + case S_IFSOCK: /* socket */ + *p++ = 's'; + break; +#endif +#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 */ +#ifdef S_IRUSR + if (mode & S_IRUSR) + *p++ = 'r'; + else +#endif + *p++ = '-'; + +#ifdef S_IWUSR + if (mode & S_IWUSR) + *p++ = 'w'; + else +#endif + *p++ = '-'; + +#ifndef _MSC_VER +#ifdef S_ISUID + switch (mode & (S_IXUSR | S_ISUID)) { +#else + switch (mode & (S_IXUSR)) { +#endif + case 0: + *p++ = '-'; + break; + case S_IXUSR: + *p++ = 'x'; + break; +#ifdef S_ISUID + case S_ISUID: + *p++ = 'S'; + break; + case S_IXUSR | S_ISUID: + *p++ = 's'; + break; +#endif + } +#endif + /* group */ +#ifdef S_IRGRP + if (mode & S_IRGRP) + *p++ = 'r'; + else +#endif + *p++ = '-'; +#ifdef S_IWGRP + if (mode & S_IWGRP) + *p++ = 'w'; + else +#endif + *p++ = '-'; +#if defined(S_IXGRP) && defined(S_ISGID) + 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; + } +#else + *p++ = '-'; +#endif +#ifndef WIN32 + /* 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; + } +#else + *p++ = '-'; + *p++ = '-'; + *p++ = '-'; +#endif + *p++ = ' '; /* will be a '+' if ACL's implemented */ + *p = '\0'; +} diff --git a/Utilities/cmtar/compat/strrstr.c b/Utilities/cmtar/compat/strrstr.c new file mode 100644 index 0000000..8b7f299 --- /dev/null +++ b/Utilities/cmtar/compat/strrstr.c @@ -0,0 +1,40 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <stdio.h> +#include <sys/types.h> + +#include <string.h> + + +/* +** 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; +} + + diff --git a/Utilities/cmtar/compat/strsep.c b/Utilities/cmtar/compat/strsep.c new file mode 100644 index 0000000..9d036a9 --- /dev/null +++ b/Utilities/cmtar/compat/strsep.c @@ -0,0 +1,87 @@ +/* $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 <string.h> +#include <stdio.h> + +#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 */ diff --git a/Utilities/cmtar/config.h.in b/Utilities/cmtar/config.h.in new file mode 100644 index 0000000..eba0ed3 --- /dev/null +++ b/Utilities/cmtar/config.h.in @@ -0,0 +1,190 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if your system has a working basename */ +#cmakedefine HAVE_BASENAME @HAVE_BASENAME@ + +/* Define to 1 if you have the <ctype.h> header file. */ +#cmakedefine HAVE_CTYPE_H @HAVE_CTYPE_H@ + +/* Define to 1 if the system has the type `dev_t'. */ +#cmakedefine HAVE_DEV_T @HAVE_DEV_T@ + +/* Define if your system has a working dirname */ +#cmakedefine HAVE_DIRNAME @HAVE_DIRNAME@ + +/* Define to 1 if your system has a working POSIX `fnmatch' function. */ +#cmakedefine HAVE_FNMATCH @HAVE_FNMATCH@ + +/* Define to 1 if you have the <fnmatch.h> header file. */ +#cmakedefine HAVE_FNMATCH_H @HAVE_FNMATCH_H@ + +/* Define to 1 if you have the <inttypes.h> header file. */ +#cmakedefine HAVE_INTTYPES_H @HAVE_INTTYPES_H@ + +/* Define to 1 if you have the `lchown' function. */ +#cmakedefine HAVE_LCHOWN @HAVE_LCHOWN@ + +/* Define to 1 if you have the <libgen.h> header file. */ +#cmakedefine HAVE_LIBGEN_H @HAVE_LIBGEN_H@ + +/* Define to 1 if you have the `z' library (-lz). */ +#cmakedefine HAVE_LIBZ @HAVE_LIBZ@ + +/* Define to 1 if the system has the type `major_t'. */ +#cmakedefine HAVE_MAJOR_T @HAVE_MAJOR_T@ + +/* Define to 1 if you have the <memory.h> header file. */ +#cmakedefine HAVE_MEMORY_H @HAVE_MEMORY_H@ + +/* Define to 1 if the system has the type `minor_t'. */ +#cmakedefine HAVE_MINOR_T @HAVE_MINOR_T@ + +/* Define to 1 if the system has the type `nlink_t'. */ +#cmakedefine HAVE_NLINK_T @HAVE_NLINK_T@ + +/* Define if your system has a working snprintf */ +#cmakedefine HAVE_SNPRINTF @HAVE_SNPRINTF@ + +/* Define to 1 if the system has the type `socklen_t'. */ +#cmakedefine HAVE_SOCKLEN_T @HAVE_SOCKLEN_T@ + +/* Define to 1 if you have the <stdint.h> header file. */ +#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@ + +/* Define to 1 if you have the <stdlib.h> header file. */ +#cmakedefine HAVE_STDLIB_H @HAVE_STDLIB_H@ + +/* Define if you have the strdup function */ +#cmakedefine HAVE_STRDUP @HAVE_STRDUP@ + +/* Define to 1 if you have the `strftime' function. */ +#cmakedefine HAVE_STRFTIME @HAVE_STRFTIME@ + +/* Define to 1 if you have the <strings.h> header file. */ +#cmakedefine HAVE_STRINGS_H @HAVE_STRINGS_H@ + +/* Define to 1 if you have the <string.h> header file. */ +#cmakedefine HAVE_STRING_H @HAVE_STRING_H@ + +/* Define if you have the strlcpy function */ +#cmakedefine HAVE_STRLCPY @HAVE_STRLCPY@ + +/* Define if you have the strmode function */ +#cmakedefine HAVE_STRMODE @HAVE_STRMODE@ + +/* Define if you have the strsep function */ +#cmakedefine HAVE_STRSEP @HAVE_STRSEP@ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#cmakedefine HAVE_SYS_STAT_H @HAVE_SYS_STAT_H@ + +/* Define to 1 if you have the <sys/types.h> header file. */ +#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@ + +/* Define to 1 if the system has the type `uint64_t'. */ +#cmakedefine HAVE_UINT64_T @HAVE_UINT64_T@ + +/* Define to 1 if you have the <unistd.h> header file. */ +#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@ + +/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>. + */ +#cmakedefine MAJOR_IN_MKDEV @MAJOR_IN_MKDEV@ + +/* Define to 1 if `major', `minor', and `makedev' are declared in + <sysmacros.h>. */ +#cmakedefine MAJOR_IN_SYSMACROS @MAJOR_IN_SYSMACROS@ + +/* Define as 1 if makedev expects three arguments */ +#cmakedefine MAKEDEV_THREE_ARGS @MAKEDEV_THREE_ARGS@ + +/* Define if you want to use the basename function */ +#cmakedefine NEED_BASENAME @NEED_BASENAME@ + +/* Define if you want to use the dirname function */ +#cmakedefine NEED_DIRNAME @NEED_DIRNAME@ + +/* Define if you want to use the fnmatch function */ +#cmakedefine NEED_FNMATCH @NEED_FNMATCH@ + +/* Define if you want to use the makedev function */ +#cmakedefine NEED_MAKEDEV @NEED_MAKEDEV@ + +/* Define if you want to use the snprintf function */ +#cmakedefine NEED_SNPRINTF @NEED_SNPRINTF@ + +/* Define if you want to use the strdup function */ +#cmakedefine NEED_STRDUP @NEED_STRDUP@ + +/* Define if you want to use the strlcpy function */ +#cmakedefine NEED_STRLCPY @NEED_STRLCPY@ + +/* Define if you want to use the strmode function */ +#cmakedefine NEED_STRMODE @NEED_STRMODE@ + +/* Define if you want to use the strsep function */ +#cmakedefine NEED_STRSEP @NEED_STRSEP@ + +/* Define to the address where bug reports for this package should be sent. */ +#cmakedefine PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@ + +/* Define to the full name of this package. */ +#cmakedefine PACKAGE_NAME @PACKAGE_NAME@ + +/* Define to the full name and version of this package. */ +#cmakedefine PACKAGE_STRING @PACKAGE_STRING@ + +/* Define to the one symbol short name of this package. */ +#cmakedefine PACKAGE_TARNAME @PACKAGE_TARNAME@ + +/* Define to the version of this package. */ +#cmakedefine PACKAGE_VERSION @PACKAGE_VERSION@ + +/* Define to 1 if you have the ANSI C header files. */ +#cmakedefine STDC_HEADERS @STDC_HEADERS@ + +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +#cmakedefine _ALL_SOURCE @_ALL_SOURCE@ +#endif + +/* Define to empty if `const' does not conform to ANSI C. */ +#cmakedefine const @const@ + +/* Define to `unsigned long' if not defined in system header files. */ +#cmakedefine dev_t @dev_t@ + +/* Define to `int' if <sys/types.h> doesn't define. */ +#cmakedefine gid_t @gid_t@ + +/* Define to `unsigned int' if not defined in system header files. */ +#cmakedefine major_t @major_t@ + +/* Define to `unsigned int' if not defined in system header files. */ +#cmakedefine minor_t @minor_t@ + +/* Define to `int' if <sys/types.h> does not define. */ +#cmakedefine mode_t @mode_t@ + +/* Define to `unsigned short' if not defined in system header files. */ +#cmakedefine nlink_t @nlink_t@ + +/* Define to `long' if <sys/types.h> does not define. */ +#cmakedefine off_t @off_t@ + +/* Define to `unsigned' if <sys/types.h> does not define. */ +#cmakedefine size_t @size_t@ + +/* Define to `int' if <sys/types.h> does not define. */ +#cmakedefine ssize_t @size_t@ + +/* Define to `unsigned long' if not defined in system header files. */ +#cmakedefine socklen_t @socklen_t@ + +/* Define to `int' if <sys/types.h> doesn't define. */ +#cmakedefine uid_t @uid_t@ + +/* Define to `long long' if not defined in system header files. */ +#cmakedefine uint64_t @uint64_t@ diff --git a/Utilities/cmtar/decode.c b/Utilities/cmtar/decode.c new file mode 100644 index 0000000..39077de --- /dev/null +++ b/Utilities/cmtar/decode.c @@ -0,0 +1,136 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <libtarint/internal.h> + +#include <stdio.h> + +#ifndef _MSC_VER +#include <sys/param.h> +#else +#include <compat.h> +#endif + +#ifndef WIN32 +#include <pwd.h> +#include <grp.h> +#endif + +#ifdef STDC_HEADERS +# include <string.h> +#endif + + +/* determine full path name */ +char * +th_get_pathname(TAR *t) +{ + 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 strdup(filename); + } + + snprintf(filename, sizeof(filename), "%.100s", t->th_buf.name); + return strdup(filename); +} + + +uid_t +th_get_uid(TAR *t) +{ + int uid; +#ifndef WIN32 + struct passwd *pw; + + pw = getpwnam(t->th_buf.uname); + if (pw != NULL) + return pw->pw_uid; + + /* if the password entry doesn't exist */ +#endif + sscanf(t->th_buf.uid, "%o", &uid); + return uid; +} + + +gid_t +th_get_gid(TAR *t) +{ + int gid; +#ifndef WIN32 + struct group *gr; + + gr = getgrnam(t->th_buf.gname); + if (gr != NULL) + return gr->gr_gid; + + /* if the group entry doesn't exist */ +#endif + 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) + { +#ifndef WIN32 + case SYMTYPE: + mode |= S_IFLNK; + break; +#endif + case CHRTYPE: + mode |= S_IFCHR; + break; + case BLKTYPE: + mode |= S_IFBLK; + break; + case DIRTYPE: + mode |= S_IFDIR; + break; +#ifndef WIN32 + case FIFOTYPE: + mode |= S_IFIFO; + break; +#endif + 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; +} + + diff --git a/Utilities/cmtar/encode.c b/Utilities/cmtar/encode.c new file mode 100644 index 0000000..cadac67 --- /dev/null +++ b/Utilities/cmtar/encode.c @@ -0,0 +1,234 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <libtarint/internal.h> + +#include <stdio.h> +#ifndef WIN32 +#include <pwd.h> +#include <grp.h> +#endif +#include <sys/types.h> + +#ifdef STDC_HEADERS +# include <string.h> +# include <stdlib.h> +#endif + + +/* magic, version, and checksum */ +void +th_finish(TAR *t) +{ + int i, sum = 0; + + if (t->options & TAR_GNU) + strncpy(t->th_buf.magic, "ustar ", 8); + else + { + strncpy(t->th_buf.version, TVERSION, TVERSLEN); + strncpy(t->th_buf.magic, TMAGIC, TMAGLEN); + } + + for (i = 0; i < T_BLOCKSIZE; i++) + sum += ((char *)(&(t->th_buf)))[i]; + for (i = 0; i < 8; i++) + sum += (' ' - t->th_buf.chksum[i]); + int_to_oct(sum, t->th_buf.chksum, 8); +} + + +/* map a file mode to a typeflag */ +void +th_set_type(TAR *t, mode_t mode) +{ +#ifdef S_ISLNK + if (S_ISLNK(mode)) + t->th_buf.typeflag = SYMTYPE; +#endif + if (S_ISREG(mode)) + t->th_buf.typeflag = REGTYPE; + if (S_ISDIR(mode)) + t->th_buf.typeflag = DIRTYPE; +#ifdef S_ISCHR + if (S_ISCHR(mode)) + t->th_buf.typeflag = CHRTYPE; +#endif + if (S_ISBLK(mode)) + t->th_buf.typeflag = BLKTYPE; + if (S_ISFIFO(mode) +#ifdef S_ISSOCK + || S_ISSOCK(mode)) +#else + ) +#endif + t->th_buf.typeflag = FIFOTYPE; +} + + +/* encode file path */ +void +th_set_path(TAR *t, 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 && (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, char *linkname) +{ +#ifdef DEBUG + printf("==> th_set_link(th, linkname=\"%s\")\n", linkname); +#endif + + if (strlen(linkname) > T_NAMELEN && (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 +#ifndef major +# define major(dev) ((int)(((dev) >> 8) & 0xff)) +#endif +#ifndef minor +# define minor(dev) ((int)((dev) & 0xff)) +#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) +{ +#ifndef WIN32 + struct passwd *pw; + + pw = getpwuid(uid); + if (pw != NULL) + strlcpy(t->th_buf.uname, pw->pw_name, sizeof(t->th_buf.uname)); +#endif + int_to_oct(uid, t->th_buf.uid, 8); +} + + +/* encode group info */ +void +th_set_group(TAR *t, gid_t gid) +{ +#ifndef WIN32 + struct group *gr; + + gr = getgrgid(gid); + if (gr != NULL) + strlcpy(t->th_buf.gname, gr->gr_name, sizeof(t->th_buf.gname)); +#endif + int_to_oct(gid, t->th_buf.gid, 8); +} + + +/* encode file mode */ +void +th_set_mode(TAR *t, mode_t fmode) +{ +#ifndef WIN32 + if (S_ISSOCK(fmode)) + { + fmode &= ~S_IFSOCK; + fmode |= S_IFIFO; + } +#endif + 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); +#ifndef WIN32 + if (S_ISCHR(s->st_mode) || S_ISBLK(s->st_mode)) + th_set_device(t, s->st_rdev); +#endif + 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); +} + + diff --git a/Utilities/cmtar/extract.c b/Utilities/cmtar/extract.c new file mode 100644 index 0000000..4314325 --- /dev/null +++ b/Utilities/cmtar/extract.c @@ -0,0 +1,561 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <libtarint/internal.h> + +#include <stdio.h> +#include <libtar/compat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <errno.h> +#ifdef _MSC_VER +#include <sys/utime.h> +#include <io.h> +#include <direct.h> +#else +#include <utime.h> +#include <sys/param.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + + +struct linkname +{ + char ln_save[MAXPATHLEN]; + char ln_real[MAXPATHLEN]; +}; +typedef struct linkname linkname_t; + + +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 */ +#ifndef WIN32 + 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; + } + +#endif /* WIN32 */ + + return 0; +} + + +/* switchboard */ +int +tar_extract_file(TAR *t, char *realname) +{ + int i; + linkname_t *lnp; + + if (t->options & TAR_NOOVERWRITE) + { + struct stat s; + +#ifdef WIN32 + if (stat(realname, &s) == 0 || errno != ENOENT) +#else + if (lstat(realname, &s) == 0 || errno != ENOENT) +#endif + { + errno = EEXIST; + return -1; + } + } + + if (TH_ISDIR(t)) + { + i = tar_extract_dir(t, realname); + if (i == 1) + i = 0; + } +#ifndef _WIN32 + 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); +#endif + 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; + + lnp = (linkname_t *)calloc(1, sizeof(linkname_t)); + if (lnp == NULL) + return -1; + strlcpy(lnp->ln_save, th_get_pathname(t), sizeof(lnp->ln_save)); + strlcpy(lnp->ln_real, realname, sizeof(lnp->ln_real)); +#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; + linkname_t *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 = (linkname_t *)libtar_hashptr_data(&hp); + linktgt = lnp->ln_real; + } + else + linktgt = th_get_linkname(t); + +#ifdef DEBUG + printf(" ==> extracting: %s (link to %s)\n", filename, linktgt); +#endif +#ifndef WIN32 + if (link(linktgt, filename) == -1) +#endif + { +#ifdef DEBUG + perror("link()"); +#endif + return -1; + } + + return 0; +} + + +/* symlink */ +int +tar_extract_symlink(TAR *t, char *realname) +{ + char *filename; + +#ifndef _WIN32 + if (!TH_ISSYM(t)) + { + errno = EINVAL; + return -1; + } +#endif + + 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 +#ifndef WIN32 + if (symlink(th_get_linkname(t), filename) == -1) +#endif + { +#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; + +#ifndef _WIN32 + if (!TH_ISCHR(t)) + { + errno = EINVAL; + return -1; + } +#endif + 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 +#ifndef WIN32 + if (mknod(filename, mode | S_IFCHR, + compat_makedev(devmaj, devmin)) == -1) +#endif + { +#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 +#ifndef WIN32 + if (mknod(filename, mode | S_IFBLK, + compat_makedev(devmaj, devmin)) == -1) +#endif + { +#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 +#ifdef WIN32 + if (mkdir(filename) == -1) +#else + if (mkdir(filename, mode) == -1) +#endif + { + 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 +#ifndef WIN32 + if (mkfifo(filename, mode) == -1) +#endif + { +#ifdef DEBUG + perror("mkfifo()"); +#endif + return -1; + } + + return 0; +} + + diff --git a/Utilities/cmtar/filesystem.c b/Utilities/cmtar/filesystem.c new file mode 100644 index 0000000..cc4f912 --- /dev/null +++ b/Utilities/cmtar/filesystem.c @@ -0,0 +1,82 @@ + + + +// First microsoft compilers + +#ifdef _MSC_VER +#include <windows.h> +#include <io.h> +#include <ctype.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <filesystem.h> + + +kwDirectory * kwOpenDir(const char* name) +{ +// struct _KWDIR ssss; + char* buf; + size_t n = strlen(name); + kwDirectory * dir = (kwDirectory *)malloc(sizeof (kwDirectory)); + if(dir==NULL) + { + return NULL; + } + dir->EOD=0; //not the end of directory + if ( name[n - 1] == '/' ) + { + buf = (char*) malloc(n + 1 + 1); +// buf = new char[n + 1 + 1]; + sprintf(buf, "%s*", name); + } + else + { + buf = (char*)malloc(n + 2 + 1); +// buf = new char[n + 2 + 1]; + sprintf(buf, "%s/*", name); + } + + // Now put them into the file array + dir->SrchHandle = _findfirst(buf, &dir->Entry); + free(buf); + + if ( dir->SrchHandle == -1 ) + { + free(dir); + return NULL; + } + return dir; +} + +kwDirEntry * kwReadDir(kwDirectory * dir) +{ + kwDirEntry * entry; + if(!dir || dir->EOD ==1) + { + return NULL; + } + entry = (kwDirEntry*)malloc(sizeof(kwDirEntry)); + strncpy(entry->d_name,dir->Entry.name,MAXPATHLEN-1); + if(_findnext(dir->SrchHandle, &dir->Entry) == -1) + { + dir->EOD=1; + } + return entry; +} +int kwCloseDir(kwDirectory * dir) +{ + int r=-1; + if(dir) + { + r=_findclose(dir->SrchHandle); + free(dir); + } + if(r==-1) return 0; + return 1; +} +#endif diff --git a/Utilities/cmtar/filesystem.h b/Utilities/cmtar/filesystem.h new file mode 100644 index 0000000..f2ee202 --- /dev/null +++ b/Utilities/cmtar/filesystem.h @@ -0,0 +1,35 @@ +#ifndef _FILESYSTEM_H_ +#define _FILESYSTEM_H_ + +#ifdef _MSC_VER +#include <io.h> + +struct _KWDIR +{ +#if _MSC_VER < 1300 + long SrchHandle; +#else + intptr_t SrchHandle; +#endif + struct _finddata_t Entry; // data of current file + int EOD; //end of directory + +}; +#ifndef MAXPATHLEN +#define MAXPATHLEN _MAX_PATH +#endif +typedef struct _KWDIRENTRY +{ + char d_name[MAXPATHLEN]; +}kwDirEntry; + +typedef struct _KWDIR kwDirectory; +kwDirectory * kwOpenDir(const char* name); +kwDirEntry * kwReadDir(kwDirectory * dir); +int kwCloseDir(kwDirectory * dir); +#else + +#endif //MSC + + +#endif diff --git a/Utilities/cmtar/handle.c b/Utilities/cmtar/handle.c new file mode 100644 index 0000000..1fe053e --- /dev/null +++ b/Utilities/cmtar/handle.c @@ -0,0 +1,136 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <libtarint/internal.h> + +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef STDC_HEADERS +# include <stdlib.h> +#endif + +#ifdef _MSC_VER +#include <io.h> +//Yogi: hack. this should work on windows where there is no O_ACCMODE defined +#ifndef O_ACCMODE +# define O_ACCMODE 0x0003 +#endif +#endif + +const char libtar_version[] = PACKAGE_VERSION; + +static tartype_t default_type = { open, close, read, write }; + + +static int +tar_init(TAR **t, 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, 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, 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; +} + + diff --git a/Utilities/cmtar/internal.h b/Utilities/cmtar/internal.h new file mode 100644 index 0000000..434fbb0 --- /dev/null +++ b/Utilities/cmtar/internal.h @@ -0,0 +1,17 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <libtar/config.h> +#include <libtar/compat.h> + +#include <libtar/libtar.h> + diff --git a/Utilities/cmtar/libtar.c b/Utilities/cmtar/libtar.c new file mode 100644 index 0000000..1068959 --- /dev/null +++ b/Utilities/cmtar/libtar.c @@ -0,0 +1,377 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ +#include <libtar/config.h> +#include <libtar/libtar.h> + +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#ifdef _MSC_VER +#include <libtar/compat.h> +#include <io.h> +#else +#include <sys/param.h> +#endif + +#ifdef STDC_HEADERS +# include <string.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef DEBUG +# include <signal.h> +#endif + +#ifdef HAVE_LIBZ +# include <cmzlib/zlib.h> +#endif + +#include <libtar/compat.h> + + +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; + +#ifndef _MSC_VER + if ((oflags & O_CREAT) && fchmod(fd, mode)) + return -1; +#endif + + gzf = gzdopen(fd, gzoflags); + if (!gzf) + { + errno = ENOMEM; + return -1; + } + + 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; +#ifdef _WIN32 + int optind; +#endif + progname = basename(argv[0]); + +#ifndef _WIN32 + while ((c = getopt(argc, argv, "cC:gtvVxz")) != -1) + switch (c) + { + case 'V': + printf("libtar %s by Mark D. Roth <roth@uiuc.edu>\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(); + } + +#else + mode = MODE_EXTRACT; + use_zlib=1; + optind = 1; +#endif + +#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; +} + + diff --git a/Utilities/cmtar/libtar.h b/Utilities/cmtar/libtar.h new file mode 100644 index 0000000..ef822ea --- /dev/null +++ b/Utilities/cmtar/libtar.h @@ -0,0 +1,295 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#ifndef LIBTAR_H +#define LIBTAR_H + +#include <sys/types.h> +#include <sys/stat.h> +#include <libtar/tar.h> + +#include <libtar/libtar_listhash.h> +#include <libtar/compat.h> +#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, 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, 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, char *realname, char *savename); + +/* write EOF indicator */ +int tar_append_eof(TAR *t); + +/* add file contents to a tarchive */ +int tar_append_regfile(TAR *t, 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, char *pathname); +void th_set_link(TAR *t, 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); +#define th_crc_ok(t) (th_get_crc(t) == th_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 */ + diff --git a/Utilities/cmtar/listhash/hash.c.in b/Utilities/cmtar/listhash/hash.c.in new file mode 100644 index 0000000..41a1618 --- /dev/null +++ b/Utilities/cmtar/listhash/hash.c.in @@ -0,0 +1,344 @@ +/* @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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <@LISTHASH_PREFIX@/config.h> +#include <@LISTHASH_PREFIX@/compat.h> + +#include <@LISTHASH_PREFIX@/@LISTHASH_PREFIX@_listhash.h> + +#include <stdio.h> +#include <errno.h> + +#ifdef STDC_HEADERS +# include <stdlib.h> +#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; +} + + diff --git a/Utilities/cmtar/listhash/list.c.in b/Utilities/cmtar/listhash/list.c.in new file mode 100644 index 0000000..71c5bf6 --- /dev/null +++ b/Utilities/cmtar/listhash/list.c.in @@ -0,0 +1,457 @@ +/* @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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <@LISTHASH_PREFIX@/config.h> +#include <@LISTHASH_PREFIX@/compat.h> + +#include <@LISTHASH_PREFIX@/@LISTHASH_PREFIX@_listhash.h> + +#include <stdio.h> +#include <errno.h> + +#ifdef STDC_HEADERS +# include <string.h> +# include <stdlib.h> +#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; +} + + diff --git a/Utilities/cmtar/listhash/listhash.h.in b/Utilities/cmtar/listhash/listhash.h.in new file mode 100644 index 0000000..4ab5fdf --- /dev/null +++ b/Utilities/cmtar/listhash/listhash.h.in @@ -0,0 +1,196 @@ +/* @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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#ifndef @LISTHASH_PREFIX@_LISTHASH_H +#define @LISTHASH_PREFIX@_LISTHASH_H + + +/***** 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 *); + +#endif /* ! @LISTHASH_PREFIX@_LISTHASH_H */ + diff --git a/Utilities/cmtar/output.c b/Utilities/cmtar/output.c new file mode 100644 index 0000000..5bd69c7 --- /dev/null +++ b/Utilities/cmtar/output.c @@ -0,0 +1,145 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <libtarint/internal.h> + +#include <stdio.h> +#ifndef WIN32 +#include <pwd.h> +#include <grp.h> +#endif +#include <time.h> +#include <limits.h> +//#include <sys/param.h> + +#ifdef STDC_HEADERS +# include <string.h> +#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]; +#ifndef WIN32 + struct passwd *pw; + struct group *gr; +#endif + 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); +#ifndef WIN32 + pw = getpwuid(uid); + if (pw != NULL) + strlcpy(username, pw->pw_name, sizeof(username)); + else +#endif + snprintf(username, sizeof(username), "%d", uid); + gid = th_get_gid(t); +#ifndef WIN32 + gr = getgrgid(gid); + if (gr != NULL) + strlcpy(groupname, gr->gr_name, sizeof(groupname)); + else +#endif + snprintf(groupname, sizeof(groupname), "%d", gid); + + strmode(th_get_mode(t), modestring); + printf("%.10s %-8.8s %-8.8s ", modestring, username, groupname); + +#ifndef WIN32 + 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)); +#endif + + 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)); + +#ifndef _WIN32 + 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); + } +#endif + + putchar('\n'); +} + + diff --git a/Utilities/cmtar/tar.h b/Utilities/cmtar/tar.h new file mode 100644 index 0000000..da11c14 --- /dev/null +++ b/Utilities/cmtar/tar.h @@ -0,0 +1,71 @@ +/* $NetBSD: tar.h,v 1.4 2003/08/07 09:44:11 agc Exp $ */ + +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chuck Karish of Mindcraft, Inc. + * + * 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. 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. + * + * @(#)tar.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _TAR_H +#define _TAR_H + +#define TMAGIC "ustar" /* ustar and a null */ +#define TMAGLEN 6 +#define TVERSION "00" /* 00 and no null */ +#define TVERSLEN 2 + +/* Values used in typeflag field */ +#define REGTYPE '0' /* Regular file */ +#define AREGTYPE '\0' /* Regular file */ +#define LNKTYPE '1' /* Link */ +#define SYMTYPE '2' /* Reserved */ +#define CHRTYPE '3' /* Character special */ +#define BLKTYPE '4' /* Block special */ +#define DIRTYPE '5' /* Directory */ +#define FIFOTYPE '6' /* FIFO special */ +#define CONTTYPE '7' /* Reserved */ + +/* Bits used in the mode field - values in octal */ +#define TSUID 04000 /* Set UID on execution */ +#define TSGID 02000 /* Set GID on execution */ +#define TSVTX 01000 /* Reserved */ + /* File permissions */ +#define TUREAD 00400 /* Read by owner */ +#define TUWRITE 00200 /* Write by owner */ +#define TUEXEC 00100 /* Execute/Search by owner */ +#define TGREAD 00040 /* Read by group */ +#define TGWRITE 00020 /* Write by group */ +#define TGEXEC 00010 /* Execute/Search by group */ +#define TOREAD 00004 /* Read by other */ +#define TOWRITE 00002 /* Write by other */ +#define TOEXEC 00001 /* Execute/Search by other */ + +#endif diff --git a/Utilities/cmtar/util.c b/Utilities/cmtar/util.c new file mode 100644 index 0000000..007ed93 --- /dev/null +++ b/Utilities/cmtar/util.c @@ -0,0 +1,158 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <libtarint/internal.h> + +#include <stdio.h> +#include <libtar/compat.h> +#include <errno.h> + +#ifdef STDC_HEADERS +# include <string.h> +#endif + +#ifdef _MSC_VER +#include <direct.h> +#else +#include <sys/param.h> +#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); +#ifndef _MSC_VER + if (mkdir(dst, 0777) == -1) +#else + if (mkdir(dst) == -1) +#endif + { + 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; +} + + +/* 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] = ' '; +} + + diff --git a/Utilities/cmtar/wrapper.c b/Utilities/cmtar/wrapper.c new file mode 100644 index 0000000..fd80f39 --- /dev/null +++ b/Utilities/cmtar/wrapper.c @@ -0,0 +1,183 @@ +/* +** 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 <roth@uiuc.edu> +** Campus Information Technologies and Educational Services +** University of Illinois at Urbana-Champaign +*/ + +#include <libtarint/internal.h> + +#include <stdio.h> +#include <libtar/compat.h> +#ifdef _MSC_VER +#include <filesystem.h> +#else +#include <sys/param.h> +#include <dirent.h> +#endif +#include <errno.h> + +#ifdef HAVE_FNMATCH_H +#include <fnmatch.h> +#endif + +#ifdef STDC_HEADERS +# include <string.h> +#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, filename) != 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]; +#ifndef _MSC_VER + struct dirent *dent; + DIR *dp; +#else + kwDirEntry * dent; + kwDirectory *dp; +#endif + 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 + +#ifdef _MSC_VER + dp = kwOpenDir(realdir); +#else + dp = opendir(realdir); +#endif + + if (dp == NULL) + { + if (errno == ENOTDIR) + return 0; + return -1; + } +#ifdef _MSC_VER + while ((dent = kwReadDir(dp)) != NULL) +#else + while ((dent = readdir(dp)) != NULL) +#endif + { + 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); + +#ifndef WIN32 + if (lstat(realpath, &s) != 0) + return -1; +#else + if (stat(realpath, &s) != 0) + return -1; +#endif + 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; + } + +#ifdef _MSC_VER + kwCloseDir(dp); +#else + closedir(dp); +#endif + + return 0; +} + + |