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

📄 mccopy.pl

📁 hl2 source code. Do not use it illegal.
💻 PL
📖 第 1 页 / 共 2 页
字号:
	&MakeDirHier( $g_dst_path );

	&SetBaseDir( $g_dst_path );

	if( $g_opt_verbose )
	{
		print "\n\$g_src_is_local = $g_src_is_local\n";
		print "\$g_src_machine = $g_src_machine\n";
		print "\$g_src_path = $g_src_path\n";
		print "\$g_dst_is_local = $g_dst_is_local\n";
		print "\$g_dst_machine = $g_dst_machine\n";
		print "\$g_dst_path = $g_dst_path\n\n";
	}
}

&ProcessCommandLine( @ARGV );
&ValidateOptions();
&PrintOptions();

if( $g_opt_server )
{
	&RunServer();
	exit;
}

&ParseSrcDstPaths();

sub GetRemoteDirList
{
	local( $sock ) = shift;
	local( $remotedirname ) = shift;
	if( $g_opt_md5 )
	{
		print $sock "dirlistmd5 $remotedirname\n";
	}
	else
	{
		print $sock "dirlist $remotedirname\n";
	}
	local( $filename, $mtime, $mode, $size );
	while( defined( $fileordir = <$sock> ) )
	{
		last if $fileordir=~ m/^\n$/;
		$filename = <$sock>;
		$mtime = <$sock>;
		$mode = <$sock>;
		$size = <$sock>;
		$md5 = "";
		if( ( $fileordir =~ /f/i ) && $g_opt_md5 )
		{
			$md5 = <$sock>;
		}
		if( 0 )
		{
			print "file: $filename";
			print "fileordir: $fileordir";
			print "mtime: $mtime";
			print "mode: $mode";
			print "size: $size\n";
		}
		$filename =~ s/\n//;
		$mtime =~ s/\n//;
		$mode =~ s/\n//;
		$size =~ s/\n//;
		$md5 =~ s/\n//;
		if( $fileordir =~ m/d/ )
		{
#			print $filename . " is a dir\n";
			$g_remote_isdir{$filename} = 1;	
		}
		else
		{
			$g_remote_isdir{$filename} = 0;	
		}
		$g_remote_mtime{$filename} = $mtime;
#		print $g_remote_mtime{$filename};
		$g_remote_mode{$filename} = $mode;
		$g_remote_size{$filename} = $size;
		if( $g_opt_md5 )
		{
			$g_remote_md5{$filename} = $md5;
		}
	}
}

sub GetLocalDirList_File
{
	local( $filename ) = shift;
	local( $isdir ) = -d $filename;
	if( $isdir )
	{
		if( $filename =~ m/\/\.$/ ||		# "."
			$filename =~ m/\/\.\.$/ )	# ".."
		{
			return;
		}
	}

	if( $isdir )
	{
		GetLocalDirList_Dir( $filename );
	}
	local( @statinfo ) = stat $filename;
	if( @statinfo )
	{
		local( $mtime ) = $statinfo[9];
		local( $mode ) = $statinfo[2];
#			local( $mtimestr ) = scalar( localtime( $mtime ) );
		local( $size ) = $statinfo[7];
		local( $filename_nobase ) = &RemoveBaseDir( $filename );
		$g_local_isdir{$filename_nobase} = $isdir;
		$g_local_mtime{$filename_nobase} = $mtime;
		$g_local_mode{$filename_nobase} = sprintf "%o", $mode;
		$g_local_size{$filename_nobase} = $size;
		if( !$isdir && $g_opt_md5 )	
		{
			$g_local_md5{$filename_nobase} = &GetMD5( $filename );
		}
	}
	else
	{
		print "CAN'T STAT $file\n";
	}
}

sub GetLocalDirList_Dir
{
	local( $dirname ) = shift;
	if( $dirname =~ m/\/\.$/ ||		# "."
		$dirname =~ m/\/\.\.$/ )	# ".."
	{
		return;
	}

	local( *SRCDIR );
	opendir SRCDIR, $dirname;
	local( @dir ) = readdir SRCDIR;
	closedir SRCDIR;

	local( $item );
	while( $item = shift @dir )
	{
		&GetLocalDirList_File( $dirname . "/" . $item );
	}
}

