📄 main.cs
字号:
using System;
using System.IO;
using ICSharpCode.SharpZipLib;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.BZip2;
using ICSharpCode.SharpZipLib.Tar;
/// <summary>
/// The tar class implements a simplistic version of the
/// traditional UNIX tar command. It currently supports
/// creating, listing, and extracting from archives.
/// It supports GZIP, unix compress and bzip2 compression
/// GNU long filename extensions are supported, POSIX extensions are not yet supported...
/// See the help (-? or --help) for option details.
/// </summary>
public class Tar
{
/// <summary>
/// The compresion to use when creating archives.
/// </summary>
enum Compression
{
None,
Compress,
Gzip,
Bzip2
}
/// <summary>
/// Operation to perform on archive
/// </summary>
enum Operation
{
List,
Create,
Extract
}
#region Instance Fields
/// <summary>
/// Flag that determines if verbose feedback is to be provided.
/// </summary>
bool verbose;
/// <summary>
/// What kind of <see cref="Compression"/> to use.
/// </summary>
Compression compression = Compression.None;
/// <summary>
/// The <see cref="Operation"/> to perform.
/// </summary>
Operation operation = Operation.List;
/// <summary>
/// True if we are not to overwrite existing files. (Unix noKlobber option)
/// </summary>
bool keepOldFiles;
/// <summary>
/// True if we are to convert ASCII text files from local line endings
/// to the UNIX standard '\n'.
/// </summary>
bool asciiTranslate;
/// <summary>
/// The archive name provided on the command line, '-' if stdio.
/// </summary>
string archiveName;
/// <summary>
/// The blocking factor to use for the tar archive IO. Set by the '-b' option.
/// </summary>
int blockingFactor;
/// <summary>
/// The userId to use for files written to archives. Set by '-U' option.
/// </summary>
int userId;
/// <summary>
/// The userName to use for files written to archives. Set by '-u' option.
/// </summary>
string userName;
/// <summary>
/// The groupId to use for files written to archives. Set by '-G' option.
/// </summary>
int groupId;
/// <summary>
/// The groupName to use for files written to archives. Set by '-g' option.
/// </summary>
string groupName;
#endregion
/// <summary>
/// Initialise default instance of <see cref="Tar"/>.
/// Sets up the default userName with the system 'UserName' property.
/// </summary>
public Tar()
{
this.blockingFactor = TarBuffer.DefaultBlockFactor;
this.userId = 0;
string sysUserName = Environment.UserName;
this.userName = ((sysUserName == null) ? "" : sysUserName);
this.groupId = 0;
this.groupName = "None";
}
/// <summary>
/// The main entry point of the tar class.
/// </summary>
public static void Main(string[] argv)
{
Tar tarApp = new Tar();
tarApp.InstanceMain(argv);
}
/// <summary>
/// This is the "real" main. The class main() instantiates a tar object
/// for the application and then calls this method. Process the arguments
/// and perform the requested operation.
/// </summary>
public void InstanceMain(string[] argv)
{
TarArchive archive = null;
int argIdx = this.ProcessArguments(argv);
if (this.archiveName != null && ! this.archiveName.Equals("-")) {
if (operation == Operation.Create) {
if (!Directory.Exists(Path.GetDirectoryName(archiveName))) {
Console.Error.WriteLine("Directory for archive doesnt exist");
return;
}
}
else {
if (File.Exists(this.archiveName) == false) {
Console.Error.WriteLine("File does not exist " + this.archiveName);
return;
}
}
}
if (operation == Operation.Create) { // WRITING
Stream outStream = Console.OpenStandardOutput();
if (this.archiveName != null && ! this.archiveName.Equals("-")) {
outStream = File.Create(archiveName);
}
if (outStream != null) {
switch (this.compression) {
case Compression.Compress:
outStream = new DeflaterOutputStream(outStream);
break;
case Compression.Gzip:
outStream = new GZipOutputStream(outStream);
break;
case Compression.Bzip2:
outStream = new BZip2OutputStream(outStream, 9);
break;
}
archive = TarArchive.CreateOutputTarArchive(outStream, this.blockingFactor);
}
} else { // EXTRACTING OR LISTING
Stream inStream = Console.OpenStandardInput();
if (this.archiveName != null && ! this.archiveName.Equals( "-" )) {
inStream = File.OpenRead(archiveName);
}
if (inStream != null) {
switch (this.compression) {
case Compression.Compress:
inStream = new InflaterInputStream(inStream);
break;
case Compression.Gzip:
inStream = new GZipInputStream(inStream);
break;
case Compression.Bzip2:
inStream = new BZip2InputStream(inStream);
break;
}
archive = TarArchive.CreateInputTarArchive(inStream, this.blockingFactor);
}
}
if (archive != null) { // SET ARCHIVE OPTIONS
archive.SetKeepOldFiles(this.keepOldFiles);
archive.AsciiTranslate = this.asciiTranslate;
archive.SetUserInfo(this.userId, this.userName, this.groupId, this.groupName);
}
if (archive == null) {
Console.Error.WriteLine( "no processing due to errors" );
} else if (operation == Operation.Create) { // WRITING
if (verbose) {
archive.ProgressMessageEvent += new ProgressMessageHandler(ShowTarProgressMessage);
}
for ( ; argIdx < argv.Length ; ++argIdx ) {
string[] fileNames = GetFilesForSpec(argv[argIdx]);
if (fileNames.Length > 0) {
foreach (string name in fileNames) {
TarEntry entry = TarEntry.CreateEntryFromFile(name);
archive.WriteEntry(entry, true);
}
} else {
Console.Error.Write("No files for " + argv[argIdx]);
}
}
} else if (operation == Operation.List) { // LISTING
archive.ProgressMessageEvent += new ProgressMessageHandler(ShowTarProgressMessage);
archive.ListContents();
} else { // EXTRACTING
string userDir = Environment.CurrentDirectory;
if (verbose) {
archive.ProgressMessageEvent += new ProgressMessageHandler(ShowTarProgressMessage);
}
if (userDir != null) {
archive.ExtractContents(userDir);
}
}
if (archive != null) { // CLOSE ARCHIVE
archive.Close();
}
}
/// <summary>
/// Display progress information on console
/// </summary>
public void ShowTarProgressMessage(TarArchive archive, TarEntry entry, string message)
{
if (entry.TarHeader.TypeFlag != TarHeader.LF_NORMAL && entry.TarHeader.TypeFlag != TarHeader.LF_OLDNORM) {
Console.WriteLine("Entry type " + (char)entry.TarHeader.TypeFlag + " found!");
}
if (message != null)
Console.Write(entry.Name + " " + message);
else {
if (this.verbose) {
string modeString = DecodeType(entry.TarHeader.TypeFlag, entry.Name.EndsWith("/")) + DecodeMode(entry.TarHeader.Mode);
string userString = (entry.UserName == null || entry.UserName.Length == 0) ? entry.UserId.ToString() : entry.UserName;
string groupString = (entry.GroupName == null || entry.GroupName.Length == 0) ? entry.GroupId.ToString() : entry.GroupName;
Console.WriteLine(string.Format("{0} {1}/{2} {3,8} {4:yyyy-MM-dd HH:mm:ss} {5}", modeString, userString, groupString, entry.Size, entry.ModTime.ToLocalTime(), entry.Name));
} else {
Console.WriteLine(entry.Name);
}
}
}
///
/// <summary>
/// Process arguments, handling options, and return the index of the
/// first non-option argument.
/// </summary>
/// <returns>
/// The index of the first non-option argument.
/// </returns>
int ProcessArguments(string[] args)
{
int idx = 0;
bool bailOut = false;
bool gotOP = false;
for ( ; idx < args.Length ; ++idx ) {
string arg = args[ idx ];
if (!arg.StartsWith("-")) {
break;
}
if (arg.StartsWith("--" )) {
int valuePos = arg.IndexOf('=');
string argValue = null;
if (valuePos >= 0) {
argValue = arg.Substring(valuePos + 1);
arg = arg.Substring(0, valuePos);
}
if (arg.Equals( "--help")) {
ShowHelp();
Environment.Exit(1);
} else if (arg.Equals( "--version")) {
Version();
Environment.Exit(1);
} else if (arg.Equals("--extract")) {
gotOP = true;
operation = Operation.Extract;
} else if (arg.Equals("--list")) {
gotOP = true;
operation = Operation.List;
} else if (arg.Equals("--create")) {
gotOP = true;
operation = Operation.Create;
} else if (arg.Equals("--gzip")) {
compression = Compression.Gzip;
} else if (arg.Equals("--bzip2")) {
compression = Compression.Bzip2;
} else if (arg.Equals("--compress")) {
compression = Compression.Compress;
} else if (arg.Equals("--blocking-factor")) {
if (argValue == null || argValue.Length == 0)
Console.Error.WriteLine("expected numeric blocking factor");
else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -