[PATCH pve-storage v1 20/54] api: status: simplify file content assertion logic for up-/download

Max R. Carrara
2026-04-22T11:18:27Z

Create another helper for the file content assertion logic in the
upload / download_url API methods. Absorb the `assert_ova_contents()`
helper along the way, since it does not need to be standalone anymore.

Signed-off-by: Max R. Carrara <m.carrara@proxmox.com>
---
src/PVE/API2/Storage/Status.pm | 89 ++++++++++++----------------------
1 file changed, 32 insertions(+), 57 deletions(-)

diff --git a/src/PVE/API2/Storage/Status.pm b/src/PVE/API2/Storage/Status.pm
index 3a798899..2b0b121a 100644
--- a/src/PVE/API2/Storage/Status.pm
+++ b/src/PVE/API2/Storage/Status.pm
@@ -102,25 +102,40 @@ my sub parse_transferred_file_path_extension : prototype($$) {
die "upload / download: failed to parse '$path' - unhandled content type '$vtype'\n";
}

-my sub assert_ova_contents {
- my ($file) = @_;
+my sub assert_file_transfer_contents_valid : prototype($$$) {
+ my ($path, $vtype, $extension) = @_;

- # test if it's really a tar file with an ovf file inside
- my $hasOvf = 0;
- run_command(
- ['tar', '-t', '-f', $file],
- outfunc => sub {
- my ($line) = @_;
+ if ($vtype eq 'iso') {
+ PVE::Storage::assert_iso_content($path);
+ return;
+ }

- if ($line =~ m/\.ovf$/) {
- $hasOvf = 1;
- }
- },
- );
+ if ($vtype eq 'import') {
+ if ($extension eq 'ova') {
+ # test if it's really a tar file with an ovf file inside
+ my $hasOvf = 0;
+ run_command(
+ ['tar', '-t', '-f', $path],
+ outfunc => sub {
+ my ($line) = @_;

- die "ova archive has no .ovf file inside\n" if !$hasOvf;
+ if ($line =~ m/\.ovf$/) {
+ $hasOvf = 1;
+ }
+ },
+ );

- return 1;
+ die "ova archive has no .ovf file inside\n" if !$hasOvf;
+ return;
+ }
+
+ my $is_untrusted = 1;
+ my $timeout = 10;
+
+ PVE::Storage::file_size_info($path, $timeout, $extension, $is_untrusted);
+
+ return;
+ }
}

__PACKAGE__->register_method({
@@ -645,18 +660,7 @@ __PACKAGE__->register_method({
die "temporary file '$tmpfilename' does not exist\n" if !defined($size);

my $filename = PVE::Storage::normalize_content_filename($param->{filename});
-
- my $is_ova = 0;
- my $image_format;
-
my $extension = parse_transferred_file_path_extension($filename, $content);
-
- if ($extension eq 'ova') {
- $is_ova = 1;
- } else {
- $image_format = $extension;
- }
-
my $path = plugin_get_vtype_subdir($scfg, $content);

my $dest = "$path/$filename";
@@ -725,16 +729,7 @@ __PACKAGE__->register_method({
}
}

- if ($content eq 'iso') {
- PVE::Storage::assert_iso_content($tmpfilename);
- }
-
- if ($is_ova) {
- assert_ova_contents($tmpfilename);
- } elsif (defined($image_format)) {
- # checks untrusted image
- PVE::Storage::file_size_info($tmpfilename, 10, $image_format, 1);
- }
+ assert_file_transfer_contents_valid($tmpfilename, $content, $extension);
};
if (my $err = $@) {
# unlinks only the temporary file from the http server
@@ -859,18 +854,7 @@ __PACKAGE__->register_method({
assert_can_transfer_files($scfg, $storage, $content);

my $filename = PVE::Storage::normalize_content_filename($param->{filename});
-
- my $is_ova = 0;
- my $image_format;
-
my $extension = parse_transferred_file_path_extension($filename, $content);
-
- if ($extension eq 'ova') {
- $is_ova = 1;
- } else {
- $image_format = $extension;
- }
-
my $path = plugin_get_vtype_subdir($scfg, $content);

PVE::Storage::activate_storage($cfg, $storage);
@@ -893,16 +877,7 @@ __PACKAGE__->register_method({
$opts->{assert_file_validity} = sub {
my ($tmp_path) = @_;

- if ($content eq 'iso') {
- PVE::Storage::assert_iso_content($tmp_path);
- }
-
- if ($is_ova) {
- assert_ova_contents($tmp_path);
- } elsif (defined($image_format)) {
- # checks untrusted image
- PVE::Storage::file_size_info($tmp_path, 10, $image_format, 1);
- }
+ assert_file_transfer_contents_valid($tmp_path, $content, $extension);
};

my $worker = sub {
--
2.47.3