]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Refactor the UID/GID lookup in write_disk so that it can be
authorTim Kientzle <kientzle@gmail.com>
Mon, 19 Dec 2011 01:05:50 +0000 (20:05 -0500)
committerTim Kientzle <kientzle@gmail.com>
Mon, 19 Dec 2011 01:05:50 +0000 (20:05 -0500)
called from outside of this module.

SVN-Revision: 3943

Makefile.am
libarchive/archive.h
libarchive/archive_write_disk_posix.c
libarchive/archive_write_disk_windows.c
libarchive/test/CMakeLists.txt
libarchive/test/test_write_disk_lookup.c [new file with mode: 0644]

index 1cdaea063e1fd9c265d0b1ad7c1693f6be390dbf..5775432d03e022ca7e9eccbb0fa69a897d864683 100644 (file)
@@ -382,6 +382,7 @@ libarchive_test_SOURCES=                                    \
        libarchive/test/test_write_disk.c                       \
        libarchive/test/test_write_disk_failures.c              \
        libarchive/test/test_write_disk_hardlink.c              \
+       libarchive/test/test_write_disk_lookup.c                \
        libarchive/test/test_write_disk_perms.c                 \
        libarchive/test/test_write_disk_secure.c                \
        libarchive/test/test_write_disk_sparse.c                \
index c4fcd0c8dd0ef834eb552d0d0249fc68a4e6b0e5..14c2aed9897f55a6804115c1c9680bfeaac8e306 100644 (file)
@@ -724,6 +724,8 @@ __LA_DECL int archive_write_disk_set_user_lookup(struct archive *,
     void * /* private_data */,
     __LA_INT64_T (*)(void *, const char *, __LA_INT64_T),
     void (* /* cleanup */)(void *));
+__LA_DECL __LA_INT64_T archive_write_disk_gid(struct archive *, const char *, __LA_INT64_T);
+__LA_DECL __LA_INT64_T archive_write_disk_uid(struct archive *, const char *, __LA_INT64_T);
 
 /*
  * ARCHIVE_READ_DISK API
index 98356a9429e158ebaf2c74bce72bb2b8af936896..99afab2f635c814fe77ef581de6f8125f72a70e0 100644 (file)
@@ -286,8 +286,6 @@ static int  set_times(struct archive_write_disk *, int, int, const char *,
                    time_t, long, time_t, long, time_t, long, time_t, long);
 static int     set_times_from_entry(struct archive_write_disk *);
 static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
-static int64_t trivial_lookup_gid(void *, const char *, int64_t);
-static int64_t trivial_lookup_uid(void *, const char *, int64_t);
 static ssize_t write_data_block(struct archive_write_disk *,
                    const char *, size_t);
 
@@ -805,14 +803,14 @@ _archive_write_disk_finish_entry(struct archive *_a)
         * TODO: the TODO_SGID condition can be dropped here, can't it?
         */
        if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) {
-               a->uid = a->lookup_uid(a->lookup_uid_data,
+               a->uid = archive_write_disk_uid(&a->archive,
                    archive_entry_uname(a->entry),
                    archive_entry_uid(a->entry));
        }
        /* Look up the "real" GID only if we're going to need it. */
        /* TODO: the TODO_SUID condition can be dropped here, can't it? */
        if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) {
-               a->gid = a->lookup_gid(a->lookup_gid_data,
+               a->gid = archive_write_disk_gid(&a->archive,
                    archive_entry_gname(a->entry),
                    archive_entry_gid(a->entry));
         }
@@ -910,6 +908,9 @@ archive_write_disk_set_group_lookup(struct archive *_a,
        archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
            ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup");
 
+       if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
+               (a->cleanup_gid)(a->lookup_gid_data);
+
        a->lookup_gid = lookup_gid;
        a->cleanup_gid = cleanup_gid;
        a->lookup_gid_data = private_data;
@@ -926,12 +927,36 @@ archive_write_disk_set_user_lookup(struct archive *_a,
        archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
            ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup");
 
+       if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
+               (a->cleanup_uid)(a->lookup_uid_data);
+
        a->lookup_uid = lookup_uid;
        a->cleanup_uid = cleanup_uid;
        a->lookup_uid_data = private_data;
        return (ARCHIVE_OK);
 }
 
+int64_t
+archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
+{
+       struct archive_write_disk *a = (struct archive_write_disk *)_a;
+       archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+           ARCHIVE_STATE_ANY, "archive_write_disk_gid");
+       if (a->lookup_gid)
+               return (a->lookup_gid)(a->lookup_gid_data, name, id);
+       return (id);
+}
+int64_t
+archive_write_disk_uid(struct archive *_a, const char *name, int64_t id)
+{
+       struct archive_write_disk *a = (struct archive_write_disk *)_a;
+       archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+           ARCHIVE_STATE_ANY, "archive_write_disk_uid");
+       if (a->lookup_uid)
+               return (a->lookup_uid)(a->lookup_uid_data, name, id);
+       return (id);
+}
 
 /*
  * Create a new archive_write_disk object and initialize it with global state.
@@ -949,8 +974,6 @@ archive_write_disk_new(void)
        /* We're ready to write a header immediately. */
        a->archive.state = ARCHIVE_STATE_HEADER;
        a->archive.vtable = archive_write_disk_vtable();