sub IsExcluded
{
	local( $filename ) = shift;
	local( $regexp );
	foreach $regexp ( @g_opt_include )
	{
		if( eval "\$filename =~ $regexp" )
		{
			return 0;
		}
	}
	foreach $regexp ( @g_opt_exclude )
	{
		if( eval "\$filename =~ $regexp" )
		{
			if( defined( $g_local_mtime{$filename} ) )
			{
				if( $g_opt_deleteexcluded )
				{
					print "excluding and deleting $filename\n" if( $g_opt_verbose );
					if( defined $g_remote_isdir{$filename} )
					{
						if( $g_remote_isdir{$filename} )
						{
							$g_dirs_to_delete{$filename} = 1;
						}
						else
						{
							$g_files_to_delete{$filename} = 1;
						}
					}
					elsif( defined $g_local_isdir{$filename} )
					{
						if( $g_local_isdir{$filename} )
						{
							$g_dirs_to_delete{$filename} = 1;
						}
						else
						{
							$g_files_to_delete{$filename} = 1;
						}
					}
					else
					{
						die;
					}
				}
				else
				{
					print "excluding but keeping local copy of $filename\n" if( $g_opt_verbose );
				}
			}
			else
			{
				print "excluding $filename, which doesn't exist locally\n" if( $g_opt_verbose );
			}
			return 1;
		}
	}
	return 0;
}

sub CompareTime
{
	if( $g_opt_ignoretime )
	{
		return;
	}
	local( $filename ) = shift;
	# hack! ignore directories. . seems like robocopy does too.
	if( $g_remote_isdir{$filename} || $g_local_isdir{$filename} )
	{
		return;
	}

	if( defined( $g_alreadycomparedtime{$filename} ) )
	{
		return;
	}
	$g_alreadycomparedtime{$filename} = 1;

	# compare times
	local( $deltatime ) = $g_local_mtime{$filename} - $g_remote_mtime{$filename};
#	print "g_remote_mtime: " . $g_remote_mtime{$filename} . "\n";
#	print "g_local_mtime: " . $g_local_mtime{$filename} . "\n";
#	print "deltatime: $deltatime\n";
	if( !( ( $deltatime >= -$g_max_time_delta && $deltatime <= $g_max_time_delta ) ||
               ( $deltatime + 3600 >= -$g_max_time_delta && $deltatime + 3600 <= $g_max_time_delta ) ||
	       ( $deltatime - 3600 >= -$g_max_time_delta && $deltatime - 3600 <= $g_max_time_delta ) ) )
	{
		$g_files_to_copy{$filename} = 1;
		if( $g_opt_verbose )
		{
			print "timedelta of $deltatime for $filename\n";
		}
	}
}

sub ComparePermissions
{
	if( $g_opt_ignoreperms )
	{
		return;
	}
	local( $filename ) = shift;
	if( defined( $g_alreadycomparedpermissions{$filename} ) )
	{
		return;
	}
	$g_alreadycomparedpermissions{$filename} = 1;

	# compare permissions
	if( $g_remote_mode{$filename} != $g_local_mode{$filename} )
	{
		if( !$g_remote_isdir{$filename} )
		{
			$g_files_to_copy{$filename} = 1;
		}
		else
		{
			MakeLocalFileAttribsMatchRemote( $filename );
		}
		if( $g_opt_verbose )
		{
			printf "permissions different for $filename: %s %s\n", $g_remote_mode{$filename}, $g_local_mode{$filename};
		}
	}
}

sub CompareSize
{
	if( $g_opt_ignoresize )
	{
		return;
	}
	local( $filename ) = shift;
	if( defined( $g_alreadycomparedsize{$filename} ) )
	{
		return;
	}
	$g_alreadycomparedsize{$filename} = 1;

	# compare permissions
	if( $g_remote_size{$filename} != $g_local_size{$filename} )
	{
		$g_files_to_copy{$filename} = 1;
		if( $g_opt_verbose )
		{
			printf "size different for $filename: %d!=%d\n", $g_remote_size{$filename}, $g_local_size{$filename};
		}
	}
}

sub CompareMD5
{
	if( !$g_opt_md5 )
	{
		return;
	}
	local( $filename ) = shift;
	if( defined( $g_alreadycomparedmd5{$filename} ) )
	{
		return;
	}
	$g_alreadycomparedmd5{$filename} = 1;

	# compare md5
	if( $g_remote_md5{$filename} ne $g_local_md5{$filename} )
	{
		$g_files_to_copy{$filename} = 1;
		if( $g_opt_verbose )
		{
			printf "md5 different for $filename: %s!=%s\n", $g_remote_md5{$filename}, $g_local_md5{$filename};
		}
	}
	else
	{
		local( $diff ) = 0;
		local( $deltatime ) = $g_local_mtime{$filename} - $g_remote_mtime{$filename};
		if( $g_remote_size{$filename} != $g_local_size{$filename} )
		{
			$diff = 1;
			print "size different\n";
		}
		if( $g_remote_mode{$filename} != $g_local_mode{$filename} )
		{
			$diff = 1;
			print "mode different\n";
		}
		if( !( ( $deltatime >= -$g_max_time_delta && $deltatime <= $g_max_time_delta ) ||
                       ( $deltatime + 3600 >= -$g_max_time_delta && $deltatime + 3600 <= $g_max_time_delta ) ||
	               ( $deltatime - 3600 >= -$g_max_time_delta && $deltatime - 3600 <= $g_max_time_delta ) ) )
		{
			$diff = 1;
			print "time different\n";
		}
		if( $diff )
		{
			print "fixing up file attribs for $filename\n";
			MakeLocalFileAttribsMatchRemote( $filename );
		}
	}
}

