MFC bsdtar 1.2.53 to FreeBSD 6:

* Fixes bin/87911 (internal error attempting -u with empty file)
  * Fixes bin/84993 (warnings with GCC 4.1)
  * Fixes bin/95175 (core dump on nonexistent symlink)
  * Documentation fixes
  * Corrections to pathname matching
  * Portability fixes
  * Initial extended attribute support
This commit is contained in:
kientzle 2006-07-30 06:32:14 +00:00
parent 1ac551f692
commit cce1fd0901
12 changed files with 182 additions and 227 deletions

View File

@ -1,14 +1,8 @@
# $FreeBSD$
#
# Use "make distfile" to build a tar.gz file suitable for distribution,
# including an autoconf/automake-generated build system.
#
PROG= bsdtar
VERSION= 1.02.023
DIST_SRCS= bsdtar.c getdate.y matching.c read.c tree.c util.c write.c
SRCS= ${DIST_SRCS}
VERSION= 1.2.53
SRCS= bsdtar.c getdate.y matching.c read.c tree.c util.c write.c
WARNS?= 5
DPADD= ${LIBARCHIVE} ${LIBBZ2} ${LIBZ}
LDADD= -larchive -lbz2 -lz
@ -17,32 +11,4 @@ CFLAGS+= -I${.CURDIR}
SYMLINKS= bsdtar ${BINDIR}/tar
MLINKS= bsdtar.1 tar.1
DIST_BUILD_DIR= ${.OBJDIR}/${PROG}-${VERSION}
CLEANDIRS+= ${DIST_BUILD_DIR}
DISTFILE= ${PROG}-${VERSION}.tar.gz
# Files that just get copied to the distfile build directory
DIST_FILES= ${DIST_SRCS}
DIST_FILES+= ${MAN}
DIST_FILES+= bsdtar.h bsdtar_platform.h
DIST_FILES+= Makefile.am
DIST_FILES+= tree.h
distfile:
rm -rf ${DIST_BUILD_DIR}
mkdir ${DIST_BUILD_DIR}
for f in ${DIST_FILES}; \
do \
cat ${.CURDIR}/$$f >${DIST_BUILD_DIR}/$$f; \
done
cat ${.CURDIR}/configure.ac.in | \
sed 's/@VERSION@/${VERSION}/' | \
cat > ${DIST_BUILD_DIR}/configure.ac
(cd ${DIST_BUILD_DIR} && aclocal && autoheader && autoconf )
(cd ${DIST_BUILD_DIR} && automake -a --foreign)
(cd ${DIST_BUILD_DIR} && ./configure && make distcheck && make dist)
mv ${DIST_BUILD_DIR}/${DISTFILE} ${.OBJDIR}
@echo ==================================================
@echo Created ${.OBJDIR}/${DISTFILE}
@echo ==================================================
.include <bsd.prog.mk>

View File

@ -1,21 +0,0 @@
# $FreeBSD$
# Process this file with automake to create Makefile.in
bin_PROGRAMS= bsdtar
bsdtar_SOURCES= \
bsdtar.c \
bsdtar.h \
bsdtar_platform.h \
getdate.y \
matching.c \
read.c \
tree.c \
tree.h \
util.c \
write.c
bsdtar_LDADD= -larchive -lbz2 -lz
dist_man_MANS= bsdtar.1
DISTCLEANFILES= getdate.c getdate.h

View File

@ -445,16 +445,16 @@ option.
.Sh EXAMPLES
The following creates a new archive
called
.Ar file.tar
.Ar file.tar.gz
that contains two files
.Ar source.c
and
.Ar source.h :
.Dl Nm Fl czf Pa file.tar Pa source.c Pa source.h
.Dl Nm Fl czf Pa file.tar.gz Pa source.c Pa source.h
.Pp
To view a detailed table of contents for this
archive:
.Dl Nm Fl tvf Pa file.tar
.Dl Nm Fl tvf Pa file.tar.gz
.Pp
To extract all entries from the archive on
the default tape drive:
@ -463,9 +463,9 @@ the default tape drive:
To move file hierarchies, invoke
.Nm
as
.Dl Nm Fl cf Pa - Fl C Pa srcdir\ . | Nm Fl xpBf Pa - Fl C Pa destdir
.Dl Nm Fl cf Pa - Fl C Pa srcdir\ . | Nm Fl xpf Pa - Fl C Pa destdir
or more traditionally
.Dl cd srcdir \&; Nm Fl cf Pa -\ . | ( cd destdir \&; Nm Fl xpBf Pa - )
.Dl cd srcdir \&; Nm Fl cf Pa -\ . | ( cd destdir \&; Nm Fl xpf Pa - )
.Pp
In create mode, the list of files and directories to be archived
can also include directory change instructions of the form