-       a->lookup_uid = trivial_lookup_uid;
-       a->lookup_gid = trivial_lookup_gid;
        a->start_time = time(NULL);
        /* Query and restore the umask. */
        umask(a->user_umask = umask(0));
@@ -1386,10 +1409,8 @@ _archive_write_disk_free(struct archive *_a)
            ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free");
        a = (struct archive_write_disk *)_a;
        ret = _archive_write_disk_close(&a->archive);
-       if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
-               (a->cleanup_gid)(a->lookup_gid_data);
-       if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
-               (a->cleanup_uid)(a->lookup_uid_data);
+       archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL);
+       archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL);
        if (a->entry)
                archive_entry_free(a->entry);
        archive_string_free(&a->_name_data);
@@ -2571,13 +2592,13 @@ set_acl(struct archive_write_disk *a, int fd, const char *name,
                switch (ae_tag) {
                case ARCHIVE_ENTRY_ACL_USER:
                        acl_set_tag_type(acl_entry, ACL_USER);
-                       ae_uid = a->lookup_uid(a->lookup_uid_data,
+                       ae_uid = archive_write_disk_uid(&a->archive,
                            ae_name, ae_id);
                        acl_set_qualifier(acl_entry, &ae_uid);
                        break;
                case ARCHIVE_ENTRY_ACL_GROUP:
                        acl_set_tag_type(acl_entry, ACL_GROUP);
-                       ae_gid = a->lookup_gid(a->lookup_gid_data,
+                       ae_gid = archive_write_disk_gid(&a->archive,
                            ae_name, ae_id);
                        acl_set_qualifier(acl_entry, &ae_gid);
                        break;
@@ -2778,28 +2799,6 @@ set_xattrs(struct archive_write_disk *a)
 }
 #endif
 
-
-/*
- * Trivial implementations of gid/uid lookup functions.
- * These are normally overridden by the client, but these stub
- * versions ensure that we always have something that works.
- */
-static int64_t
-trivial_lookup_gid(void *private_data, const char *gname, int64_t gid)
-{
-       (void)private_data; /* UNUSED */
-       (void)gname; /* UNUSED */
-       return (gid);
-}
-
-static int64_t
-trivial_lookup_uid(void *private_data, const char *uname, int64_t uid)
-{
-       (void)private_data; /* UNUSED */
-       (void)uname; /* UNUSED */
-       return (uid);
-}
-
 /*
  * Test if file on disk is older than entry.
  */
index 92d54e041a0ae7638322c70904031117d7013a37..9df9ddc722bd63024e465827047f932efe70e57a 100644 (file)
@@ -236,8 +236,6 @@ static int  set_times(struct archive_write_disk *, HANDLE, int, const wchar_t *,
                    time_t, long, time_t, long, time_t, long, time_t, long);
 static int     set_times_from_entry(struct archive_write_disk *);
 static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
-static int64_t trivial_lookup_gid(void *, const char *, int64_t);
-static int64_t trivial_lookup_uid(void *, const char *, int64_t);
 static ssize_t write_data_block(struct archive_write_disk *,
                    const char *, size_t);
 
@@ -1090,14 +1088,14 @@ _archive_write_disk_finish_entry(struct archive *_a)
         * TODO: the TODO_SGID condition can be dropped here, can't it?
         */
        if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) {
-               a->uid = a->lookup_uid(a->lookup_uid_data,
+               a->uid = archive_write_disk_uid(&a->archive,
                    archive_entry_uname(a->entry),
                    archive_entry_uid(a->entry));
        }
        /* Look up the "real" GID only if we're going to need it. */
        /* TODO: the TODO_SUID condition can be dropped here, can't it? */
        if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) {
-               a->gid = a->lookup_gid(a->lookup_gid_data,
+               a->gid = archive_write_disk_gid(&a->archive,
                    archive_entry_gname(a->entry),
                    archive_entry_gid(a->entry));
         }
@@ -1182,6 +1180,9 @@ archive_write_disk_set_group_lookup(struct archive *_a,
        archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
            ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup");
 
+       if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
+               (a->cleanup_gid)(a->lookup_gid_data);
+
        a->lookup_gid = lookup_gid;
        a->cleanup_gid = cleanup_gid;
        a->lookup_gid_data = private_data;
@@ -1198,12 +1199,36 @@ archive_write_disk_set_user_lookup(struct archive *_a,
        archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
            ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup");
 
+       if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
+               (a->cleanup_uid)(a->lookup_uid_data);
+
        a->lookup_uid = lookup_uid;
        a->cleanup_uid = cleanup_uid;
        a->lookup_uid_data = private_data;
        return (ARCHIVE_OK);
 }
 
+int64_t
+archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
+{
+       struct archive_write_disk *a = (struct archive_write_disk *)_a;
+       archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+           ARCHIVE_STATE_ANY, "archive_write_disk_gid");
+       if (a->lookup_gid)
+               return (a->lookup_gid)(a->lookup_gid_data, name, id);
+       return (id);
+}
+int64_t
+archive_write_disk_uid(struct archive *_a, const char *name, int64_t id)
+{
+       struct archive_write_disk *a = (struct archive_write_disk *)_a;
+       archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+           ARCHIVE_STATE_ANY, "archive_write_disk_uid");
+       if (a->lookup_uid)
+               return (a->lookup_uid)(a->lookup_uid_data, name, id);
+       return (id);
+}
 
 /*
  * Create a new archive_write_disk object and initialize it with global state.
@@ -1221,8 +1246,6 @@ archive_write_disk_new(void)
        /* We're ready to write a header immediately. */
        a->archive.state = ARCHIVE_STATE_HEADER;
        a->archive.vtable = archive_write_disk_vtable();
-       a->lookup_uid = trivial_lookup_uid;
-       a->lookup_gid = trivial_lookup_gid;
        a->start_time = time(NULL);
        /* Query and restore the umask. */
        umask(a->user_umask = umask(0));
@@ -1671,10 +1694,8 @@ _archive_write_disk_free(struct archive *_a)
            ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free");
        a = (struct archive_write_disk *)_a;
        ret = _archive_write_disk_close(&a->archive);
-       if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
-               (a->cleanup_gid)(a->lookup_gid_data);
-       if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
-               (a->cleanup_uid)(a->lookup_uid_data);
+       archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL);
+       archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL);
        if (a->entry)
                archive_entry_free(a->entry);
        archive_wstring_free(&a->_name_data);
@@ -2459,28 +2480,6 @@ set_xattrs(struct archive_write_disk *a)
        return (ARCHIVE_OK);
 }
 
-
-/*
- * Trivial implementations of gid/uid lookup functions.
- * These are normally overridden by the client, but these stub
- * versions ensure that we always have something that works.
- */
-static int64_t
-trivial_lookup_gid(void *private_data, const char *gname, int64_t gid)
-{
-       (void)private_data; /* UNUSED */
-       (void)gname; /* UNUSED */
-       return (gid);
-}
-
-static int64_t
-trivial_lookup_uid(void *private_data, const char *uname, int64_t uid)
-{
-       (void)private_data; /* UNUSED */
-       (void)uname; /* UNUSED */
-       return (uid);
-}
-
 static void
 fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
 {
index 8bbe6a419e29fbb1e030aced0036e5525313892a..d9be74f1941950af8d9f49a8e6923f56d0bb7e82 100644 (file)
@@ -142,6 +142,7 @@ IF(ENABLE_TEST)
     test_write_disk.c
     test_write_disk_failures.c
     test_write_disk_hardlink.c
+    test_write_disk_lookup.c
     test_write_disk_perms.c
     test_write_disk_secure.c
     test_write_disk_sparse.c
diff --git a/libarchive/test/test_write_disk_lookup.c b/libarchive/test/test_write_disk_lookup.c
new file mode 100644 (file)
index 0000000..54a63bb
--- /dev/null
@@ -0,0 +1,140 @@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+static void
+group_cleanup(void *d)
+{
+       int *mp = d;
+       assertEqualInt(*mp, 0x13579);
+       *mp = 0x2468;
+}
+
+static int64_t
+group_lookup(void *d, const char *name, int64_t g)
+{
+       int *mp = d;
+       assertEqualInt(*mp, 0x13579);
+       if (strcmp(name, "FOOGROUP"))
+               return (1);
+       return (73);
+}
+
+static void
+user_cleanup(void *d)
+{
+       int *mp = d;
+       assertEqualInt(*mp, 0x1234);
+       *mp = 0x2345;
+}
+
+static int64_t
+user_lookup(void *d, const char *name, int64_t u)
+{
+       int *mp = d;
+       assertEqualInt(*mp, 0x1234);
+       if (strcmp("FOO", name) == 0)
+               return (2);
+       return (74);
+}
+
+DEFINE_TEST(test_write_disk_lookup)
+{
+       struct archive *a;
+       int gmagic = 0x13579, umagic = 0x1234;
+       int64_t id;
+
+       assert((a = archive_write_disk_new()) != NULL);
+
+       /* Default uname/gname lookups always return ID. */
+       assertEqualInt(0, archive_write_disk_gid(a, "", 0));
+       assertEqualInt(12, archive_write_disk_gid(a, "root", 12));
+       assertEqualInt(12, archive_write_disk_gid(a, "wheel", 12));
+       assertEqualInt(0, archive_write_disk_uid(a, "", 0));
+       assertEqualInt(18, archive_write_disk_uid(a, "root", 18));
+
+       /* Register some weird lookup functions. */
+       assertEqualInt(ARCHIVE_OK, archive_write_disk_set_group_lookup(a,
+                      &gmagic, &group_lookup, &group_cleanup));
+       /* Verify that our new function got called. */
+       assertEqualInt(73, archive_write_disk_gid(a, "FOOGROUP", 8));
+       assertEqualInt(1, archive_write_disk_gid(a, "NOTFOOGROUP", 8));
+
+       /* De-register. */
+       assertEqualInt(ARCHIVE_OK,
+                      archive_write_disk_set_group_lookup(a, NULL, NULL, NULL));
+       /* Ensure our cleanup function got called. */
+       assertEqualInt(gmagic, 0x2468);
+
+       /* Same thing with uname lookup.... */
+       assertEqualInt(ARCHIVE_OK, archive_write_disk_set_user_lookup(a,
+                          &umagic, &user_lookup, &user_cleanup));
+       assertEqualInt(2, archive_write_disk_uid(a, "FOO", 0));
+       assertEqualInt(74, archive_write_disk_uid(a, "NOTFOO", 1));
+       assertEqualInt(ARCHIVE_OK,
+           archive_write_disk_set_user_lookup(a, NULL, NULL, NULL));
+       assertEqualInt(umagic, 0x2345);
+
+       /* Try the standard lookup functions. */
+       if (archive_write_disk_set_standard_lookup(a) != ARCHIVE_OK) {
+               skipping("standard uname/gname lookup");
+       } else {
+               /* Try a few common names for group #0. */
+               id = archive_write_disk_gid(a, "wheel", 8);
+               if (id != 0)
+                       id = archive_write_disk_gid(a, "root", 8);
+               failure("Unable to verify lookup of group #0");
+               assertEqualInt(0, id);
+
+               /* Try a few common names for user #0. */
+               id = archive_write_disk_uid(a, "root", 8);
+               failure("Unable to verify lookup of user #0");
+               assertEqualInt(0, id);
+       }
+
+       /* Deregister again and verify the default lookups again. */
+       assertEqualInt(ARCHIVE_OK,
+           archive_write_disk_set_group_lookup(a, NULL, NULL, NULL));
+       assertEqualInt(ARCHIVE_OK,
+           archive_write_disk_set_user_lookup(a, NULL, NULL, NULL));
+       assertEqualInt(0, archive_write_disk_gid(a, "", 0));
+       assertEqualInt(0, archive_write_disk_uid(a, "", 0));
+
+       /* Re-register our custom handlers. */
+       gmagic = 0x13579;
+       umagic = 0x1234;
+       assertEqualInt(ARCHIVE_OK, archive_write_disk_set_group_lookup(a,
+                          &gmagic, &group_lookup, &group_cleanup));
+       assertEqualInt(ARCHIVE_OK, archive_write_disk_set_user_lookup(a,
+                     &umagic, &user_lookup, &user_cleanup));
+
+       /* Destroy the archive. */
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+
+       /* Verify our cleanup functions got called. */
+       assertEqualInt(gmagic, 0x2468);
+       assertEqualInt(umagic, 0x2345);
+}