]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
IFC
authorTim Kientzle <kientzle@gmail.com>
Sun, 7 Sep 2008 21:25:57 +0000 (17:25 -0400)
committerTim Kientzle <kientzle@gmail.com>
Sun, 7 Sep 2008 21:25:57 +0000 (17:25 -0400)
SVN-Revision: 197

libarchive/archive_write_disk.c
libarchive/test/Makefile
libarchive/test/test_read_format_gtar_sparse.c
libarchive/test/test_write_disk_secure.c

index 40b4014435511b4a19a062a9b4a94a94537d8075..b385978f17dd3b884575dc77324de9c2371d3319 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 #include "archive_platform.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_disk.c,v 1.35 2008/09/05 06:13:11 kientzle Exp $");
+__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_disk.c,v 1.36 2008/09/07 05:22:33 kientzle Exp $");
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -907,14 +907,26 @@ restore_entry(struct archive_write_disk *a)
                 * We know something is in the way, but we don't know what;
                 * we need to find out before we go any further.
                 */
-               if (lstat(a->name, &a->st) != 0) {
+               int r = 0;
+               /*
+                * The SECURE_SYMLINK logic has already removed a
+                * symlink to a dir if the client wants that.  So
+                * follow the symlink if we're creating a dir.
+                */
+               if (S_ISDIR(a->mode))
+                       r = stat(a->name, &a->st);
+               /*
+                * If it's not a dir (or it's a broken symlink),
+                * then don't follow it.
+                */
+               if (r != 0 || !S_ISDIR(a->mode))
+                       r = lstat(a->name, &a->st);
+               if (r != 0) {
                        archive_set_error(&a->archive, errno,
                            "Can't stat existing object");
                        return (ARCHIVE_WARN);
                }
 
-               /* TODO: if it's a symlink... */
-
                /*
                 * NO_OVERWRITE_NEWER doesn't apply to directories.
                 */
index e3600165697749076e58fa5683235448ed480ee5..0bd338b0af958fc7b8654e960700e948a6ba9497 100644 (file)
@@ -1,4 +1,4 @@
-# $FreeBSD: src/lib/libarchive/test/Makefile,v 1.24 2008/08/25 06:08:22 kientzle Exp $
+# $FreeBSD: src/lib/libarchive/test/Makefile,v 1.25 2008/09/08 00:58:12 kientzle Exp $
 
 # Where to find the libarchive sources
 LA_SRCDIR=${.CURDIR}/..
@@ -89,7 +89,7 @@ CFLAGS+= -I${LA_SRCDIR} -I.
 # Uncomment to link against dmalloc
 #LDADD+= -L/usr/local/lib -ldmalloc
 #CFLAGS+= -I/usr/local/include -DUSE_DMALLOC
-#WARNS=6
+WARNS=6
 
 # Build libarchive_test and run it.
 check test: libarchive_test
index a8257f8922e54c481f698dac37f435b96b38f7bd..32aecf9e779671985ac6872ae34c0a85685fc489 100644 (file)
@@ -23,7 +23,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "test.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/test/test_read_format_gtar_sparse.c,v 1.9 2008/09/01 05:38:33 kientzle Exp $");
+__FBSDID("$FreeBSD: src/lib/libarchive/test/test_read_format_gtar_sparse.c,v 1.10 2008/09/08 00:58:12 kientzle Exp $");
 
 
 struct contents {
@@ -187,6 +187,7 @@ verify_archive_file(const char *name, struct archive_contents *ac)
        struct contents expect;
        /* data, size, offset of block read from archive. */
        struct contents actual;
+       const void *p;
        struct archive *a;
 
        extract_reference_file(name);
@@ -206,10 +207,10 @@ verify_archive_file(const char *name, struct archive_contents *ac)
 
                expect = *cts++;
                while (0 == (err = archive_read_data_block(a,
-                                (const void **)&actual.d,
-                                &actual.s, &actual.o))) {
+                                &p, &actual.s, &actual.o))) {
+                       actual.d = p;
                        while (actual.s > 0) {
-                               char c = *(const char *)actual.d;
+                               char c = *actual.d;
                                if(actual.o < expect.o) {
                                        /*
                                         * Any byte before the expected
index 67c6bc08e556fbecde5cd3fc68bba7e05f5a34b4..be7353053670f8f6b8ac293b7394988cb085f2a7 100644 (file)
@@ -23,7 +23,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "test.h"
-__FBSDID("$FreeBSD: src/lib/libarchive/test/test_write_disk_secure.c,v 1.5 2008/09/01 05:38:33 kientzle Exp $");
+__FBSDID("$FreeBSD: src/lib/libarchive/test/test_write_disk_secure.c,v 1.8 2008/09/07 23:59:27 kientzle Exp $");
 
 #define UMASK 022
 
@@ -105,6 +105,80 @@ DEFINE_TEST(test_write_disk_secure)
        archive_entry_free(ae);
        assert(0 == archive_write_finish_entry(a));
 
+       /*
+        * Without security checks, extracting a dir over a link to a
+        * dir should follow the link.
+        */
+       /* Create a symlink to a dir. */
+       assert((ae = archive_entry_new()) != NULL);
+       archive_entry_copy_pathname(ae, "link_to_dir3");
+       archive_entry_set_mode(ae, S_IFLNK | 0777);
+       archive_entry_set_symlink(ae, "dir");
+       archive_write_disk_set_options(a, 0);
+       assert(0 == archive_write_header(a, ae));
+       assert(0 == archive_write_finish_entry(a));
+       /* Extract a dir whose name matches the symlink. */
+       assert(archive_entry_clear(ae) != NULL);
+       archive_entry_copy_pathname(ae, "link_to_dir3");
+       archive_entry_set_mode(ae, S_IFDIR | 0777);
+       assert(0 == archive_write_header(a, ae));
+       assert(0 == archive_write_finish_entry(a));
+       /* Verify link was followed. */
+       assertEqualInt(0, lstat("link_to_dir3", &st));
+       assert(S_ISLNK(st.st_mode));
+       archive_entry_free(ae);
+
+       /*
+        * As above, but a broken link, so the link should get replaced.
+        */
+       /* Create a symlink to a dir. */
+       assert((ae = archive_entry_new()) != NULL);
+       archive_entry_copy_pathname(ae, "link_to_dir4");
+       archive_entry_set_mode(ae, S_IFLNK | 0777);
+       archive_entry_set_symlink(ae, "nonexistent_dir");
+       archive_write_disk_set_options(a, 0);
+       assert(0 == archive_write_header(a, ae));
+       assert(0 == archive_write_finish_entry(a));
+       /* Extract a dir whose name matches the symlink. */
+       assert(archive_entry_clear(ae) != NULL);
+       archive_entry_copy_pathname(ae, "link_to_dir4");
+       archive_entry_set_mode(ae, S_IFDIR | 0777);
+       assert(0 == archive_write_header(a, ae));
+       assert(0 == archive_write_finish_entry(a));
+       /* Verify link was replaced. */
+       assertEqualInt(0, lstat("link_to_dir4", &st));
+       assert(S_ISDIR(st.st_mode));
+       archive_entry_free(ae);
+
+       /*
+        * As above, but a link to a non-dir, so the link should get replaced.
+        */
+       /* Create a regular file and a symlink to it */
+       assert((ae = archive_entry_new()) != NULL);
+       archive_entry_copy_pathname(ae, "non_dir");
+       archive_entry_set_mode(ae, S_IFREG | 0777);
+       archive_write_disk_set_options(a, 0);
+       assert(0 == archive_write_header(a, ae));
+       assert(0 == archive_write_finish_entry(a));
+       /* Create symlink to the file. */
+       archive_entry_copy_pathname(ae, "link_to_dir5");
+       archive_entry_set_mode(ae, S_IFLNK | 0777);
+       archive_entry_set_symlink(ae, "non_dir");
+       archive_write_disk_set_options(a, 0);
+       assert(0 == archive_write_header(a, ae));
+       assert(0 == archive_write_finish_entry(a));
+       /* Extract a dir whose name matches the symlink. */
+       assert(archive_entry_clear(ae) != NULL);
+       archive_entry_copy_pathname(ae, "link_to_dir5");
+       archive_entry_set_mode(ae, S_IFDIR | 0777);
+       assert(0 == archive_write_header(a, ae));
+       assert(0 == archive_write_finish_entry(a));
+       /* Verify link was replaced. */
+       assertEqualInt(0, lstat("link_to_dir5", &st));
+       assert(S_ISDIR(st.st_mode));
+       archive_entry_free(ae);
+
+
 #if ARCHIVE_VERSION_NUMBER < 2000000
        archive_write_finish(a);
 #else