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