ENH: Initial import
This commit is contained in:
parent
552842d11f
commit
bc1548b236
|
@ -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})
|
||||
|
|
@ -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.
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
||||
}
|
|
@ -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 */
|
||||
}
|
|
@ -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';
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
|
@ -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@
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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');
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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] = ' ';
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue