summaryrefslogtreecommitdiffstats
path: root/usr.bin/tar
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2009-03-08 05:22:50 +0000
committerkientzle <kientzle@FreeBSD.org>2009-03-08 05:22:50 +0000
commita6848f2b2f10ee6b71e817b0f08103c4e5eb2886 (patch)
treecce7714014699d4f4dd92650dec85bc3fcae4619 /usr.bin/tar
parent4d11395f6512783b51409c335f28f791bf3a7916 (diff)
downloadFreeBSD-src-a6848f2b2f10ee6b71e817b0f08103c4e5eb2886.zip
FreeBSD-src-a6848f2b2f10ee6b71e817b0f08103c4e5eb2886.tar.gz
Merge r283,r423 from libarchive.googlecode.com: Use libarchive's new
archive_read_disk API to pull metadata off of disk. This removes a lot of platform-specific knowledge of things like ACLs, file flags, and extended attributes from bsdtar.
Diffstat (limited to 'usr.bin/tar')
-rw-r--r--usr.bin/tar/bsdtar.h3
-rw-r--r--usr.bin/tar/matching.c2
-rw-r--r--usr.bin/tar/write.c652
3 files changed, 127 insertions, 530 deletions
diff --git a/usr.bin/tar/bsdtar.h b/usr.bin/tar/bsdtar.h
index 3b4edae..98b365b 100644
--- a/usr.bin/tar/bsdtar.h
+++ b/usr.bin/tar/bsdtar.h
@@ -92,7 +92,8 @@ struct bsdtar {
* Data for various subsystems. Full definitions are located in
* the file where they are used.
*/
- struct archive_entry_linkresolver *resolver;
+ struct archive *diskreader; /* for write.c */
+ struct archive_entry_linkresolver *resolver; /* for write.c */
struct archive_dir *archive_dir; /* for write.c */
struct name_cache *gname_cache; /* for write.c */
char *buff; /* for write.c */
diff --git a/usr.bin/tar/matching.c b/usr.bin/tar/matching.c
index 2e146fe..36bc84b 100644
--- a/usr.bin/tar/matching.c
+++ b/usr.bin/tar/matching.c
@@ -188,7 +188,7 @@ excluded(struct bsdtar *bsdtar, const char *pathname)
* gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
*
*/
-int
+static int
match_exclusion(struct match *match, const char *pathname)
{
const char *p;
diff --git a/usr.bin/tar/write.c b/usr.bin/tar/write.c
index b14aad5..682a3e5 100644
--- a/usr.bin/tar/write.c
+++ b/usr.bin/tar/write.c
@@ -44,7 +44,8 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
-#ifdef HAVE_EXT2FS_EXT2_FS_H
+#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
+/* This header exists but is broken on Cygwin. */
#include <ext2fs/ext2_fs.h>
#endif
#ifdef HAVE_FCNTL_H
@@ -120,25 +121,10 @@ static int archive_names_from_file_helper(struct bsdtar *bsdtar,
const char *line);
static int copy_file_data(struct bsdtar *bsdtar,
struct archive *a, struct archive *ina);
-static void create_cleanup(struct bsdtar *);
-static void free_cache(struct name_cache *cache);
-static const char * lookup_gname(struct bsdtar *bsdtar, gid_t gid);
-static int lookup_gname_helper(struct bsdtar *bsdtar,
- const char **name, id_t gid);
-static const char * lookup_uname(struct bsdtar *bsdtar, uid_t uid);
-static int lookup_uname_helper(struct bsdtar *bsdtar,
- const char **name, id_t uid);
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 *,
- const struct stat *, const char *pathname,
- const char *accpath);
static void write_entry_backend(struct bsdtar *, struct archive *,
struct archive_entry *);
static int write_file_data(struct bsdtar *, struct archive *,
@@ -417,6 +403,9 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
bsdtar_errc(bsdtar, 1, 0, "cannot create link resolver");
archive_entry_linkresolver_set_strategy(bsdtar->resolver,
archive_format(a));
+ if ((bsdtar->diskreader = archive_read_disk_new()) == NULL)
+ bsdtar_errc(bsdtar, 1, 0, "Cannot create read_disk object");
+ archive_read_disk_set_standard_lookup(bsdtar->diskreader);
if (bsdtar->names_from_file != NULL)
archive_names_from_file(bsdtar, a);
@@ -458,7 +447,6 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
}
- create_cleanup(bsdtar);
if (archive_write_close(a)) {
bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
bsdtar->return_value = 1;
@@ -467,6 +455,10 @@ write_archive(struct archive *a, struct bsdtar *bsdtar)
cleanup:
/* Free file data buffer. */
free(bsdtar->buff);
+ archive_entry_linkresolver_free(bsdtar->resolver);
+ bsdtar->resolver = NULL;
+ archive_read_finish(bsdtar->diskreader);
+ bsdtar->diskreader = NULL;
if (bsdtar->option_totals) {
fprintf(stderr, "Total bytes written: " BSDTAR_FILESIZE_PRINTF "\n",
@@ -636,6 +628,7 @@ copy_file_data(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
static void
write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
{
+ struct archive_entry *entry = NULL, *spare_entry = NULL;
struct tree *tree;
char symlink_mode = bsdtar->symlink_mode;
dev_t first_dev = 0;
@@ -651,8 +644,10 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
}
while ((tree_ret = tree_next(tree))) {
+ int r;
const char *name = tree_current_path(tree);
- const struct stat *st = NULL, *lst = NULL;
+ const struct stat *st = NULL; /* info to use for this entry */
+ const struct stat *lst = NULL; /* lstat() information */
int descend;
if (tree_ret == TREE_ERROR_FATAL)
@@ -666,31 +661,56 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
}
if (tree_ret != TREE_REGULAR)
continue;
+
+ /*
+ * If this file/dir is excluded by a filename
+ * pattern, skip it.
+ */
+ if (excluded(bsdtar, name))
+ continue;
+
+ /*
+ * Get lstat() info from the tree library.
+ */
lst = tree_current_lstat(tree);
if (lst == NULL) {
/* Couldn't lstat(); must not exist. */
bsdtar_warnc(bsdtar, errno, "%s: Cannot stat", name);
-
- /*
- * Report an error via the exit code if the failed
- * path is a prefix of what the user provided via
- * the command line. (Testing for string equality
- * here won't work due to trailing '/' characters.)
- */
- if (memcmp(name, path, strlen(name)) == 0)
- bsdtar->return_value = 1;
-
+ /* Return error if files disappear during traverse. */
+ bsdtar->return_value = 1;
continue;
}
- if (S_ISLNK(lst->st_mode))
+
+ /*
+ * Distinguish 'L'/'P'/'H' symlink following.
+ */
+ switch(symlink_mode) {
+ case 'H':
+ /* 'H': After the first item, rest like 'P'. */
+ symlink_mode = 'P';
+ /* 'H': First item (from command line) like 'L'. */
+ /* FALLTHROUGH */
+ case 'L':
+ /* 'L': Do descend through a symlink to dir. */
+ descend = tree_current_is_dir(tree);
+ /* 'L': Follow symlinks to files. */
+ archive_read_disk_set_symlink_logical(bsdtar->diskreader);
+ /* 'L': Archive symlinks as targets, if we can. */
st = tree_current_stat(tree);
- /* Default: descend into any dir or symlink to dir. */
- /* We'll adjust this later on. */
- descend = 0;
- if ((st != NULL) && S_ISDIR(st->st_mode))
- descend = 1;
- if ((lst != NULL) && S_ISDIR(lst->st_mode))
- descend = 1;
+ if (st != NULL)
+ break;
+ /* If stat fails, we have a broken symlink;
+ * in that case, don't follow the link. */
+ /* FALLTHROUGH */
+ default:
+ /* 'P': Don't descend through a symlink to dir. */
+ descend = tree_current_is_physical_dir(tree);
+ /* 'P': Don't follow symlinks to files. */
+ archive_read_disk_set_symlink_physical(bsdtar->diskreader);
+ /* 'P': Archive symlinks as symlinks. */
+ st = lst;
+ break;
+ }
/*
* If user has asked us not to cross mount points,
@@ -702,11 +722,41 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
dev_recorded = 1;
}
if (bsdtar->option_dont_traverse_mounts) {
- if (lst != NULL && lst->st_dev != first_dev)
+ if (lst->st_dev != first_dev)
descend = 0;
}
/*
+ * 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, name, st))
+ continue;
+
+ archive_entry_free(entry);
+ entry = archive_entry_new();
+
+ archive_entry_set_pathname(entry, name);
+ archive_entry_copy_sourcepath(entry,
+ tree_current_access_path(tree));
+
+ /* Populate the archive_entry with metadata from the disk. */
+ /* XXX TODO: Arrange to open a regular file before
+ * calling this so we can pass in an fd and shorten
+ * the race to query metadata. The linkify dance
+ * makes this more complex than it might sound. */
+ r = archive_read_disk_entry_from_file(bsdtar->diskreader,
+ entry, -1, st);
+ if (r != ARCHIVE_OK)
+ bsdtar_warnc(bsdtar, archive_errno(bsdtar->diskreader),
+ archive_error_string(bsdtar->diskreader));
+ if (r < ARCHIVE_WARN)
+ continue;
+
+ /* XXX TODO: Just use flag data from entry; avoid the
+ * duplicate check here. */
+
+ /*
* If this file/dir is flagged "nodump" and we're
* honoring such flags, skip this file/dir.
*/
@@ -732,62 +782,55 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
#endif
/*
- * If this file/dir is excluded by a filename
- * pattern, skip it.
- */
- if (excluded(bsdtar, name))
- continue;
-
- /*
* If the user vetoes this file/directory, skip it.
+ * We want this to be fairly late; if some other
+ * check would veto this file, we shouldn't bother
+ * the user with it.
*/
if (bsdtar->option_interactive &&
!yes("add '%s'", name))
continue;
- /*
- * If this is a dir, decide whether or not to recurse.
- */
- if (bsdtar->option_no_subdirs)
- descend = 0;
+ /* Note: if user vetoes, we won't descend. */
+ if (descend && !bsdtar->option_no_subdirs)
+ tree_descend(tree);
/*
- * Distinguish 'L'/'P'/'H' symlink following.
+ * Rewrite the pathname to be archived. If rewrite
+ * fails, skip the entry.
*/
- switch(symlink_mode) {
- case 'H':
- /* 'H': After the first item, rest like 'P'. */
- symlink_mode = 'P';
- /* '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. */
- if (!S_ISDIR(lst->st_mode))
- descend = 0;
- /* 'P': Archive symlink to file as symlink. */
- /* lst = tree_current_lstat(tree); */
- break;
- }
+ if (edit_pathname(bsdtar, entry))
+ continue;
- if (descend)
- tree_descend(tree);
+ /* Display entry as we process it.
+ * This format is required by SUSv2. */
+ if (bsdtar->verbose)
+ safe_fprintf(stderr, "a %s",
+ archive_entry_pathname(entry));
- /*
- * Write the entry. Note that write_entry() handles
- * pathname editing and newness testing.
- */
- write_entry(bsdtar, a, lst, name,
- tree_current_access_path(tree));
+ /* Non-regular files get archived with zero size. */
+ if (!S_ISREG(st->st_mode))
+ archive_entry_set_size(entry, 0);
+
+ /* Record what we're doing, for SIGINFO / SIGUSR1. */
+ siginfo_setinfo(bsdtar, "adding",
+ archive_entry_pathname(entry), archive_entry_size(entry));
+ archive_entry_linkify(bsdtar->resolver, &entry, &spare_entry);
+
+ /* Handle SIGINFO / SIGUSR1 request if one was made. */
+ siginfo_printinfo(bsdtar, 0);
+
+ while (entry != NULL) {
+ write_entry_backend(bsdtar, a, entry);
+ archive_entry_free(entry);
+ entry = spare_entry;
+ spare_entry = NULL;
+ }
+
+ if (bsdtar->verbose)
+ fprintf(stderr, "\n");
}
+ archive_entry_free(entry);
tree_close(tree);
}
@@ -846,117 +889,6 @@ write_entry_backend(struct bsdtar *bsdtar, struct archive *a,
close(fd);
}
-/*
- * Add a single filesystem object to the archive.
- */
-static void
-write_entry(struct bsdtar *bsdtar, struct archive *a, const struct stat *st,
- const char *pathname, const char *accpath)
-{
- struct archive_entry *entry, *sparse_entry;
- static char linkbuffer[PATH_MAX+1];
-
- entry = archive_entry_new();
-
- archive_entry_set_pathname(entry, pathname);
- archive_entry_copy_sourcepath(entry, accpath);
-
- /*
- * Rewrite the pathname to be archived. If rewrite
- * fails, skip the entry.
- */
- 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;
-
- /* Display entry as we process it. This format is required by SUSv2. */
- if (bsdtar->verbose)
- safe_fprintf(stderr, "a %s", archive_entry_pathname(entry));
-
- /* Read symbolic link information. */
- if ((st->st_mode & S_IFMT) == S_IFLNK) {
- int lnklen;
-
- lnklen = readlink(accpath, linkbuffer, PATH_MAX);
- if (lnklen < 0) {
- if (!bsdtar->verbose)
- bsdtar_warnc(bsdtar, errno,
- "%s: Couldn't read symbolic link",
- pathname);
- else
- safe_fprintf(stderr,
- ": Couldn't read symbolic link: %s",
- strerror(errno));
- goto cleanup;
- }
- linkbuffer[lnklen] = 0;
- archive_entry_set_symlink(entry, linkbuffer);
- }
-
- /* Look up username and group name. */
- archive_entry_set_uname(entry, lookup_uname(bsdtar, st->st_uid));
- archive_entry_set_gname(entry, lookup_gname(bsdtar, st->st_gid));
-
-#ifdef HAVE_STRUCT_STAT_ST_FLAGS
- /* XXX TODO: archive_entry_copy_stat() should copy st_flags
- * on platforms that support it. This should go away then. */
- if (st->st_flags != 0)
- archive_entry_set_fflags(entry, st->st_flags, 0);
-#endif
-
-#ifdef EXT2_IOC_GETFLAGS
- /* XXX TODO: Find a way to merge this with the
- * flags fetch for nodump support earlier. */
- if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
- int fd = open(accpath, O_RDONLY | O_NONBLOCK);
- if (fd >= 0) {
- unsigned long stflags;
- int r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
- close(fd);
- if (r == 0 && stflags != 0)
- archive_entry_set_fflags(entry, stflags, 0);
- }
- }
-#endif
-
- archive_entry_copy_stat(entry, st);
- setup_acls(bsdtar, entry, accpath);
- setup_xattrs(bsdtar, entry, accpath);
-
- /* Non-regular files get archived with zero size. */
- if (!S_ISREG(st->st_mode))
- archive_entry_set_size(entry, 0);
-
- /* Record what we're doing, for the benefit of SIGINFO / SIGUSR1. */
- siginfo_setinfo(bsdtar, "adding", archive_entry_pathname(entry),
- archive_entry_size(entry));
- archive_entry_linkify(bsdtar->resolver, &entry, &sparse_entry);
-
- /* Handle SIGINFO / SIGUSR1 request if one was made. */
- siginfo_printinfo(bsdtar, 0);
-
- while (entry != NULL) {
- write_entry_backend(bsdtar, a, entry);
- archive_entry_free(entry);
- entry = sparse_entry;
- sparse_entry = NULL;
- }
-
-cleanup:
- if (bsdtar->verbose)
- fprintf(stderr, "\n");
-
-abort:
- if (entry != NULL)
- archive_entry_free(entry);
-}
-
/* Helper function to copy file to archive. */
static int
@@ -991,342 +923,6 @@ write_file_data(struct bsdtar *bsdtar, struct archive *a,
return 0;
}
-
-static void
-create_cleanup(struct bsdtar *bsdtar)
-{
- free_cache(bsdtar->uname_cache);
- bsdtar->uname_cache = NULL;
- free_cache(bsdtar->gname_cache);
- bsdtar->gname_cache = NULL;
-}
-
-#ifdef HAVE_POSIX_ACL
-static void setup_acl(struct bsdtar *bsdtar,
- struct archive_entry *entry, const char *accpath,
- int acl_type, int archive_entry_acl_type);
-
-static void
-setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry,
- const char *accpath)
-{
- archive_entry_acl_clear(entry);
-
- setup_acl(bsdtar, entry, accpath,
- ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
- /* Only directories can have default ACLs. */
- if (S_ISDIR(archive_entry_mode(entry)))
- setup_acl(bsdtar, entry, accpath,
- ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
-}
-
-static void
-setup_acl(struct bsdtar *bsdtar, struct archive_entry *entry,
- const char *accpath, int acl_type, int archive_entry_acl_type)
-{
- acl_t acl;
- acl_tag_t acl_tag;
- acl_entry_t acl_entry;
- acl_permset_t acl_permset;
- int s, ae_id, ae_tag, ae_perm;
- const char *ae_name;
-
- /* Retrieve access ACL from file. */
- acl = acl_get_file(accpath, acl_type);
- if (acl != NULL) {
- s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
- while (s == 1) {
- ae_id = -1;
- ae_name = NULL;
-
- acl_get_tag_type(acl_entry, &acl_tag);
- if (acl_tag == ACL_USER) {
- ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
- ae_name = lookup_uname(bsdtar, ae_id);
- ae_tag = ARCHIVE_ENTRY_ACL_USER;
- } else if (acl_tag == ACL_GROUP) {
- ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
- ae_name = lookup_gname(bsdtar, ae_id);
- ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
- } else if (acl_tag == ACL_MASK) {
- ae_tag = ARCHIVE_ENTRY_ACL_MASK;
- } else if (acl_tag == ACL_USER_OBJ) {
- ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
- } else if (acl_tag == ACL_GROUP_OBJ) {
- ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
- } else if (acl_tag == ACL_OTHER) {
- ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
- } else {
- /* Skip types that libarchive can't support. */
- continue;
- }
-
- acl_get_permset(acl_entry, &acl_permset);
- ae_perm = 0;
- /*
- * acl_get_perm() is spelled differently on different
- * platforms; see bsdtar_platform.h for details.
- */
- if (ACL_GET_PERM(acl_permset, ACL_EXECUTE))
- ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
- if (ACL_GET_PERM(acl_permset, ACL_READ))
- ae_perm |= ARCHIVE_ENTRY_ACL_READ;
- if (ACL_GET_PERM(acl_permset, ACL_WRITE))
- ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
-
- archive_entry_acl_add_entry(entry,
- archive_entry_acl_type, ae_perm, ae_tag,
- ae_id, ae_name);
-
- s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
- }
- acl_free(acl);
- }
-}
-#else
-static void
-setup_acls(struct bsdtar *bsdtar, struct archive_entry *entry,
- const char *accpath)
-{
- (void)bsdtar;
- (void)entry;
- (void)accpath;
-}
-#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++) {
- if (cache->cache[i].name != NULL &&
- cache->cache[i].name != NO_NAME)
- free((void *)(uintptr_t)cache->cache[i].name);
- }
- free(cache);
- }
-}
-
-/*
- * Lookup uid/gid from uname/gname, return NULL if no match.
- */
-static const char *
-lookup_name(struct bsdtar *bsdtar, struct name_cache **name_cache_variable,
- int (*lookup_fn)(struct bsdtar *, const char **, id_t), id_t id)
-{
- struct name_cache *cache;
- const char *name;
- int slot;
-
-
- if (*name_cache_variable == NULL) {
- *name_cache_variable = malloc(sizeof(struct name_cache));
- if (*name_cache_variable == NULL)
- bsdtar_errc(bsdtar, 1, ENOMEM, "No more memory");
- memset(*name_cache_variable, 0, sizeof(struct name_cache));
- (*name_cache_variable)->size = name_cache_size;
- }
-
- cache = *name_cache_variable;
- cache->probes++;
-
- slot = id % cache->size;
- if (cache->cache[slot].name != NULL) {
- if (cache->cache[slot].id == id) {
- cache->hits++;
- if (cache->cache[slot].name == NO_NAME)
- return (NULL);
- return (cache->cache[slot].name);
- }
- if (cache->cache[slot].name != NO_NAME)
- free((void *)(uintptr_t)cache->cache[slot].name);
- cache->cache[slot].name = NULL;
- }
-
- if (lookup_fn(bsdtar, &name, id) == 0) {
- if (name == NULL || name[0] == '\0') {
- /* Cache the negative response. */
- cache->cache[slot].name = NO_NAME;
- cache->cache[slot].id = id;
- } else {
- cache->cache[slot].name = strdup(name);
- if (cache->cache[slot].name != NULL) {
- cache->cache[slot].id = id;
- return (cache->cache[slot].name);
- }
- /*
- * Conveniently, NULL marks an empty slot, so
- * if the strdup() fails, we've just failed to
- * cache it. No recovery necessary.
- */
- }
- }
- return (NULL);
-}
-
-static const char *
-lookup_uname(struct bsdtar *bsdtar, uid_t uid)
-{
- return (lookup_name(bsdtar, &bsdtar->uname_cache,
- &lookup_uname_helper, (id_t)uid));
-}
-
-static int
-lookup_uname_helper(struct bsdtar *bsdtar, const char **name, id_t id)
-{
- struct passwd *pwent;
-
- (void)bsdtar; /* UNUSED */
-
- errno = 0;
- pwent = getpwuid((uid_t)id);
- if (pwent == NULL) {
- *name = NULL;
- if (errno != 0)
- bsdtar_warnc(bsdtar, errno, "getpwuid(%d) failed", id);
- return (errno);
- }
-
- *name = pwent->pw_name;
- return (0);
-}
-
-static const char *
-lookup_gname(struct bsdtar *bsdtar, gid_t gid)
-{
- return (lookup_name(bsdtar, &bsdtar->gname_cache,
- &lookup_gname_helper, (id_t)gid));
-}
-
-static int
-lookup_gname_helper(struct bsdtar *bsdtar, const char **name, id_t id)
-{
- struct group *grent;
-
- (void)bsdtar; /* UNUSED */
-
- errno = 0;
- grent = getgrgid((gid_t)id);
- if (grent == NULL) {
- *name = NULL;
- if (errno != 0)
- bsdtar_warnc(bsdtar, errno, "getgrgid(%d) failed", id);
- return (errno);
- }
-
- *name = grent->gr_name;
- return (0);
-}
-
/*
* Test if the specified file is new enough to include in the archive.
*/
OpenPOWER on IntegriCloud