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:
parent
1ac551f692
commit
cce1fd0901
@ -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>
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -29,7 +29,7 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <archive.h>
|
||||
#include "bsdtar_platform.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define DEFAULT_BYTES_PER_BLOCK (20*512)
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 = ".";
|
||||
|
@ -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>
|
||||
|
@ -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 ||
|
||||
|
Loading…
x
Reference in New Issue
Block a user