#print "socket: PeerAddr: \"$g_src_machine\"\n";
my $sock = new IO::Socket::INET (
                                  PeerAddr => $g_src_machine,
                                  PeerPort => $g_opt_port,
                                  Proto => 'tcp',
                                 );
die "Could not create socket: $!\n" unless $sock;

print $sock $g_protocol_version;
$remotedirname = $g_src_path;
print "Getting remote dirlist for $remotedirname\n";
&GetRemoteDirList( $sock, $remotedirname );

$localdirname = $g_dst_path;
print "Getting local dirlist for $localdirname\n";
&GetLocalDirList_Dir( $localdirname );

foreach $remote_filename (keys %g_remote_mtime)
{
	next if( &IsExcluded( $remote_filename ) );
	if( !defined( $g_local_mtime{$remote_filename} ) )
	{
		if( $g_remote_isdir{$remote_filename} )
		{
#			print "dir ";
			$g_dirs_to_create{$remote_filename} = 1;
		}
		else
		{
#			print "file ";
			$g_files_to_copy{$remote_filename} = 1;
		}
		if( $g_opt_verbose )
		{
			print "doesn't exist locally and will be copied: $remote_filename\n";
		}
	}
	else
	{
		&CompareTime( $remote_filename );
		&ComparePermissions( $remote_filename );
		&CompareSize( $remote_filename );
		&CompareMD5( $remote_filename );
	}
}

foreach $local_filename (keys %g_local_mtime)
{
	next if( &IsExcluded( $local_filename ) );
	if( !defined( $g_remote_mtime{$local_filename} ) )
	{
		if( $g_local_isdir{$local_filename} )
		{
			$g_dirs_to_delete{$local_filename} = 1;
#			print "dir ";
		}
		else
		{
			$g_files_to_delete{$local_filename} = 1;
#			print "file ";
		}
#		print $local_filename . " doesn't exist remotely\n";
	}
	else
	{
		&CompareTime( $local_filename );
		&ComparePermissions( $local_filename );
		&CompareSize( $local_filename );
	}
}

#%g_files_to_delete;
#%g_dirs_to_delete;
#%g_files_to_copy;
#%g_dirs_to_create;

