Commit | Line | Data |
---|---|---|
1479465f GJ |
1 | #!/usr/bin/perl |
2 | # | |
3 | # Copyright © 2014 Guillem Jover <guillem@debian.org> | |
4 | # | |
5 | # This program is free software; you can redistribute it and/or modify | |
6 | # it under the terms of the GNU General Public License as published by | |
7 | # the Free Software Foundation; either version 2 of the License, or | |
8 | # (at your option) any later version. | |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | # GNU General Public License for more details. | |
14 | # | |
15 | # You should have received a copy of the GNU General Public License | |
16 | # along with this program. If not, see <https://www.gnu.org/licenses/>. | |
17 | ||
18 | use Test::More; | |
19 | use Cwd; | |
20 | use File::Path qw(make_path remove_tree); | |
21 | use File::Temp qw(tempdir); | |
22 | use File::Spec; | |
23 | use File::Find; | |
24 | use POSIX qw(mkfifo); | |
25 | ||
26 | use Dpkg (); | |
27 | use Dpkg::IPC; | |
28 | ||
29 | use strict; | |
30 | use warnings; | |
31 | use version; | |
32 | ||
33 | my $srcdir = $ENV{srcdir} || '.'; | |
34 | my $builddir = $ENV{builddir} || '.'; | |
35 | my $tmpdir = 't.tmp/t-tarextract'; | |
36 | ||
37 | # We require GNU tar >= 1.27 for --owner=NAME:ID and --group=NAME:ID. | |
38 | my $tar_version = qx($Dpkg::PROGTAR --version 2>/dev/null); | |
39 | if ($tar_version and $tar_version =~ m/^tar \(GNU tar\) (\d+\.\d+)/ and | |
40 | qv("v$1") >= qv('v1.27')) | |
41 | { | |
42 | plan tests => 12; | |
43 | } else { | |
44 | plan skip_all => 'needs GNU tar >= 1.27'; | |
45 | } | |
46 | ||
47 | # Set a known umask. | |
48 | umask 0022; | |
49 | ||
50 | sub create { | |
51 | my ($pathname) = @_; | |
52 | ||
53 | open my $fh, '>>', $pathname or die "cannot touch $pathname: $!"; | |
54 | close $fh; | |
55 | } | |
56 | ||
57 | sub tar_create_tree { | |
58 | my $type = shift; | |
59 | ||
60 | my $long_a = 'a' x 29; | |
61 | my $long_b = 'b' x 29; | |
62 | my $long_c = 'c' x 29; | |
63 | my $long_d = 'd' x 29; | |
64 | my $long_e = 'e' x 29; | |
65 | my $long_f = 'f' x 22; | |
66 | ||
67 | # Populate tar hierarchy | |
68 | create('file'); | |
69 | link 'file', 'hardlink'; | |
70 | ||
71 | make_path("$long_a/$long_b/$long_c/$long_d/$long_e/"); | |
72 | make_path("$long_a/$long_b/$long_c/$long_d/$long_e/$long_f/"); | |
73 | create("$long_a/$long_b/$long_c/$long_d/$long_e/$long_f/long"); | |
74 | ||
75 | # POSIX specifies that symlinks have undefined permissions in their | |
76 | # mode, so their handling is system dependent. Linux does not honor | |
77 | # the umask for symlinks, other systems like GNU/Hurd or kFreeBSD do, | |
78 | # which means we get different results due to this. | |
79 | my $umask = umask 0; | |
80 | ||
81 | symlink "$long_a/$long_b/$long_c/$long_d/$long_e/$long_f/long", | |
82 | 'symlink-long'; | |
83 | symlink 'file', 'symlink-a'; | |
84 | symlink 'hardlink', 'symlink-b'; | |
85 | symlink 'dangling', 'symlink-c'; | |
86 | ||
87 | umask $umask; | |
88 | ||
89 | mkdir 'directory'; | |
90 | mkfifo('fifo', 0770); | |
91 | ||
92 | # FIXME: Need root. | |
93 | # system 'mknod', 'chardev', 'c', '1', '3'; | |
94 | # system 'mknod', 'blockdev', 'b', '0', '0'; | |
95 | } | |
96 | ||
97 | sub test_tar_extractor { | |
98 | my $stdout; | |
99 | my $stderr; | |
100 | ||
101 | my $expected_tar = <<'TAR'; | |
102 | . mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir | |
103 | ./fifo mode=10750 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=fifo | |
104 | ./file mode=100644 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=file size=0 | |
105 | ./hardlink mode=100644 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=hardlink linkto=./file size=0 | |
106 | ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir | |
107 | ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir | |
108 | ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir | |
109 | ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc/ddddddddddddddddddddddddddddd mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir | |
110 | ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc/ddddddddddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeee mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir | |
111 | ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc/ddddddddddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeee/ffffffffffffffffffffff mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir | |
112 | ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccc/ddddddddddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeee/ffffffffffffffffffffff/long mode=100644 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=file size=0 | |
113 | ./directory mode=40755 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=dir | |
114 | ./symlink-a mode=120777 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=symlink linkto=file size=0 | |
115 | ./symlink-b mode=120777 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=symlink linkto=hardlink size=0 | |
116 | ./symlink-c mode=120777 time=100000000.000000000 uid=100 gid=200 uname=user gname=group type=symlink linkto=dangling size=0 | |
117 | ./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 | |
118 | TAR | |
119 | ||
120 | make_path($tmpdir); | |
121 | ||
122 | my $cwd = cwd(); | |
123 | ||
124 | # Check generated tarballs. | |
125 | foreach my $type (qw(v7 ustar oldgnu gnu)) { | |
126 | my $dirtree = "$tmpdir/$type"; | |
127 | my @paths; | |
128 | ||
129 | mkdir $dirtree; | |
130 | chdir $dirtree; | |
131 | tar_create_tree($type); | |
132 | find({ no_chdir => 1, wanted => sub { | |
133 | return if $type eq 'v7' and length > 99; | |
134 | return if $type eq 'v7' and -l and length readlink > 99; | |
135 | return if $type eq 'v7' and not (-f or -l or -d); | |
136 | return if $type eq 'ustar' and length > 256; | |
137 | return if $type eq 'ustar' and -l and length readlink > 100; | |
138 | push @paths, $_; | |
139 | }, | |
140 | preprocess => sub { my (@files) = sort @_; @files } }, '.'); | |
141 | chdir $cwd; | |
142 | ||
143 | my $paths_list = join "\0", @paths; | |
144 | spawn(exec => [ $Dpkg::PROGTAR, '-cf', "$dirtree.tar", | |
145 | '--format', $type, | |
146 | '-C', $dirtree, '--mtime=@100000000', | |
147 | '--owner=user:100', '--group=group:200', | |
148 | '--null', '--no-unquote', '--no-recursion', '-T-' ], | |
149 | wait_child => 1, from_string => \$paths_list); | |
150 | ||
151 | my $expected = $expected_tar; | |
152 | $expected =~ s/[ug]name=[^ ]+ //g if $type eq 'v7'; | |
153 | $expected =~ s/\n^.*fifo.*$//mg if $type eq 'v7'; | |
154 | $expected =~ s/\n^.*dddd.*$//mg if $type eq 'v7'; | |
155 | $expected =~ s/\n^.*symlink-long.*$//mg if $type eq 'ustar'; | |
156 | ||
157 | spawn(exec => [ './c-tarextract', "$dirtree.tar" ], | |
158 | nocheck => 1, to_string => \$stdout, to_error => \$stderr); | |
159 | ok($? == 0, "tar extractor $type should succeed"); | |
160 | is($stderr, undef, "tar extractor $type stderr is empty"); | |
161 | is($stdout, $expected, "tar extractor $type is ok"); | |
162 | } | |
163 | } | |
164 | ||
165 | test_tar_extractor(); |