Author: kientzle
Date: Sun Mar  8 05:22:50 2009
New Revision: 189514
URL: http://svn.freebsd.org/changeset/base/189514

Log:
  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.

Modified:
  head/usr.bin/tar/bsdtar.h
  head/usr.bin/tar/matching.c
  head/usr.bin/tar/write.c

Modified: head/usr.bin/tar/bsdtar.h
==============================================================================
--- head/usr.bin/tar/bsdtar.h   Sun Mar  8 05:19:36 2009        (r189513)
+++ head/usr.bin/tar/bsdtar.h   Sun Mar  8 05:22:50 2009        (r189514)
@@ -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 */

Modified: head/usr.bin/tar/matching.c
==============================================================================
--- head/usr.bin/tar/matching.c Sun Mar  8 05:19:36 2009        (r189513)
+++ head/usr.bin/tar/matching.c Sun Mar  8 05:22:50 2009        (r189514)
@@ -188,7 +188,7 @@ excluded(struct bsdtar *bsdtar, const ch
  * 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;

Modified: head/usr.bin/tar/write.c
==============================================================================
--- head/usr.bin/tar/write.c    Sun Mar  8 05:19:36 2009        (r189513)
+++ head/usr.bin/tar/write.c    Sun Mar  8 05:22:50 2009        (r189514)
@@ -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_hel
                             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_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 
                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 
 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, st
 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, s
        }
 
        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, s
                }
                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, s
                        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, s
 #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 *bsdta
                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, s
        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.
  */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to