summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGuillem Jover <guillem@debian.org>2014-10-01 05:02:43 +0200
committerGuillem Jover <guillem@debian.org>2014-10-06 02:08:05 +0200
commitf71e02c8e913884bfbf9d97b58ded4591b823cdb (patch)
tree70fa51b9b04bc916fc92135ac796af7f5252f924 /lib
parentb59b7403a713f5f28ad16b61183197e4fba9a588 (diff)
downloaddpkg-f71e02c8e913884bfbf9d97b58ded4591b823cdb.tar.gz
libdpkg: Add new tar extractor test cases
Test the different supported tar formats, and verify that we can parse them correctly.
Diffstat (limited to 'lib')
-rw-r--r--lib/dpkg/test/.gitignore2
-rw-r--r--lib/dpkg/test/Makefile.am22
-rwxr-xr-xlib/dpkg/test/t-tar.t141
-rw-r--r--lib/dpkg/test/t-tarextract.c125
4 files changed, 287 insertions, 3 deletions
diff --git a/lib/dpkg/test/.gitignore b/lib/dpkg/test/.gitignore
index b096ff2a7..323b83d9d 100644
--- a/lib/dpkg/test/.gitignore
+++ b/lib/dpkg/test/.gitignore
@@ -13,6 +13,8 @@ t-pkg-queue
t-progname
t-string
t-subproc
+t-tar/
+t-tarextract
t-test
t-test-skip
t-trigger
diff --git a/lib/dpkg/test/Makefile.am b/lib/dpkg/test/Makefile.am
index 197f48200..5fca086c8 100644
--- a/lib/dpkg/test/Makefile.am
+++ b/lib/dpkg/test/Makefile.am
@@ -9,9 +9,13 @@ LDADD = \
$(top_builddir)/lib/dpkg/libdpkg.la \
$(LIBINTL)
+EXTRA_DIST = \
+ $(test_scripts) \
+ $(nil)
+
# The tests are sorted in order of increasing complexity.
-check_PROGRAMS = \
+test_programs = \
t-test \
t-test-skip \
t-macros \
@@ -31,8 +35,20 @@ check_PROGRAMS = \
t-pkg-list \
t-pkg-queue \
t-trigger \
- t-mod-db
+ t-mod-db \
+ $(nil)
+
+test_scripts = \
+ t-tar.t \
+ $(nil)
-test_programs = $(check_PROGRAMS)
+check_PROGRAMS = \
+ $(test_programs) \
+ t-tarextract \
+ $(nil)
+
+test_tmpdir = t.tmp
include $(top_srcdir)/check.am
+
+clean-local: check-clean
diff --git a/lib/dpkg/test/t-tar.t b/lib/dpkg/test/t-tar.t
new file mode 100755
index 000000000..bb536d964
--- /dev/null
+++ b/lib/dpkg/test/t-tar.t
@@ -0,0 +1,141 @@
+#!/usr/bin/perl
+#
+# Copyright © 2014 Guillem Jover <guillem@debian.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+use Test::More tests => 12;
+use Cwd;
+use File::Path qw(make_path remove_tree);
+use File::Temp qw(tempdir);
+use File::Spec;
+use File::Find;
+use POSIX qw(mkfifo);
+
+use Dpkg::IPC;
+
+use strict;
+use warnings;
+
+my $srcdir = $ENV{srcdir} || '.';
+my $builddir = $ENV{builddir} || '.';
+my $tmpdir = 't.tmp/t-tar';
+
+sub create {
+ my ($pathname) = @_;
+
+ open my $fh, '>>', $pathname or die "cannot touch $pathname: $!";
+ close $fh;
+}
+
+sub tar_create_tree {
+ my $type = shift;
+
+ my $long_a = 'a' x 29;
+ my $long_b = 'b' x 29;
+ my $long_c = 'c' x 29;
+ my $long_d = 'd' x 29;
+ my $long_e = 'e' x 29;
+ my $long_f = 'f' x 22;
+
+ # Popullate tar hierarchy
+ create('file');
+ link 'file', 'hardlink';
+
+ make_path("$long_a/$long_b/$long_c/$long_d/$long_e/");
+ make_path("$long_a/$long_b/$long_c/$long_d/$long_e/$long_f/");
+ create("$long_a/$long_b/$long_c/$long_d/$long_e/$long_f/long");
+ symlink "$long_a/$long_b/$long_c/$long_d/$long_e/$long_f/long",
+ 'symlink-long';
+
+ symlink 'file', 'symlink-a';
+ symlink 'hardlink', 'symlink-b';
+ symlink 'dangling', 'symlink-c';
+
+ mkdir 'directory';
+ mkfifo('fifo', 0770);
+
+ # FIXME: Need root.
+ # system 'mknod', 'chardev', 'c', '1', '3';
+ # system 'mknod', 'blockdev', 'b', '0', '0';
+}
+
+sub test_tar_extractor {
+ my $stdout;
+ my $stderr;
+
+ my $expected_tar = <<TAR;
+. mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir
+./fifo mode=10750 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=fifo
+./file mode=100644 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=file size=0
+./hardlink mode=100644 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=hardlink linkto=./file size=0
+./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir
+./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir
+./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir
+./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc/ddddddddddddddddddddddddddddd mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir
+./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc/ddddddddddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeee mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir
+./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc/ddddddddddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeee/ffffffffffffffffffffff mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir
+./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc/ddddddddddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeee/ffffffffffffffffffffff/long mode=100644 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=file size=0
+./directory mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir
+./symlink-a mode=120777 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=symlink linkto=file size=0
+./symlink-b mode=120777 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=symlink linkto=hardlink size=0
+./symlink-c mode=120777 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=symlink linkto=dangling size=0
+./symlink-long mode=120777 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=symlink linkto=aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc/ddddddddddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeee/ffffffffffffffffffffff/long size=0
+TAR
+
+ make_path($tmpdir);
+
+ my $cwd = cwd();
+
+ # Check generated tarballs.
+ foreach my $type (qw(v7 ustar oldgnu gnu)) {
+ my $dirtree = "$tmpdir/$type";
+ my @paths;
+
+ mkdir $dirtree;
+ chdir $dirtree;
+ tar_create_tree($type);
+ find({ no_chdir => 1, wanted => sub {
+ return if $type eq 'v7' and length > 99;
+ return if $type eq 'v7' and -l and length readlink > 99;
+ return if $type eq 'v7' and not (-f or -l or -d);
+ return if $type eq 'ustar' and length > 256;
+ return if $type eq 'ustar' and -l and length readlink > 100;
+ push @paths, $_;
+ },
+ preprocess => sub { my (@files) = sort @_; @files } }, '.');
+ chdir $cwd;
+
+ my $paths_list = join "\0", @paths;
+ spawn(exec => [ 'tar', '-cf', "$dirtree.tar", '--format', $type,
+ '-C', $dirtree, "--mtime=\@100000000",
+ "--owner=user:100", "--group=group:200",
+ '--null', '--no-unquote', '--no-recursion', '-T-' ],
+ wait_child => 1, from_string => \$paths_list);
+
+ my $expected = $expected_tar;
+ $expected =~ s/[ug]name=[^ ]+ //g if $type eq 'v7';
+ $expected =~ s/\n^.*fifo.*$//mg if $type eq 'v7';
+ $expected =~ s/\n^.*dddd.*$//mg if $type eq 'v7';
+ $expected =~ s/\n^.*symlink-long.*$//mg if $type eq 'ustar';
+
+ spawn(exec => [ './t-tarextract', "$dirtree.tar" ],
+ nocheck => 1, to_string => \$stdout, to_error => \$stderr);
+ ok($? == 0, "tar extractor $type should succeed");
+ is($stderr, undef, "tar extractor $type stderr is empty");
+ is($stdout, $expected, "tar extractor $type is ok");
+ }
+}
+
+test_tar_extractor();
diff --git a/lib/dpkg/test/t-tarextract.c b/lib/dpkg/test/t-tarextract.c
new file mode 100644
index 000000000..3a9f9f5fb
--- /dev/null
+++ b/lib/dpkg/test/t-tarextract.c
@@ -0,0 +1,125 @@
+/*
+ * libdpkg - Debian packaging suite library routines
+ * t-tarextract.c - test tar extractor
+ *
+ * Copyright © 2014 Guillem Jover <guillem@debian.org>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+#include <compat.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <dpkg/ehandle.h>
+#include <dpkg/fdio.h>
+#include <dpkg/tarfn.h>
+
+struct tar_context {
+ int tar_fd;
+};
+
+static int
+tar_read(void *ctx, char *buffer, int size)
+{
+ struct tar_context *tc = ctx;
+
+ return fd_read(tc->tar_fd, buffer, size);
+}
+
+static int
+tar_object(void *ctx, struct tar_entry *te)
+{
+ printf("%s mode=%o time=%ld.%.9d uid=%d gid=%d", te->name,
+ te->stat.mode, te->mtime, 0, te->stat.uid, te->stat.gid);
+ if (te->stat.uname)
+ printf(" uname=%s", te->stat.uname);
+ if (te->stat.gname)
+ printf(" gname=%s", te->stat.gname);
+
+ switch (te->type) {
+ case TAR_FILETYPE_FILE0:
+ case TAR_FILETYPE_FILE:
+ printf(" type=file size=%jd", te->size);
+ break;
+ case TAR_FILETYPE_HARDLINK:
+ printf(" type=hardlink linkto=%s size=%jd",
+ te->linkname, te->size);
+ break;
+ case TAR_FILETYPE_SYMLINK:
+ printf(" type=symlink linkto=%s size=%jd",
+ te->linkname, te->size);
+ break;
+ case TAR_FILETYPE_DIR:
+ printf(" type=dir");
+ break;
+ case TAR_FILETYPE_CHARDEV:
+ case TAR_FILETYPE_BLOCKDEV:
+ printf(" type=device id=%d.%d", major(te->dev), minor(te->dev));
+ break;
+ case TAR_FILETYPE_FIFO:
+ printf(" type=fifo");
+ break;
+ default:
+ ohshit("unexpected tar entry type '%c'", te->type);
+ }
+
+ printf("\n");
+
+ return 0;
+}
+
+struct tar_operations tar_ops = {
+ .read = tar_read,
+ .extract_file = tar_object,
+ .link = tar_object,
+ .symlink = tar_object,
+ .mkdir = tar_object,
+ .mknod = tar_object,
+};
+
+int
+main(int argc, char **argv)
+{
+ struct tar_context ctx;
+ const char *tar_name = argv[1];
+
+ setvbuf(stdout, NULL, _IOLBF, 0);
+
+ push_error_context();
+
+ if (tar_name) {
+ ctx.tar_fd = open(tar_name, O_RDONLY);
+ if (ctx.tar_fd < 0)
+ ohshite("cannot open file '%s'", tar_name);
+ } else {
+ ctx.tar_fd = STDIN_FILENO;
+ }
+
+ if (tar_extractor(&ctx, &tar_ops))
+ ohshite("extracting tar");
+
+ if (tar_name)
+ close(ctx.tar_fd);
+
+ pop_error_context(ehflag_normaltidy);
+
+ return 0;
+}