ENH: Initial import

This commit is contained in:
Andy Cedilnik 2005-12-28 10:18:37 -05:00
parent 552842d11f
commit bc1548b236
38 changed files with 7705 additions and 0 deletions

View File

@ -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})

35
Utilities/cmtar/COPYRIGHT Normal file
View File

@ -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.

272
Utilities/cmtar/append.c Normal file
View File

@ -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;
}

384
Utilities/cmtar/block.c Normal file
View File

@ -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;
}

View File

@ -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.

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 */
}

View File

@ -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);
}

View File

@ -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 */
}

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */
}

View File

@ -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 */
}

View File

@ -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';
}

View File

@ -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;
}

View File

@ -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 */

190
Utilities/cmtar/config.h.in Normal file
View File

@ -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@

136
Utilities/cmtar/decode.c Normal file
View File

@ -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;
}

234
Utilities/cmtar/encode.c Normal file
View File

@ -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);
}

561
Utilities/cmtar/extract.c Normal file
View File

@ -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;
}

View File

@ -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

View File

@ -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

136
Utilities/cmtar/handle.c Normal file
View File

@ -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;
}

View File

@ -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>

377
Utilities/cmtar/libtar.c Normal file
View File

@ -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;
}

295
Utilities/cmtar/libtar.h Normal file
View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */

145
Utilities/cmtar/output.c Normal file
View File

@ -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');
}

71
Utilities/cmtar/tar.h Normal file
View File

@ -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

158
Utilities/cmtar/util.c Normal file
View File

@ -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] = ' ';
}

183
Utilities/cmtar/wrapper.c Normal file
View File

@ -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;
}