Extended attribute support on write for Linux; FreeBSD hooks are

forthcoming.  This commit also has a number of style(9) fixes and
minor corrections so the code works better with the build system being
used for non-FreeBSD builds.

Many thanks to: Jaakko Heinonen, who proposed a mechanism for extended
attribute support and implemented both the machine-independent portion
and the Linux-specific portion.
This commit is contained in:
Tim Kientzle 2006-03-21 17:03:51 +00:00
parent 2228e32755
commit 6b422e20c1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=156962
9 changed files with 140 additions and 23 deletions

View File

@ -1,7 +1,7 @@
# $FreeBSD$
PROG= bsdtar
VERSION= 1.2.41
VERSION= 1.2.51
SRCS= bsdtar.c getdate.y matching.c read.c tree.c util.c write.c
WARNS?= 5
DPADD= ${LIBARCHIVE} ${LIBBZ2} ${LIBZ}

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

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

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

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>

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>

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)" : "");

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 *,
@ -444,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)
@ -509,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);
}
/*
@ -741,6 +746,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
@ -991,11 +997,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)
{
@ -1009,7 +1015,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)
{
@ -1073,7 +1079,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)
{
@ -1083,13 +1089,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);