aboutsummaryrefslogtreecommitdiff
blob: 9bc0fd6a3dc90ead35caa58b68748ad088865e48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/perl -w
# Copyright 2019 Gentoo Authors; Distributed under the GPL v2
# Trivial tool to modify the path strings of files in a tarball, WITHOUT
# unpacking the tarball.
use strict;
use warnings;
#use re 'strict'; # This fails if the modifiers are empty
use Getopt::Long;
use File::Temp qw/tempfile/;
use File::Basename;
use Archive::Tar::Stream;

my $input_filename;
my $output_filename;
my $regex;
my $verbose = 0;
#my ($t, $t2, $r);

GetOptions(
	"i|input-filename=s" => \$input_filename,
	"o|output-filename=s" => \$output_filename,
	"r|regex-replacement=s" => \$regex,
	"v|verbose" => \$verbose,
	#"t|test-string=s" => \$t,
) or die("Error in args");

die("--input-filename=... is required") unless -e $input_filename;
die("--output-filename=... is required") unless defined $output_filename;
die("--regex=... is required") unless defined $regex;
$regex =~ /^(?<op>s)(?<sep>.)(?<match>.*)\g{sep}(?<replacement>.*)\g{sep}(?<mod>[a-zA-Z0-9]*)$/;
my $regex_op = $+{op};
my $regex_match = $+{match};
my $regex_replacement = $+{replacement};
my $regex_mod = $+{mod};
die("--regex=$regex is not valid") unless defined $regex_op and defined $regex_match and defined $regex_replacement and defined $regex_mod;
die "Refusing unsafe/unknown regex modifiers" unless $regex_mod=~/^[msixpodualng]*$/;

die("Refusing to overwrite") if $input_filename eq $output_filename;

#printf "op %s\n", $regex_op;
#printf "match %s\n", $regex_match;
#printf "replacement %s\n", $regex_replacement;
#printf "mod %s\n", $regex_mod;

#my $infh = IO::File->new("zcat $infile |") || die "oops";
#my $outfh = IO::File->new("| gzip > $outfile") || die "double oops";
open(my $infh, '<', $input_filename);
my ($outfh, $temp_filename) = tempfile(
	sprintf('.%s.XXXXXXXX', basename($output_filename)),
	DIR => dirname($output_filename),
	UNLINK => 1,
);


my $ts = Archive::Tar::Stream->new(infh => $infh, outfh => $outfh);
my $success = 0;
$Archive::Tar::Stream::VERBOSE = $verbose;
$ts->StreamCopy(sub {
    my ($header, $outpos, $fh) = @_;

	$header->{name} =~ s/(?${regex_mod})${regex_match}/${regex_replacement}/;
	#printf "%s => %s\n", $header->{name}, $newheader->{name};

	return 'KEEP', $header;
});
$success = 1;

close($infh);

END {
	if($success == 1) {
		rename $temp_filename, $output_filename or do {
			unlink $temp_filename;
			die("Failed to rename temporary file to destination name");
		}
	}
	# Cleanup in other case
	unlink $temp_filename if -e $temp_filename;
	close $outfh;
}