View File

@ -29,8 +29,6 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/stat.h>
#include <archive.h>
#include <archive_entry.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_GETOPT_LONG
@ -410,6 +408,7 @@ main(int argc, char **argv)
case 'p': /* GNU tar, star */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_PERM;
bsdtar->extract_flags |= ARCHIVE_EXTRACT_ACL;
bsdtar->extract_flags |= ARCHIVE_EXTRACT_XATTR;
bsdtar->extract_flags |= ARCHIVE_EXTRACT_FFLAGS;
break;
case 'r': /* SUSv2 */
@ -689,9 +688,7 @@ usage(struct bsdtar *bsdtar)
static void
version(void)
{
printf("bsdtar %s, ", PACKAGE_VERSION);
printf("%s\n", archive_version());
printf("Copyright (C) 2003-2005 Tim Kientzle\n");
printf("bsdtar %s - %s\n", PACKAGE_VERSION, archive_version());
exit(1);
}
@ -757,8 +754,7 @@ long_help(struct bsdtar *bsdtar)
} else
putchar(*p);
}
fprintf(stdout, "\n%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
fprintf(stdout, "%s\n", archive_version());
version();
}
static int

View File

@ -29,7 +29,7 @@
* $FreeBSD$
*/
#include <archive.h>
#include "bsdtar_platform.h"
#include <stdio.h>
#define DEFAULT_BYTES_PER_BLOCK (20*512)

View File

@ -36,7 +36,7 @@
#define BSDTAR_PLATFORM_H_INCLUDED
#if HAVE_CONFIG_H
#include "config.h"
#include "../config.h"
#else
#ifdef __FreeBSD__
@ -112,8 +112,14 @@
#define __FBSDID(a) /* null */
#endif
#ifndef HAVE_LIBARCHIVE
#error Configuration error: did not find libarchive.
#ifdef HAVE_LIBARCHIVE
/* If we're using the platform libarchive, include system headers. */
#include <archive.h>
#include <archive_entry.h>
#else
/* Otherwise, include user headers. */
#include "archive.h"
#include "archive_entry.h"
#endif
/*
@ -121,12 +127,16 @@
* including some variant of the acl_get_perm() function (which was
* omitted from the POSIX.1e draft)?
*/
#if HAVE_SYS_ACL_H && HAVE_ACL_PERMSET_T
#if HAVE_SYS_ACL_H && HAVE_ACL_PERMSET_T && HAVE_ACL_USER
#if HAVE_ACL_GET_PERM || HAVE_ACL_GET_PERM_NP
#define HAVE_POSIX_ACL 1
#endif
#endif
#ifdef HAVE_LIBACL
#include <acl/libacl.h>
#endif
#if HAVE_ACL_GET_PERM
#define ACL_GET_PERM acl_get_perm
#else

View File

