ArcCheck.pm revision 1.7
1# ex:ts=8 sw=4:
2# $OpenBSD: ArcCheck.pm,v 1.7 2007/05/25 12:19:24 espie Exp $
3#
4# Copyright (c) 2005-2006 Marc Espie <espie@openbsd.org>
5#
6# Permission to use, copy, modify, and distribute this software for any
7# purpose with or without fee is hereby granted, provided that the above
8# copyright notice and this permission notice appear in all copies.
9#
10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18# Supplementary code to handle archives in the package context.
19# Contrarily to GNU-tar, we do not change the archive format, but by
20# convention,  the names LongName\d+ and LongLink\d correspond to names
21# too long to fit. The actual names reside in the PLIST, but the archive
22# is still a valid archive.
23#
24
25package OpenBSD::Ustar::Object;
26
27# match archive header name against PackingElement item
28sub check_name
29{
30	my ($self, $item) = @_;
31	return 1 if $self->{name} eq $item->{name};
32	if ($self->{name} =~ m/^LongName\d+$/) {
33		$self->{name} = $item->{name};
34		return 1;
35	}
36	return 0;
37}
38
39# match archive header link name against actual link names
40sub check_linkname
41{
42	my ($self, $linkname) = @_;
43	my $c = $self->{linkname};
44	if ($self->isHardLink && defined $self->{cwd}) {
45		$c = $self->{cwd}.'/'.$c;
46	}
47	return 1 if $c eq $linkname;
48	if ($self->{linkname} =~ m/^Long(?:Link|Name)\d+$/) {
49		$self->{linkname} = $linkname;
50		if ($self->isHardLink && defined $self->{cwd}) {
51			$self->{linkname} =~ s|^$self->{cwd}/||;
52		}
53		return 1;
54	}
55	return 0;
56}
57
58use POSIX;
59
60sub verify_modes
61{
62	my ($o, $item) = @_;
63	my $result = 1;
64
65	if (!defined $item->{owner} && !$o->isSymLink) {
66	    if ($o->{uname} ne 'root' && $o->{uname} ne 'bin') {
67		    print STDERR "Error: no \@owner for ",
68			$item->fullname, " (", $o->{uname}, ")\n";
69	    		$result = 0;
70	    }
71	}
72	if (!defined $item->{group} && !$o->isSymLink) {
73	    if ($o->{gname} ne 'bin' && $o->{gname} ne 'wheel') {
74		    print STDERR "Warning: no \@group for ",
75			$item->fullname, " (", $o->{gname}, ")\n";
76	    }
77	}
78	if (!defined $item->{mode} && $o->isFile) {
79	    if (($o->{mode} & (S_ISUID | S_ISGID | S_IWOTH)) != 0) {
80		    print STDERR "Error: weird mode for ",
81			$item->fullname, ": ",
82			sprintf("%4o", $o->{mode} & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID)), "\n";
83	    		$result = 0;
84	    }
85	}
86	return $result;
87}
88
89# copy long items, avoiding duplicate long names.
90sub copy_long
91{
92	my ($self, $wrarc) = @_;
93	if ($self->{name} =~ m/^LongName(\d+)$/) {
94		$wrarc->{name_index} = $1 + 1;
95	}
96	if (length($self->{name}) > MAXFILENAME+MAXPREFIX+1) {
97		$wrarc->{name_index} = 0 if !defined $wrarc->{name_index};
98		$entry->{name} = 'LongName'.$wrarc->{name_index}++;
99	}
100	$self->copy($wrarc);
101}
102
103package OpenBSD::Ustar;
104
105# prepare item and introduce long names where needed.
106sub prepare_long
107{
108	my ($self, $item) = @_;
109	my $filename = $item->{name};
110	my $entry = $self->prepare($filename);
111	if (!defined $entry->{uname}) {
112		die "No user name for ", $entry->{name}, " (uid ", $entry->{uid}, ")\n";
113	}
114	if (!defined $entry->{gname}) {
115		die "No group name for ", $entry->{name}, " (gid ", $entry->{gid}. "\n";
116	}
117	my ($prefix, $name) = split_name($entry->{name});
118	if (length($name) > MAXFILENAME || length($prefix) > MAXPREFIX) {
119		$self->{name_index} = 0 if !defined $self->{name_index};
120		$entry->{name} = 'LongName'.$self->{name_index}++;
121	}
122	if (length($entry->{linkname}) > MAXLINKNAME) {
123		$self->{linkname_index} = 0 if !defined $self->{linkname_index};
124		$entry->{linkname} = 'LongLink'.$self->{linkname_index}++;
125	}
126	return $entry;
127}
128
1291;
130