sub validate_prune_backups {
my ($prune_backups) = @_;
- my $keep_all = delete $prune_backups->{'keep-all'};
+ my $res = { $prune_backups->%* };
- if (!scalar(grep {$_ > 0} values %{$prune_backups})) {
- $prune_backups = { 'keep-all' => 1 };
+ my $keep_all = delete $res->{'keep-all'};
+
+ if (scalar(grep { $_ > 0 } values %{$res}) == 0) {
+ $res = { 'keep-all' => 1 };
} elsif ($keep_all) {
die "keep-all cannot be set together with other options.\n";
}
- return $prune_backups;
+ return $res;
}
register_standard_option('prune-backups', {
description => "The retention options with shorter intervals are processed first " .
return ('images', $name, $vmid, undef, undef, $isBase, $format);
} elsif ($volname =~ m!^iso/([^/]+$PVE::Storage::iso_extension_re)$!) {
return ('iso', $1);
- } elsif ($volname =~ m!^vztmpl/([^/]+\.tar\.[gx]z)$!) {
+ } elsif ($volname =~ m!^vztmpl/([^/]+$PVE::Storage::vztmpl_extension_re)$!) {
return ('vztmpl', $1);
} elsif ($volname =~ m!^rootdir/(\d+)$!) {
return ('rootdir', $1, $1);
warn $@ if $@;
my $info = eval { decode_json($json) };
- warn "could not parse qemu-img info command output for '$filename'\n" if $@;
+ if (my $err = $@) {
+ warn "could not parse qemu-img info command output for '$filename' - $err\n";
+ return wantarray ? (undef, undef, undef, undef, $st->ctime) : undef;
+ }
my ($size, $format, $used, $parent) = $info->@{qw(virtual-size format actual-size backing-filename)};
- ($size) = ($size =~ /^(\d+)$/); #untaint
- ($used) = ($used =~ /^(\d+)$/); #untaint
- ($format) = ($format =~ /^([-\w]+)$/); #untaint
+ ($size) = ($size =~ /^(\d+)$/) or die "size '$size' not an integer\n"; # untaint
+ ($used) = ($used =~ /^(\d+)$/) or die "used '$used' not an integer\n"; # untaint
+ ($format) = ($format =~ /^(\S+)$/) or die "format '$format' includes whitespace\n"; # untaint
if (defined($parent)) {
- ($parent) = ($parent =~ /^(.*)$/); #untaint
+ ($parent) = ($parent =~ /^(\S+)$/) or die "parent '$parent' includes whitespace\n"; # untaint
}
return wantarray ? ($size, $format, $used, $parent, $st->ctime) : $size;
}
$info = { volid => "$sid:iso/$1", format => 'iso' };
} elsif ($tt eq 'vztmpl') {
- next if $fn !~ m!/([^/]+\.tar\.([gx]z))$!;
+ next if $fn !~ m!/([^/]+$PVE::Storage::vztmpl_extension_re)$!;
$info = { volid => "$sid:vztmpl/$1", format => "t$2" };
# Import data from a stream, creating a new or replacing or adding to an existing volume.
sub volume_import {
- my ($class, $scfg, $storeid, $fh, $volname, $format, $base_snapshot, $with_snapshots, $allow_rename) = @_;
+ my ($class, $scfg, $storeid, $fh, $volname, $format, $snapshot, $base_snapshot, $with_snapshots, $allow_rename) = @_;
die "volume import format '$format' not available for $class\n"
if $format !~ /^(raw|tar|qcow2|vmdk)\+size$/;
}
sub volume_import_formats {
- my ($class, $scfg, $storeid, $volname, $base_snapshot, $with_snapshots) = @_;
+ my ($class, $scfg, $storeid, $volname, $snapshot, $base_snapshot, $with_snapshots) = @_;
if ($scfg->{path} && !defined($base_snapshot)) {
my $format = ($class->parse_volname($volname))[6];
if ($with_snapshots) {