@ -1,117 +0,0 @@
# $FreeBSD$
# Process this file with autoconf to produce a configure script.
AC_INIT(bsdtar, @VERSION@, kientzle@freebsd.org)
AM_INIT_AUTOMAKE(bsdtar, @VERSION@)
AC_CONFIG_SRCDIR([bsdtar.c])
AM_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
AC_PROG_YACC
# Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS([bzlib.h fcntl.h inttypes.h langinfo.h limits.h locale.h paths.h stdint.h stdlib.h string.h sys/ioctl.h sys/param.h unistd.h zlib.h])
# Checks for libraries.
AC_CHECK_LIB([z], [inflate])
AC_CHECK_LIB([bz2], [BZ2_bzDecompressInit])
AC_CHECK_LIB([archive], [archive_version])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_UID_T
AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
AC_CHECK_TYPE(id_t, [unsigned long])
AC_CHECK_MEMBERS([struct stat.st_rdev, struct stat.st_mtimespec.tv_nsec, struct stat.st_mtim.tv_nsec])
AC_CHECK_DECL([D_MD_ORDER],
[AC_DEFINE(HAVE_D_MD_ORDER, 1, [Define to 1 if nl_langinfo supports D_MD_ORDER])],
[],
[#if HAVE_LANGINFO_H
#include <langinfo.h>
#endif
])
AC_FUNC_FNMATCH
AC_CHECK_DECL([FNM_LEADING_DIR],
[AC_DEFINE(HAVE_FNM_LEADING_DIR, 1, [Define to 1 if fnmatch(3) supports the FNM_LEADING_DIR flag])],
[],
[#if HAVE_FNMATCH
#define _GNU_SOURCE /* Required on Linux to get GNU extensions */
#include <fnmatch.h>
#endif
])
# Check for dirent.d_namlen field explicitly
AC_CHECK_MEMBER(struct dirent.d_namlen,,,
[#if HAVE_DIRENT_H
#include <dirent.h>
#endif
])
# Check for ACL support
AC_CHECK_HEADERS([sys/acl.h])
AC_CHECK_LIB([acl],[acl_get_file])
AC_CHECK_TYPES(acl_permset_t,,,
[#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
])
# The "acl_get_perm()" function was omitted from the POSIX draft.
# (It's a pretty obvious oversight; otherwise, there's no way to
# test for specific permissions in a permset.) Linux uses the obvious
# name, FreeBSD adds _np to mark it as "non-Posix extension."
# Test for both as a double-check that we really have POSIX-style ACL support.
AC_CHECK_FUNCS(acl_get_perm_np acl_get_perm,,,
[#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
])
# Checks for library functions.
AC_PROG_GCC_TRADITIONAL
AC_FUNC_LSTAT
AC_HEADER_MAJOR
AC_FUNC_MALLOC
AC_FUNC_STAT
AC_FUNC_STRFTIME
AC_FUNC_VPRINTF
AC_CHECK_TYPES([uintmax_t, unsigned long long])
AC_CHECK_FUNCS([chflags fchdir ftruncate getopt_long memmove memset nl_langinfo reallocf setlocale strchr strdup strerror strrchr])
#
# If any of the common 64-bit types is defined, set "int64_t"
#
AC_CHECK_TYPE(__int64_t, [long long])
AC_CHECK_TYPE(_int64_t, [__int64_t])
AC_CHECK_TYPE(int64_t, [_int64_t])
#
# If any of the common 64-bit unsigned types is defined, set "uint64_t"
#
AC_CHECK_TYPE(__uint64_t, [unsigned long long])
AC_CHECK_TYPE(_uint64_t, [__uint64_t])
AC_CHECK_TYPE(u_int64_t, [_uint64_t])
AC_CHECK_TYPE(uint64_t, [u_int64_t])
#define HAVE_CHFLAGS 1
# Additional requirements
AC_SYS_LARGEFILE
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

View File

@ -23,8 +23,10 @@
/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
/* SUPPRESS 288 on yyerrlab *//* Label unused */
#include "bsdtar_platform.h"
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#endif
#include <ctype.h>
#include <stdio.h>
@ -717,6 +719,7 @@ get_date(char *p)
time_t nowtime;
long tzone;
memset(&gmt, 0, sizeof(gmt));
yyInput = p;
(void)time (&nowtime);

View File

@ -31,8 +31,6 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/stat.h>
#include <archive.h>
#include <archive_entry.h>
#include <errno.h>
#include <grp.h>
#include <limits.h>
@ -279,7 +277,7 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
if (!now)
time(&now);
bsdtar_strmode(entry, tmp);
fprintf(out, "%s %d ", tmp, st->st_nlink);
fprintf(out, "%s %d ", tmp, (int)(st->st_nlink));
/* Use uname if it's present, else uid. */
p = archive_entry_uname(entry);

View File

