8 use Compress
::Zlib
qw(gzopen);
9 use Compress
::Bzip2
qw(bzopen);
11 use File
::Temp
qw(tempdir);
14 use POSIX
":sys_wait_h";
15 use Time
::HiRes
qw(usleep ualarm gettimeofday tv_interval);
16 use Archive
::Zip
qw(:CONSTANTS :ERROR_CODES);
25 'application/x-tar' => [ 'tar', \
&unpack_tar
, 1],
26 #'application/x-tar' => [ 'tar', \&generic_unpack ],
27 #'application/x-tar' => [ '7z', \&generic_unpack ],
28 'application/x-compressed-tar' => [ 'tar', \
&unpack_tar
, 1],
31 'application/x-cpio' => [ 'cpio', \
&unpack_tar
, 1],
32 #'application/x-cpio' => [ '7z', \&generic_unpack ],
35 #'application/zip' => [ 'zip', \&unpack_tar, 1],
36 'application/zip' => [ '7z', \
&generic_unpack
],
39 'application/x-7z-compressed' => [ '7z', \
&generic_unpack
],
42 'application/vnd.rar' => [ '7z', \
&generic_unpack
],
45 'application/x-arj' => [ '7z', \
&generic_unpack
],
48 'application/x-rpm' => [ '7z', \
&generic_unpack
],
51 'application/vnd.debian.binary-package' => [ 'ar', \
&unpack_tar
, 1],
54 'application/vnd.ms-cab-compressed' => [ '7z', \
&generic_unpack
],
57 'application/x-lha' => [ '7z', \
&generic_unpack
],
60 'application/vnd.ms-tnef' => [ 'tnef', \
&generic_unpack
],
63 'message/rfc822' => [ 'mime', \
&unpack_mime
],
65 ## CHM, Nsis - supported by 7z, but we currently do not
67 ##'application/x-zoo' - old format - no support
68 ##'application/x-ms-dos-executable' - exe should be blocked anyways - no support
69 ## application/x-arc - old format - no support
73 'application/gzip' => [ 'guzip', \
&uncompress_file
],
74 'application/x-compress' => [ 'uncompress', \
&uncompress_file
],
75 # 'application/x-compressed-tar' => [ 'guzip', \&uncompress_file ], # unpack_tar is faster
76 'application/x-tarz' => [ 'uncompress', \
&uncompress_file
],
77 'application/x-bzip' => [ 'bunzip2', \
&uncompress_file
],
78 'application/x-bzip-compressed-tar' => [ 'bunzip2', \
&uncompress_file
],
82 ## some helper methods
85 return ( $_[0] < $_[1]) ?
$_[0] : $_[1];
89 return ( $_[0] > $_[1]) ?
$_[0] : $_[1];
92 # STDERR is redirected to STDOUT by default
93 sub helper_pipe_open
{
94 my ($fh, $inputfilename, $errorfilename, @cmd) = @_;
96 my $pid = $fh->open ('-|');
98 die "unable to fork helper process: $!" if !defined $pid;
100 return $pid if ($pid != 0); # parent process simply returns
102 $inputfilename = '/dev/null' if !$inputfilename;
104 # same algorythm as used inside SA
106 my $fd = fileno (STDIN
);
108 POSIX
::close(0) if $fd != 0;
110 if (!open (STDIN
, "<$inputfilename")) {
115 $errorfilename = '&STDOUT' if !$errorfilename;
117 $fd = fileno(STDERR
);
119 POSIX
::close(2) if $fd != 2;
121 if (!open (STDERR
, ">$errorfilename")) {
132 die; # else -w complains
135 sub helper_pipe_consume
{
136 my ($cfh, $pid, $timeout, $bufsize, $callback) = @_;
139 run_with_timeout
($timeout, sub {
144 while (($count = $cfh->sysread ($buf, $bufsize)) > 0) {
145 &$callback ($buf, $count);
147 die "pipe read failed" if ($count < 0);
150 while (my $line = <$cfh>) {
159 # send TERM first if process still exits
161 kill (15, $pid) if kill (0, $pid);
163 # read remaining data, if any
165 while (($count = $cfh->sysread ($buf, $bufsize)) > 0) {
172 close ($cfh) || ($closeerr = $!);
176 if (kill (0, $pid)) {
178 kill (9, $pid); # terminate process
179 die "child '$pid' termination problems\n";
184 die "child '$pid' close failed - $closeerr\n" if $closeerr;
186 die "child '$pid' failed: $childstat\n" if $childstat;
189 sub run_with_timeout
{
190 my ($timeout, $code, @param) = @_;
192 die "got timeout\n" if $timeout <= 0;
201 local $SIG{ALRM
} = sub { $sigcount++; die "got timeout\n"; };
202 local $SIG{PIPE
} = sub { $sigcount++; die "broken pipe\n" };
203 local $SIG{__DIE__
}; # see SA bug 4631
205 $prev_alarm = alarm ($timeout);
207 $res = &$code (@param);
209 alarm 0; # avoid race conditions
214 alarm ($prev_alarm) if defined ($prev_alarm);
216 die "unknown error" if $sigcount && !$err; # seems to happen sometimes
223 # the unpacker object constructor
226 my ($type, %param) = @_;
231 $self->{tmpdir
} = $param{tmpdir
} || tempdir
(CLEANUP
=> 1);
232 $self->{starttime
} = [gettimeofday
];
233 $self->{timeout
} = $param{timeout
} || 3600*24;
235 # maxfiles: 0 = disabled
236 $self->{maxfiles
} = defined ($param{maxfiles
}) ?
$param{maxfiles
} : 1000;
238 $param{maxrec
} = 0 if !defined ($param{maxrec
});
239 if ($param{maxrec
} < 0) {
240 $param{maxrec
} = - $param{maxrec
};
241 $self->{maxrec_soft
} = 1; # do not die when limit reached
244 $self->{maxrec
} = $param{maxrec
} || 8; # 0 = disabled
245 $self->{maxratio
} = $param{maxratio
} || 0; # 0 = disabled
247 $self->{maxquota
} = $param{quota
} || 250*1024*1024; # 250 MB
249 $self->{ctonly
} = $param{ctonly
}; # only detect contained content types
253 $self->{ratioquota
} = 0;
258 $self->{debug
} = $param{debug
} || 0;
262 $self->{ufid
} = 0; # counter to creat unique file names
263 $self->{udid
} = 0; # counter to creat unique dir names
264 $self->{ulid
} = 0; # counter to creat unique link names
274 if ($self->{debug
}) {
275 system ("find '$self->{tmpdir}'");
278 rmtree
($self->{tmpdir
});
284 rmtree
($self->{tmpdir
});
288 sub uncompress_file
{
289 my ($self, $app, $filename, $newname, $csize, $filesize) = @_;
291 my $timeout = $self->check_timeout();
293 my $maxsize = $self->{quota
} - $self->{size
};
295 if ($self->{maxratio
}) {
296 $maxsize = min2
($maxsize, $filesize * $self->{maxratio
});
299 $self->add_glob_mime_type ($newname);
308 if ($app eq 'guzip' || $app eq 'bunzip2') {
314 # bzip provides a gz compatible interface
315 if ($app eq 'bunzip2') {
316 $self->{mime
}->{'application/x-bzip'} = 1;
317 $cfh = bzopen
("$filename", 'r');
318 die "bzopen '$filename' failed" if !$cfh;
320 $self->{mime
}->{'application/gzip'} = 1;
321 $cfh = gzopen
("$filename", 'rb');
322 die "gzopen '$filename' failed" if !$cfh;
325 run_with_timeout
($timeout, sub {
328 while (($count = $cfh->gzread ($buf, 128*1024)) > 0) {
331 $ct = xdg_mime_get_mime_type_for_data
($buf, $count);
334 $self->{mime
}->{$ct} = 1;
336 if (!is_archive
($ct)) {
339 # warning: this can lead to wrong size/quota test
340 last if $self->{ctonly
};
346 $self->check_comp_ratio ($filesize, $usize);
348 $self->check_quota (1, $usize, $csize);
351 $outfd = IO
::File-
>new;
353 if (!$outfd->open ($newname, O_CREAT
|O_EXCL
|O_WRONLY
, 0640)) {
354 die "unable to create file $newname: $!";
358 if (!$outfd->print ($buf)) {
359 die "unable to write '$newname' - $!";
372 } elsif ($app eq 'uncompress') {
374 $self->{mime
}->{'application/x-compress'} = 1;
377 my @cmd = ('/bin/gunzip', '-c', $filename);
378 my $cfh = IO
::File-
>new();
379 my $pid = helper_pipe_open
($cfh, '/dev/null', '/dev/null', @cmd);
381 helper_pipe_consume
($cfh, $pid, $timeout, 128*1024, sub {
382 my ($buf, $count) = @_;
384 $ct = xdg_mime_get_mime_type_for_data
($buf, $count) if (!$usize);
388 $self->check_comp_ratio ($filesize, $usize);
390 $self->check_quota (1, $usize, $csize);
393 $outfd = IO
::File-
>new;
395 if (!$outfd->open ($newname, O_CREAT
|O_EXCL
|O_WRONLY
, 0640)) {
396 die "unable to create file $newname: $!";
400 if (!$outfd->print ($buf)) {
401 die "unable to write '$newname' - $!";
410 $outfd->close () if $outfd;
417 $self->check_quota (1, $usize, $csize, 1);
419 $self->todo_list_add ($newname, $ct, $usize);
424 # calculate real filesystem space (needed by ext3 to store files/dirs)
426 my ($size, $isdir) = @_;
428 my $bs = 4096; # ext3 block size
430 $size = max2
($size, $bs) if $isdir; # dirs needs at least one block
432 return int (($size + $bs - 1) / $bs) * $bs; # round up to block size
436 my ($self, $filename, $ct, $size) = @_;
439 $self->{mime
}->{$ct} = 1;
440 if (is_archive
($ct)) {
441 push @{$self->{todo
}}, [$filename, $ct, $size];
449 my $elapsed = int (tv_interval
($self->{starttime
}));
450 my $timeout = $self->{timeout
} - $elapsed;
452 die "got timeout\n" if $timeout <= 0;
457 sub check_comp_ratio
{
458 my ($self, $compsize, $usize) = @_;
460 return if !$compsize || !$self->{maxratio
};
462 my $ratio = $usize/$compsize;
464 die "compresion ratio too large (> $self->{maxratio})"
465 if $ratio > $self->{maxratio
};
469 my ($self, $files, $size, $csize, $commit) = @_;
471 my $sizediff = $csize ?
$size - $csize : $size;
473 die "compresion ratio too large (> $self->{maxratio})"
474 if $self->{maxratio
} && (($self->{size
} + $sizediff) > $self->{ratioquota
});
476 die "archive too large (> $self->{quota})"
477 if ($self->{size
} + $sizediff) > $self->{quota
};
479 die "unexpected number of files '$files'" if $files <= 0;
481 $files-- if ($csize);
483 die "too many files in archive (> $self->{maxfiles})"
484 if $self->{maxfiles
} && (($self->{files
} + $files) > $self->{maxfiles
});
487 $self->{files
} += $files;
488 $self->{size
} += $sizediff;
493 sub add_glob_mime_type
{
494 my ($self, $filename) = @_;
496 if (my $ct = xdg_mime_get_mime_type_from_file_name
(basename
($filename))) {
497 $self->{mime
}->{$ct} = 1 if $ct ne 'application/octet-stream';
501 sub walk_mime_entity
{
502 my ($self, $entity) = @_;
507 my $ct = $entity->head->mime_attr ('content-type');
508 $self->{mime
}->{$ct} = 1 if $ct && length ($ct) < 256;
510 if (my $body = $entity->bodyhandle) {
511 my $path = $body->path;
516 foreach my $part ($entity->parts) {
517 if (my ($n, $s) = $self->walk_mime_entity ($part)) {
523 return ($count, $size);
528 my ($self, $app, $filename, $tmpdir, $csize, $filesize) = @_;
533 my $timeout = $self->check_timeout();
536 run_with_timeout
($timeout, sub {
538 # Create a new MIME parser:
539 my $parser = new MIME
::Parser
;
540 $parser->output_under ($tmpdir);
541 $parser->extract_nested_messages (1);
542 $parser->ignore_errors (1);
543 $parser->extract_uuencode (1);
544 $parser->filer->ignore_filename(1);
546 if ($self->{maxfiles
}) {
547 my $max = $self->{maxfiles
} - $self->{files
};
548 $parser->max_parts ($max);
551 my $entity = $parser->parse_open ($filename);
553 ($files, $size) = $self->walk_mime_entity ($entity);
562 $self->check_quota ($files, $size, $csize, 1); # commit sizes
569 my ($self, $app, $filename, $tmpdir, $csize, $filesize) = @_;
574 my $timeout = $self->check_timeout();
578 my $zip = Archive
::Zip-
>new ();
580 Archive
::Zip
::setErrorHandler
(sub { die @_ });
582 run_with_timeout
($timeout, sub {
584 my $status = $zip->read ($filename);
585 die "unable to open zip file '$filename'" if $status != AZ_OK
;
588 foreach my $mem ($zip->members) {
592 my $cm = $mem->compressionMethod();
593 die "unsupported zip compression method '$cm'\n"
594 if !(($cm == COMPRESSION_DEFLATED
||
595 $cm == COMPRESSION_STORED
));
597 die "encrypted archive detected\n"
598 if $mem->isEncrypted();
600 my $us = $mem->uncompressedSize();
602 next if $us <= 0; # skip zero size files
604 if ($mem->isDirectory) {
605 $size += realsize
($us, 1);
607 $size += realsize
($us);
610 $self->check_comp_ratio ($filesize, $size);
612 $self->check_quota ($files, $size, $csize);
614 next if $mem->isDirectory; # skip dirs
616 my $name = basename
($mem->fileName());
617 $name =~ s
|[^A-Za-z0-9\
.]|-|g
;
618 my $newfn = sprintf "$tmpdir/Z%08d_$name", $tid++;
620 $self->add_glob_mime_type ($name);
622 my $outfd = IO
::File-
>new;
623 if (!$outfd->open ($newfn, O_CREAT
|O_EXCL
|O_WRONLY
, 0640)) {
624 die "unable to create file $newfn: $!";
631 $mem->desiredCompressionMethod (COMPRESSION_STORED
);
633 $status = $mem->rewindData();
635 die "unable to rewind zip stream" if $status != AZ_OK
;
639 while ($status == AZ_OK
) {
640 ($outRef, $status) = $mem->readChunk();
641 die "unable to read zip member"
642 if ($status != AZ_OK
&& $status != AZ_STREAM_END
);
644 my $len = length ($$outRef);
646 $ct = xdg_mime_get_mime_type_for_data
($$outRef, $len) if (!$bytes);
647 $outfd->print ($$outRef) || die "write error during zip copy";
651 last if $status == AZ_STREAM_END
;
656 $self->todo_list_add ($newfn, $ct, $bytes);
676 $self->check_quota ($files, $size, $csize, 1); # commit sizes
682 my ($self, $app, $filename, $tmpdir, $csize, $filesize) = @_;
687 my $timeout = $self->check_timeout();
689 my $a = LibArchive
::archive_read_new
();
691 die "unable to create LibArchive object" if !$a;
693 LibArchive
::archive_read_support_format_all
($a);
694 LibArchive
::archive_read_support_compression_all
($a);
697 run_with_timeout
($timeout, sub {
699 if ((my $r = LibArchive
::archive_read_open_filename
($a, $filename, 10240))) {
700 die "LibArchive error: %s", LibArchive
::archive_error_string
($a);
705 my $r = LibArchive
::archive_read_next_header
($a, $entry);
707 last if ($r == LibArchive
::ARCHIVE_EOF
);
709 if ($r != LibArchive
::ARCHIVE_OK
) {
710 die "LibArchive error: %s", LibArchive
::archive_error_string
($a);
713 my $us = LibArchive
::archive_entry_size
($entry);
714 my $mode = LibArchive
::archive_entry_mode
($entry);
717 if (POSIX
::S_ISREG
($mode)) {
718 $rs = realsize
($us);
720 $rs = POSIX
::S_ISDIR
($mode) ? realsize
($us, 1) : 256;
725 $self->check_comp_ratio ($filesize, $size);
727 $self->check_quota ($files, $size, $csize);
729 next if POSIX
::S_ISDIR
($mode);
730 next if !POSIX
::S_ISREG
($mode);
732 my $name = basename
(LibArchive
::archive_entry_pathname
($entry));
733 $name =~ s
|[^A-Za-z0-9\
.]|-|g
;
734 my $newfn = sprintf "$tmpdir/A%08d_$name", $tid++;
736 $self->add_glob_mime_type ($name);
748 while (($len = LibArchive
::archive_read_data
($a, $buf, 128*1024)) > 0) {
751 if ($ct = xdg_mime_get_mime_type_for_data
($buf, $len)) {
752 $self->{mime
}->{$ct} = 1;
754 if (!is_archive
($ct)) {
756 last if $self->{ctonly
};
763 if (!$outfd) { # create only when needed
764 $outfd = IO
::File-
>new;
766 if (!$outfd->open ($newfn, O_CREAT
|O_EXCL
|O_WRONLY
, 0640)) {
767 die "unable to create file $newfn: $!";
771 if (!$outfd->print ($buf)) {
772 die "unable to write '$newfn' - $!";
776 die ("error reading archive (encrypted)\n")
780 $self->todo_list_add ($newfn, $ct, $bytes) if $todo;
785 $outfd->close () if $outfd;
797 LibArchive
::archive_read_close
($a);
798 LibArchive
::archive_read_finish
($a);
802 $self->check_quota ($files, $size, $csize, 1); # commit sizes
808 my ($self, $app, $filename, $tmpdir, $csize, $filesize) = @_;
813 my $timeout = $self->check_timeout();
816 my @restorecmd = ('/bin/false');
821 @listcmd = ('/bin/tar', '-tvf', $filename);
822 @restorecmd = ('/bin/tar', '-x', '--backup=number', "--transform='s,[^A-Za-z0-9\./],-,g'", '-o',
823 '-m', '-C', $tmpdir, '-f', $filename);
826 if ($line =~ m/^(\S)\S+\s+\S+\s+([\d,\.]+)\s+\S+/) {
827 my ($type, $bytes) = ($1, $2);
828 $bytes =~ s/[,\.]//g;
831 $bytes = realsize
($bytes, 1);
832 } elsif ($type eq '-') {
833 $bytes = realsize
($bytes);
835 $bytes = 256; # simple assumption
841 $self->check_comp_ratio ($filesize, $size);
842 $self->check_quota ($files, $size, $csize);
845 die "can't parse tar output: $line\n";
848 } elsif ($app eq '7z' || $app eq '7zsimple') {
849 # Note: set password to 'none' with '-pnone', to avoid reading from /dev/tty
850 @restorecmd = ('/usr/bin/7z', 'e', '-pnone', '-bd', '-y', '-aou', "-w$self->{tmpdir}", "-o$tmpdir", $filename);
852 @listcmd = ('/usr/bin/7z', 'l', '-slt', $filename);
854 my ($path, $folder, $bytes);
860 if ($line =~ m/^\s*\z/) {
861 if (defined ($path) && defined ($bytes)) {
862 $bytes = realsize
($bytes, $folder);
866 $self->check_comp_ratio ($filesize, $size);
867 $self->check_quota ($files, $size, $csize);
873 } elsif ($line =~ m/^Path = (.*)\z/s) {
875 } elsif ($line =~ m/^Size = (\d+)\z/s) {
877 } elsif ($line =~ m/^Folder = (\d+)\z/s) {
879 } elsif ($line =~ m/^Attributes = ([D\.][R\.][H\.][S\.][A\.])\z/s) {
880 $folder = 1 if $1 && substr ($1, 0, 1) eq 'D';
884 } elsif ($app eq 'tnef') {
885 @listcmd = ('/usr/bin/tnef', '-tv', '-f', $filename);
886 @restorecmd = ('/usr/bin/tnef', '-C', $tmpdir, '--number-backups', '-f', $filename);
892 if ($line =~ m!^\s*(\d+)\s*|\s*\d{4}/\d{1,2}/\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2}\s*|!) {
895 $bytes = realsize
($bytes);
899 $self->check_comp_ratio ($filesize, $size);
900 $self->check_quota ($files, $size, $csize);
902 die "can't parse tnef output\n";
908 die "unknown application '$app'";
913 my $cfh = IO
::File-
>new();
914 my $pid = helper_pipe_open
($cfh, '/dev/null', '/dev/null', @listcmd);
916 helper_pipe_consume
($cfh, $pid, $timeout, 0, $filter);
923 return if !$files; # empty archive
925 $self->check_quota ($files, $size, $csize, 1);
927 $timeout = $self->check_timeout();
929 my $cfh = IO
::File-
>new();
930 my $pid = helper_pipe_open
($cfh, '/dev/null', undef, @restorecmd);
931 helper_pipe_consume
($cfh, $pid, $timeout, 0, sub {
933 print "$app: $line" if $self->{debug
};
940 my ($self, $dirname, $level) = @_;
944 print "unpack dir '$dirname'\n" if $self->{debug
};
946 opendir(DIR
, $dirname) || die "can't opendir $dirname: $!";
950 while (defined ($name = readdir (DIR
))) {
951 my $path = "$dirname/$name";
952 my $st = lstat ($path);
955 die "no such file '$path' - $!";
956 } elsif (POSIX
::S_ISDIR
($st->mode)) {
957 next if ($name eq '.' || $name eq '..');
958 $self->unpack_dir ($path, $level);
959 } elsif (POSIX
::S_ISREG
($st->mode)) {
960 my $size = $st->size;
961 $self->__unpack_archive ($path, $level + 1, $size);
969 my ($self, $level) = @_;
971 my $ta = $self->{todo
};
974 foreach my $todo (@$ta) {
975 $self->__unpack_archive ($todo->[0], $level, $todo->[2], $todo->[1]);
979 sub __unpack_archive
{
980 my ($self, $filename, $level, $size, $ct) = @_;
982 $level = 0 if !$level;
984 $self->{levels
} = max2
($self->{levels
}, $level);
986 if ($self->{maxrec
} && ($level >= $self->{maxrec
})) {
987 return if $self->{maxrec_soft
};
988 die "max recursion limit reached\n";
991 die "undefined file size" if !defined ($size);
993 return if !$size; # nothing to do
996 $ct = PMG
::Utils
::magic_mime_type_for_file
($filename);
997 $self->add_glob_mime_type($filename);
1001 $self->{mime
}->{$ct} = 1;
1003 if (defined($decompressors->{$ct})) {
1005 my ($app, $code) = @{$decompressors->{$ct}};
1009 # we try to keep extension correctly
1010 my $tmp = basename
($filename);
1011 ($ct eq 'application/gzip') &&
1013 ($ct eq 'application/x-bzip') &&
1014 $tmp =~ s/\.bz2?\z//;
1015 ($ct eq 'application/x-compress') &&
1017 ($ct eq 'application/x-compressed-tar') &&
1018 $tmp =~ s/\.gz\z// || $tmp =~ s/\.tgz\z/.tar/;
1019 ($ct eq 'application/x-bzip-compressed-tar') &&
1020 $tmp =~ s/\.bz2?\z// || $tmp =~ s/\.tbz\z/.tar/;
1021 ($ct eq 'application/x-tarz') &&
1024 my $newname = sprintf "%s/DC_%08d_%s", $self->{tmpdir
}, ++$self->{ufid
}, $tmp;
1026 print "Decomp: $filename\n\t($ct) with $app to $newname\n"
1029 if (my $res = &$code($self, $app, $filename, $newname, $level ?
$size : 0, $size)) {
1030 unlink $filename if $level;
1031 $self->unpack_todo ($level + 1);
1034 } elsif (defined ($unpackers->{$ct})) {
1036 my ($app, $code, $ctdetect) = @{$unpackers->{$ct}};
1040 my $tmpdir = sprintf "%s/DIR_%08d", $self->{tmpdir
}, ++$self->{udid
};
1043 print "Unpack: $filename\n\t($ct) with $app to $tmpdir\n"
1046 if (my $res = &$code ($self, $app, $filename, $tmpdir, $level ?
$size : 0, $size)) {
1047 unlink $filename if $level;
1050 $self->unpack_todo ($level + 1);
1052 $self->unpack_dir ($tmpdir, $level);
1063 return defined($decompressors->{$ct}) || defined($unpackers->{$ct});
1068 # Description: unpacks an archive and records containing
1069 # content types (detected by magic numbers and file extension)
1070 # Extracted files are stored inside 'tempdir'.
1072 # returns: true if file is archive, undef otherwhise
1074 sub unpack_archive
{
1075 my ($self, $filename, $ct) = @_;
1077 my $st = lstat($filename);
1081 die "no such file '$filename' - $!";
1082 } elsif (POSIX
::S_ISREG
($st->mode)) {
1085 return if !$size; # do nothing
1087 $self->{quota
} = $self->{maxquota
} - $self->{size
};
1089 $self->{ratioquota
} = $size * $self->{maxratio
} if $self->{maxratio
};
1092 return; # do nothing
1095 $ct = PMG
::Utils
::magic_mime_type_for_file
($filename) if !$ct;
1097 return if (!$ct || !is_archive
($ct)); # not an archive
1100 $self->__unpack_archive($filename, 0, $st->size, $ct);
1105 printf "ELAPSED: %.2f ms $filename\n",
1106 int(tv_interval
($self->{starttime
}) * 1000)
1110 $self->{mime
}->{'proxmox/unreadable-archive'} = 1;