diff options
author | Guillem Jover <guillem@debian.org> | 2014-10-01 05:02:43 +0200 |
---|---|---|
committer | Guillem Jover <guillem@debian.org> | 2014-10-06 02:08:05 +0200 |
commit | f71e02c8e913884bfbf9d97b58ded4591b823cdb (patch) | |
tree | 70fa51b9b04bc916fc92135ac796af7f5252f924 /lib | |
parent | b59b7403a713f5f28ad16b61183197e4fba9a588 (diff) | |
download | dpkg-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/.gitignore | 2 | ||||
-rw-r--r-- | lib/dpkg/test/Makefile.am | 22 | ||||
-rwxr-xr-x | lib/dpkg/test/t-tar.t | 141 | ||||
-rw-r--r-- | lib/dpkg/test/t-tarextract.c | 125 |
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; +} |