sub IsWritable
{
	local( $file ) = shift;
	local( $perms ) = oct( $g_local_mode{$file} );
	if( $perms & 2 )
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

sub UnlinkFile
{
	local( $file ) = shift;
	
	print "del " . &ForwardToBackSlash( $file ) . "\n";
	if( !$g_opt_test )
	{
		chmod 0666, $file || die;
		unlink $file || die;
	}
}

sub UnlinkDir
{
	local( $file ) = shift;
	
	print "rmdir " . &ForwardToBackSlash( $file ) . "\n";
	if( !$g_opt_test )
	{
		chmod 0777, $file || die;
		if( !( rmdir $file ) )
		{
			print "Couldn't rmdir " . &ForwardToBackSlash( $file ) . "\n";
		}
	}
}

sub DeleteOrphanFile
{
	local( $file ) = shift;
#	print "\$g_local_isdir{$file} = $g_local_isdir{$file}\n";
	#	print "DeleteOrphanFile( $file )\n";
	local( $localfile ) = &AddBaseDir( $file );
	local( $iswritable ) = &IsWritable( $file );
	if( $iswritable )
	{
		if( $g_opt_deletewritable )
		{
			&UnlinkFile( &AddBaseDir( $file ) );
		}
		else
		{
			print "Would have deleted \"$file\" (use --delete-writable to delete)\n";
		}
	}
	else
	{
		if( $g_opt_deletereadonly )
		{
			&UnlinkFile( &AddBaseDir( $file ) );
		}
		else
		{
			print "Would have deleted \"$file\" (use --delete-readonly to delete)\n";
		}
	}
}

sub DeleteOrphanDir
{
	local( $localdir ) = &AddBaseDir( $dir );
	if( $g_opt_deletedirs )
	{
		&UnlinkDir( $localdir );
	}
	else
	{
		print "Would have deleted \"$dir\" (use --delete-dirs to delete)\n";
	}
}

sub MakeLocalFileAttribsMatchRemote
{
	return if( $g_opt_test );
	local( $file ) = shift;
	local( $localfilename ) = &AddBaseDir( $file );

	# Make it writable so that we can tweak permissions/time.
	chmod 0666, $localfilename || die $!;

	# Set the time on the file to match the remote
	local( @statresult );
	if( !( @statresult = stat $localfilename ) )
	{
		die "couldn't stat $localfilename locally\n";
	}
	# @statresult[8] == access time. . we don't care to change this.
	utime $statresult[8], $g_remote_mtime{$file}, $localfilename || die $!;

	# Set the permissions on the file to match the remote
	chmod oct( $g_remote_mode{$file} ), $localfilename || die $!;
}

sub CopyFileFromRemote
{
	local( $file ) = shift;
	if( &IsWritable( $file ) && !$g_opt_clobberwritablenewer && $g_local_mtime{$file} > $g_remote_mtime{$file} )
	{
		print "Would have copied \"$file\" (use --clobber-writable-newer to copy)\n";
		return;
	}
	print "copy $file from remote ($g_remote_size{$file} bytes)\n";
	if( !$g_opt_test )
	{
		local( $localfilename ) = &AddBaseDir( $file );
		# make the local version writable so that we can write over it, if it exists
		if( $g_local_mtime{$file} )
		{
			chmod 0666, $localfilename || die $!;
		}
		print $sock "getfile $file\n";
		local( $size ) = $g_remote_size{$file};
		local( $filebits );
#		print "reading $file: $size\n";
		local( $readsize ) = read $sock, $filebits, $size;
		if( $readsize != $size )
		{
			die "read size ($readsize) != expected size ($size) for $file\nYou either:\n\t1) lost your connection\n\t2) the remote file has changed since start of mccopy\n";
		}

#		print "finished with $file\n";
		local( *FILE );
#		print "opening $localfilename\n";
		open FILE, ">$localfilename" || die $!;
#		print "binmode $localfilename";
		binmode( FILE ) || die $!;
#		print "after binmode $localfilename";
		print FILE $filebits;
		close FILE || die $!;
#		print "closed $localfilename\n";

		MakeLocalFileAttribsMatchRemote( $file );
	}
}

sub PrettifyTime
{
	local( $inseconds ) = shift;
	local( $hours, $minutes, $seconds );
	local( @blah ) = gmtime( $inseconds );
	$hours = $blah[2];
	$minutes = $blah[1];
	$seconds = $blah[0];
	return sprintf "%02d:%02d:%02d", $hours, $minutes, $seconds;
}

# remove local files that aren't on remote
foreach $file (keys %g_files_to_delete)
{
	&DeleteOrphanFile( $file );
}

# remove local dirs that aren't on remote
foreach $dir (sort { length $b <=> length $a } keys( %g_dirs_to_delete ) )
{
	&DeleteOrphanDir( $dir );
}


# create local dirs that are only on remote
foreach $dir (sort { length $a <=> length $b } keys( %g_dirs_to_create) )
{
	local( $localdir ) = &AddBaseDir( $dir );
	print "mkdir $localdir, 0777\n";
	if( !$g_opt_test )
	{
		mkdir $localdir, 0777 || die $!;
	}
}

# calculate the total size of files to transfer
$totalbytes = 0;
foreach $file ( keys %g_files_to_copy )
{
	$totalbytes += $g_remote_size{$file};	
}

print "$totalbytes bytes to copy\n";

# copy files from remote that are different
$bytescopied = 0;
$starttime = time;
foreach $file (sort( keys %g_files_to_copy ) )
{
	&CopyFileFromRemote( $file );
	$bytescopied += $g_remote_size{$file};
	$curtime = time;
	$deltatime = $curtime - $starttime;
	if( $totalbytes )
	{
		$percentdone = ( $bytescopied * 1.0 ) / $totalbytes;
	}
	if( $totalbytes && $percentdone && $deltatime )
	{
		printf "progress: %.1f%% %s/%s %d bytes/sec\n",
				$percentdone * 100,
				&PrettifyTime( $deltatime ),
				&PrettifyTime( 1.0 / $percentdone * $deltatime ),
				$bytescopied / $deltatime;
	}
}

print "done!\n";

close($sock);


⌨️ 快捷键说明

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