@ -130,7 +130,7 @@ tree_dump(struct tree *t, FILE *out)
fprintf(out, "\tpwd: "); fflush(stdout); system("pwd");
fprintf(out, "\taccess: %s\n", t->basename);
fprintf(out, "\tstack:\n");
for(te = t->stack; te != NULL; te = te->next) {
for (te = t->stack; te != NULL; te = te->next) {
fprintf(out, "\t\tte->name: %s%s%s\n", te->name,
te->flags & needsPreVisit ? "" : " *",
t->current == te ? " (current)" : "");
@ -311,13 +311,14 @@ tree_next(struct tree *t)
t->tree_errno = errno;
return (t->visit_type = TREE_ERROR_DIR);
}
t->depth++;
t->d = opendir(".");
if (t->d == NULL) {
tree_ascend(t); /* Undo "chdir" */
tree_pop(t);
t->tree_errno = errno;
return (t->visit_type = TREE_ERROR_DIR);
}
t->depth++;
t->flags &= ~hasLstat;
t->flags &= ~hasStat;
t->basename = ".";

View File

@ -29,7 +29,6 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <sys/types.h> /* Linux doesn't define mode_t, etc. in sys/stat.h. */
#include <archive_entry.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>

View File

@ -32,8 +32,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_POSIX_ACL
#include <sys/acl.h>
#endif
#include <archive.h>
#include <archive_entry.h>
#ifdef HAVE_ATTR_XATTR_H
#include <attr/xattr.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
@ -119,6 +120,8 @@ static int new_enough(struct bsdtar *, const char *path,
const struct stat *);
static void setup_acls(struct bsdtar *, struct archive_entry *,
const char *path);
static void setup_xattrs(struct bsdtar *, struct archive_entry *,
const char *path);
static void test_for_append(struct bsdtar *);
static void write_archive(struct archive *, struct bsdtar *);
static void write_entry(struct bsdtar *, struct archive *,
@ -296,9 +299,13 @@ tar_mode_u(struct bsdtar *bsdtar)
archive_read_support_compression_all(a);
archive_read_support_format_tar(a);
archive_read_support_format_gnutar(a);
archive_read_open_fd(a, bsdtar->fd,
if (archive_read_open_fd(a, bsdtar->fd,
bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
DEFAULT_BYTES_PER_BLOCK);
DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
bsdtar_errc(bsdtar, 1, 0,
"Can't open %s: %s", bsdtar->filename,
archive_error_string(a));
}
/* Build a list of all entries and their recorded mod times. */
while (0 == archive_read_next_header(a, &entry)) {
@ -440,10 +447,11 @@ archive_names_from_file_helper(struct bsdtar *bsdtar, const char *line)
}
/*
* Copy from specified archive to current archive.
* Returns non-zero on fatal error (i.e., output errors). Errors
* reading the input archive set bsdtar->return_value, but this
* function will still return zero.
* Copy from specified archive to current archive. Returns non-zero
* for write errors (which force us to terminate the entire archiving
* operation). If there are errors reading the input archive, we set
* bsdtar->return_value but return zero, so the overall archiving
* operation will complete and return non-zero.
*/
static int
append_archive(struct bsdtar *bsdtar, struct archive *a, const char *filename)
@ -505,7 +513,8 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, const char *filename)
bsdtar->return_value = 1;
}
return (0); /* TODO: Return non-zero on error */
/* Note: If we got here, we saw no write errors, so return success. */
return (0);
}
/*
@ -620,15 +629,18 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
*/
switch(symlink_mode) {
case 'H':
/* 'H': First item (from command line) like 'L'. */
lst = tree_current_stat(tree);
/* 'H': After the first item, rest like 'P'. */
symlink_mode = 'P';
break;
/* 'H': First item (from command line) like 'L'. */
/* FALLTHROUGH */
case 'L':
/* 'L': Do descend through a symlink to dir. */
/* 'L': Archive symlink to file as file. */
lst = tree_current_stat(tree);
/* If stat fails, we have a broken symlink;
* in that case, archive the link as such. */
if (lst == NULL)
lst = tree_current_lstat(tree);
break;
default:
/* 'P': Don't descend through a symlink to dir. */
@ -643,15 +655,12 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
tree_descend(tree);
/*
* In -u mode, we need to check whether this
* is newer than what's already in the archive.
* In all modes, we need to obey --newerXXX flags.
* Write the entry. Note that write_entry() handles
* pathname editing and newness testing.
*/
if (new_enough(bsdtar, name, lst)) {
write_entry(bsdtar, a, lst, name,
tree_current_pathlen(tree),
tree_current_access_path(tree));
}
write_entry(bsdtar, a, lst, name,
tree_current_pathlen(tree),
tree_current_access_path(tree));
}
tree_close(tree);
}
@ -686,6 +695,13 @@ write_entry(struct bsdtar *bsdtar, struct archive *a, const struct stat *st,
if (edit_pathname(bsdtar, entry))
goto abort;
/*
* In -u mode, check that the file is newer than what's
* already in the archive; in all modes, obey --newerXXX flags.
*/
if (!new_enough(bsdtar, archive_entry_pathname(entry), st))
goto abort;
if (!S_ISDIR(st->st_mode) && (st->st_nlink > 1))
lookup_hardlink(bsdtar, entry, st);
@ -733,6 +749,7 @@ write_entry(struct bsdtar *bsdtar, struct archive *a, const struct stat *st,
archive_entry_copy_stat(entry, st);
setup_acls(bsdtar, entry, accpath);
setup_xattrs(bsdtar, entry, accpath);
/*
* If it's a regular file (and non-zero in size) make sure we
@ -983,11 +1000,11 @@ lookup_hardlink(struct bsdtar *bsdtar, struct archive_entry *entry,
}
#ifdef HAVE_POSIX_ACL
void setup_acl(struct bsdtar *bsdtar,
static void setup_acl(struct bsdtar *bsdtar,
struct archive_entry *entry, const char *accpath,
int acl_type, int archive_entry_acl_type);
void
static void
setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry,
const char *accpath)
{
@ -1001,7 +1018,7 @@ setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry,
ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
}
void
static void
setup_acl(struct bsdtar *bsdtar, struct archive_entry *entry,
const char *accpath, int acl_type, int archive_entry_acl_type)
{
@ -1065,7 +1082,7 @@ setup_acl(struct bsdtar *bsdtar, struct archive_entry *entry,
}
}
#else
void
static void
setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry,
const char *accpath)
{
@ -1075,13 +1092,120 @@ setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry,
}
#endif
#if HAVE_LISTXATTR && HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR
static void
setup_xattr(struct bsdtar *bsdtar, struct archive_entry *entry,
const char *accpath, const char *name)
{
size_t size;
void *value = NULL;
char symlink_mode = bsdtar->symlink_mode;
if (symlink_mode == 'H')
size = getxattr(accpath, name, NULL, 0);
else
size = lgetxattr(accpath, name, NULL, 0);
if (size == -1) {
bsdtar_warnc(bsdtar, errno, "Couldn't get extended attribute");
return;
}
if (size > 0 && (value = malloc(size)) == NULL) {
bsdtar_errc(bsdtar, 1, errno, "Out of memory");
return;
}
if (symlink_mode == 'H')
size = getxattr(accpath, name, value, size);
else
size = lgetxattr(accpath, name, value, size);
if (size == -1) {
bsdtar_warnc(bsdtar, errno, "Couldn't get extended attribute");
return;
}
archive_entry_xattr_add_entry(entry, name, value, size);
free(value);
}
/*
* Linux extended attribute support
*/
static void
setup_xattrs(struct bsdtar *bsdtar, struct archive_entry *entry,
const char *accpath)
{
char *list, *p;
size_t list_size;
char symlink_mode = bsdtar->symlink_mode;
if (symlink_mode == 'H')
list_size = listxattr(accpath, NULL, 0);
else
list_size = llistxattr(accpath, NULL, 0);
if (list_size == -1) {
bsdtar_warnc(bsdtar, errno,
"Couldn't list extended attributes");
return;
} else if (list_size == 0)
return;
if ((list = malloc(list_size)) == NULL) {
bsdtar_errc(bsdtar, 1, errno, "Out of memory");
return;
}
if (symlink_mode == 'H')
list_size = listxattr(accpath, list, list_size);
else
list_size = llistxattr(accpath, list, list_size);
if (list_size == -1) {
bsdtar_warnc(bsdtar, errno,
"Couldn't list extended attributes");
free(list);
return;
}
for (p = list; (p - list) < list_size; p += strlen(p) + 1) {
if (strncmp(p, "system.", 7) == 0 ||
strncmp(p, "xfsroot.", 8) == 0)
continue;
setup_xattr(bsdtar, entry, accpath, p);
}
free(list);
}
#else
/*
* Generic (stub) extended attribute support.
*/
static void
setup_xattrs(struct bsdtar *bsdtar, struct archive_entry *entry,
const char *accpath)
{
(void)bsdtar; /* UNUSED */
(void)entry; /* UNUSED */
(void)accpath; /* UNUSED */
}
#endif
static void
free_cache(struct name_cache *cache)
{
size_t i;
if (cache != NULL) {
for(i = 0; i < cache->size; i++) {
for (i = 0; i < cache->size; i++) {
if (cache->cache[i].name != NULL &&
cache->cache[i].name != NO_NAME)
free((void *)(uintptr_t)cache->cache[i].name);
@ -1235,10 +1359,6 @@ new_enough(struct bsdtar *bsdtar, const char *path, const struct stat *st)
*/
if (bsdtar->archive_dir != NULL &&
bsdtar->archive_dir->head != NULL) {
/* Ignore leading './' when comparing names. */
if (path[0] == '.' && path[1] == '/' && path[2] != '\0')
path += 2;
for (p = bsdtar->archive_dir->head; p != NULL; p = p->next) {
if (strcmp(path, p->name)==0)
return (p->mtime_sec < st->st_mtime ||