⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uzip.in

📁 MC Linux/Unix 终端下文件管理器
💻 IN
字号:
#! @PERL@ -w## zip file archive Virtual File System for Midnight Commander# Version 1.4.0 (2001-08-07).## (C) 2000-2001  Oskar Liljeblad <osk@hem.passagen.se>.#use POSIX;use File::Basename;use strict;## Configuration options## Location of the zip programmy $app_zip = "@ZIP@";# Location of the unzip programmy $app_unzip = "@UNZIP@";# Set this to 1 if zipinfo (unzip -Z) is to be used (recommended), otherwise 0.my $op_has_zipinfo = @HAVE_ZIPINFO@;# Command used to list archives (zipinfo mode)my $cmd_list_zi = "$app_unzip -Z -l -T";# Command used to list archives (non-zipinfo mode)my $cmd_list_nzi = "$app_unzip -qq -v";# Command used to add a file to the archivemy $cmd_add = "$app_zip -g";# Command used to add a link file to the archive (unused)my $cmd_addlink = "$app_zip -g -y";# Command used to delete a file from the archivemy $cmd_delete = "$app_zip -d";# Command used to extract a file to standard outmy $cmd_extract = "$app_unzip -p";## Main code#die "uzip: missing command and/or archive arguments\n" if ($#ARGV < 1);# Initialization of some global variablesmy $cmd = shift;my %known = ( './' => 1 );my %pending = ();my $oldpwd = POSIX::getcwd();my $archive = shift;my $aarchive = absolutize($archive, $oldpwd);my $cmd_list = ($op_has_zipinfo ? $cmd_list_zi : $cmd_list_nzi);my ($qarchive, $aqarchive) = map (quotemeta, $archive, $aarchive);if ($cmd eq 'list')    { &mczipfs_list(@ARGV); }if ($cmd eq 'rm')      { &mczipfs_rm(@ARGV); }if ($cmd eq 'rmdir')   { &mczipfs_rmdir(@ARGV); }if ($cmd eq 'mkdir')   { &mczipfs_mkdir(@ARGV); }if ($cmd eq 'copyin')  { &mczipfs_copyin(@ARGV); }if ($cmd eq 'copyout') { &mczipfs_copyout(@ARGV); }if ($cmd eq 'run')		 { &mczipfs_run(@ARGV); }#if ($cmd eq 'mklink')  { &mczipfs_mklink(@ARGV); }		# Not supported by MC extfs#if ($cmd eq 'linkout') { &mczipfs_linkout(@ARGV); }	# Not supported by MC extfsexit 1;# Remove a file from the archive.sub mczipfs_rm {	my ($qfile) = map { &zipquotemeta($_) } @_;	&checkargs(1, 'archive file', @_);	&safesystem("$cmd_delete $qarchive $qfile >/dev/null");	exit;}# Remove an empty directory from the archive.# The only difference from mczipfs_rm is that we append an # additional slash to the directory name to remove. I am not# sure this is absolutely necessary, but it doesn't hurt.sub mczipfs_rmdir {	my ($qfile) = map { &zipquotemeta($_) } @_;	&checkargs(1, 'archive directory', @_);	&safesystem("$cmd_delete $qarchive $qfile/ >/dev/null", 12);  exit;}# Extract a file from the archive.# Note that we don't need to check if the file is a link,# because mc apparently doesn't call copyout for symbolic links.sub mczipfs_copyout {	my ($qafile, $qfsfile) = map { &zipquotemeta($_) } @_;	&checkargs(1, 'archive file', @_);	&checkargs(2, 'local file', @_);	&safesystem("$cmd_extract $qarchive $qafile > $qfsfile", 11);  exit;}# Add a file to the archive.# This is done by making a temporary directory, in which# we create a symlink the original file (with a new name).# Zip is then run to include the real file in the archive,# with the name of the symbolic link.# Here we also doesn't need to check for symbolic links,# because the mc extfs doesn't allow adding of symbolic# links.sub mczipfs_copyin {	my ($afile, $fsfile) = @_;	&checkargs(1, 'archive file', @_);	&checkargs(2, 'local file', @_);	my ($qafile) = quotemeta $afile;	$fsfile = &absolutize($fsfile, $oldpwd);	my $adir = File::Basename::dirname($afile);	my $tmpdir = &mktmpdir();	chdir $tmpdir || &croak("chdir $tmpdir failed");	&mkdirs($adir, 0700);	symlink ($fsfile, $afile) || &croak("link $afile failed");	&safesystem("$cmd_add $aqarchive $qafile >/dev/null");	unlink $afile || &croak("unlink $afile failed");	&rmdirs($adir);	chdir $oldpwd || &croak("chdir $oldpwd failed");	rmdir $tmpdir || &croak("rmdir $tmpdir failed");  exit;}# Add an empty directory the the archive.# This is similar to mczipfs_copyin, except that we don't need# to use symlinks.sub mczipfs_mkdir {	my ($dir) = @_;	&checkargs(1, 'directory', @_);	my ($qdir) = quotemeta $dir;	my $tmpdir = &mktmpdir();	chdir $tmpdir || &croak("chdir $tmpdir failed");	&mkdirs($dir, 0700);	&safesystem("$cmd_add $aqarchive $qdir >/dev/null");	&rmdirs($dir);	chdir $oldpwd || &croak("chdir $oldpwd failed");	rmdir $tmpdir || &croak("rmdir $tmpdir failed");  exit;}# Add a link to the archive. This operation is not used yet,# because it is not supported by the MC extfs.sub mczipfs_mklink {	my ($linkdest, $afile) = @_;	&checkargs(1, 'link destination', @_);	&checkargs(2, 'archive file', @_);	my ($qafile) = quotemeta $afile;	my $adir = File::Basename::dirname($afile);	my $tmpdir = &mktmpdir();	chdir $tmpdir || &croak("chdir $tmpdir failed");	&mkdirs($adir, 0700);	symlink ($linkdest, $afile) || &croak("link $afile failed");	&safesystem("$cmd_addlink $aqarchive $qafile >/dev/null");	unlink $afile || &croak("unlink $afile failed");	&rmdirs($adir);	chdir $oldpwd || &croak("chdir $oldpwd failed");	rmdir $tmpdir || &croak("rmdir $tmpdir failed");  exit;}# This operation is not used yet, because it is not# supported by the MC extfs.sub mczipfs_linkout {	my ($afile, $fsfile) = @_;	&checkargs(1, 'archive file', @_);	&checkargs(2, 'local file', @_);	my ($qafile) = map { &zipquotemeta($_) } $afile;	my $linkdest = &get_link_destination($afile);	symlink ($linkdest, $fsfile) || &croak("link $fsfile failed");  exit;}# Use unzip to find the link destination of a certain file in the# archive.sub get_link_destination {	my ($afile) = @_;	my ($qafile) = map { &zipquotemeta($_) } $afile;	my $linkdest = safeticks("$cmd_extract $qarchive $qafile");	&croak ("extract failed", "link destination of $afile not found")			if (!defined $linkdest || $linkdest eq '');	return $linkdest;}# List files in the archive.# Because mc currently doesn't allow a file's parent directory# to be listed after the file itself, we need to do some# rearranging of the output. Most of this is done in# checked_print_file.sub mczipfs_list {	open (PIPE, "$cmd_list $qarchive |") || &croak("$app_unzip failed");	if ($op_has_zipinfo) {		while (<PIPE>) {			chomp;			next if /^Archive:/;			next if /^\d+ file/;			next if /^Empty zipfile\.$/;			my @match = /^(.{10}) +([\d.]+) +([a-z\d]+) +(\d+) +([^ ]{2}) +(\d+) +([^ ]{4}) +(\d{4})(\d\d)(\d\d)\.(\d\d)(\d\d)(\d\d) +(.*)$/;			next if ($#match != 13);			&checked_print_file(@match);		}	} else {		while (<PIPE>) {			chomp;			my @match = /^ +(\d+) +([^ ]+) +(\d+) +(\d+\%) +(\d?\d)-(\d?\d)-(\d\d) (\d?\d):(\d\d) +([0-9a-f]+) +(.*)$/;			next if ($#match != 10);			my @rmatch = ('', '', 'unknown', $match[0], '', $match[2], $match[1],					$match[6] + ($match[6] < 70 ? 2000 : 1900), $match[4], $match[5],					$match[7], $match[8], "00", $match[10]);			&checked_print_file(@rmatch);		}	}	if (!close (PIPE)) {		&croak("$app_unzip failed") if ($! != 0);		&croak("$app_unzip failed", 'non-zero exit status ('.($? >> 8).')') 	}	foreach my $key (sort keys %pending) {		foreach my $file (@{ $pending{$key} }) {			&print_file(@{ $file });		}	}  exit;}# Execute a file in the archive, by first extracting it to a# temporary directory. The name of the extracted file will be# the same as the name of it in the archive.sub mczipfs_run {	my ($afile) = @_;	&checkargs(1, 'archive file', @_);	my $qafile = &zipquotemeta($afile);	my $tmpdir = &mktmpdir();	my $tmpfile = File::Basename::basename($afile);	chdir $tmpdir || &croak("chdir $tmpdir failed");	&safesystem("$cmd_extract $aqarchive $qafile > $tmpfile");  chmod 0700, $tmpfile;	&safesystem("./$tmpfile");	unlink $tmpfile || &croak("rm $tmpfile failed");	chdir $oldpwd || &croak("chdir $oldpwd failed");	rmdir $tmpdir || &croak("rmdir $tmpdir failed");  exit;}# This is called prior to printing the listing of a file.# A check is done to see if the parent directory of the file has already# been printed or not. If it hasn't, we must cache it (in %pending) and# print it later once the parent directory has been listed. When all# files have been processed, there may still be some that haven't been # printed because their parent directories weren't listed at all. These# files are dealt with in mczipfs_list.sub checked_print_file {	my @waiting = ([ @_ ]);	while ($#waiting != -1) {		my $item = shift @waiting;		my $filename = ${$item}[13];		my $dirname = File::Basename::dirname($filename) . '/';		if (exists $known{$dirname}) {			&print_file(@{$item});			if ($filename =~ /\/$/) {				$known{$filename} = 1;				if (exists $pending{$filename}) {					push @waiting, @{ $pending{$filename} };					delete $pending{$filename};				}			}		} else {			push @{$pending{$dirname}}, $item;		}	}}# Print the mc extfs listing of a file from a set of parsed fields.# If the file is a link, we extract it from the zip archive and# include the output as the link destination. Because this output# is not newline terminated, we must execute unzip once for each# link file encountered.sub print_file {	my ($perms,$zipver,$platform,$realsize,$format,$cmpsize,$comp,$year,$mon,$day,$hours,$mins,$secs,$filename) = @_;	$mon = (qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/)[$mon-1];	if ($platform ne 'unx') {		$perms = ($filename =~ /\/$/ ? 'drwxr-xr-x' : '-rw-r--r--');	}	printf "%-10s    1 %-8d %-8d %8d %s %s %s %s:%s %s", $perms, $<,		$(, $realsize, $mon, $day, $year, $hours, $mins, $filename;	if ($platform eq 'unx' && $perms =~ /^l/) {		my $linkdest = &get_link_destination($filename);		print " -> $linkdest";	}	print "\n";}# Die with a reasonable error message.sub croak {	my ($command, $desc) = @_;	die "uzip ($cmd): $command - $desc\n" if (defined $desc);	die "uzip ($cmd): $command - $!\n";}# Make a set of directories, like the command `mkdir -p'.# This subroutine has been tailored for this script, and# because of that, it ignored the directory name '.'.sub mkdirs {	my ($dirs, $mode) = @_;	$dirs = &cleandirs($dirs);	return if ($dirs eq '.');	my $newpos = -1;	while (($newpos = index($dirs, '/', $newpos+1)) != -1) {		my $dir = substr($dirs, 0, $newpos);		mkdir ($dir, $mode) || &croak("mkdir $dir failed");	}	mkdir ($dirs, $mode) || &croak("mkdir $dirs failed");}# Remove a set of directories, failing if the directories# contain other files.# This subroutine has been tailored for this script, and# because of that, it ignored the directory name '.'.sub rmdirs {	my ($dirs) = @_;	$dirs = &cleandirs($dirs);	return if ($dirs eq '.');	rmdir $dirs || &croak("rmdir $dirs failed");	my $newpos = length($dirs);	while (($newpos = rindex($dirs, '/', $newpos-1)) != -1) {		my $dir = substr($dirs, 0, $newpos);		rmdir $dir || &croak("rmdir $dir failed");	}}# Return a semi-canonical directory name.sub cleandirs {	my ($dir) = @_;	$dir =~ s:/+:/:g;	$dir =~ s:/*$::;	return $dir;}# Make a temporary directory with mode 0700.sub mktmpdir {	while (1) {		my $dir = POSIX::tmpnam();		return $dir if mkdir ($dir, 0700);	}}# Make a filename absolute and return it.sub absolutize {	my ($file, $pwd) = @_;	return "$pwd/$file" if ($file !~ /^\//);	return $file;}# Like the system built-in function, but with error checking.# The other argument is an exit status to allow.sub safesystem {	my ($command, @allowrc) = @_;	my ($desc) = ($command =~ /^([^ ]*) */);	$desc = File::Basename::basename($desc);	system $command;	my $rc = $?;	&croak("`$desc' failed") if (($rc & 0xFF) != 0);	if ($rc != 0) {		$rc = $rc >> 8;		foreach my $arc (@allowrc) {			return if ($rc == $arc);		}		&croak("`$desc' failed", "non-zero exit status ($rc)");	}}# Like backticks built-in, but with error checking.sub safeticks {	my ($command, @allowrc) = @_;	my ($desc) = ($command =~ /^([^ ]*) /);	$desc = File::Basename::basename($desc);	my $out = `$command`;	my $rc = $?;	&croak("`$desc' failed") if (($rc & 0xFF) != 0);	if ($rc != 0) {		$rc = $rc >> 8;		foreach my $arc (@allowrc) {			return if ($rc == $arc);		}		&croak("`$desc' failed", "non-zero exit status ($rc)");	}	return $out;}# Make sure enough arguments are supplied, or die.sub checkargs {	my $count = shift;	my $desc = shift;	&croak('missing argument', $desc) if ($count-1 > $#_);}# Quote zip wildcard metacharacters. Unfortunately Info-ZIP zip and unzip# on unix interpret some wildcards in filenames, despite the fact that# the shell already does this. Thus this function.sub zipquotemeta {	my ($name) = @_;	my $out = '';	for (my $c = 0; $c < length $name; $c++) {		my $ch = substr($name, $c, 1);		$out .= '\\' if (index('*?[]\\', $ch) != -1);		$out .= $ch;	}	return quotemeta($out);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -