tararchive.cs
来自「全功能c#编译器」· CS 代码 · 共 715 行 · 第 1/2 页
CS
715 行
/// NOTE That this method uses the progress display to actually list
/// the contents. If the progress display is not set, nothing will be
/// listed!
/// </summary>
public void ListContents()
{
while (true) {
TarEntry entry = this.tarIn.GetNextEntry();
if (entry == null) {
if (this.debug) {
Console.Error.WriteLine("READ EOF BLOCK");
}
break;
}
OnProgressMessageEvent(entry, null);
}
}
/// <summary>
/// Perform the "extract" command and extract the contents of the archive.
/// </summary>
/// <param name="destDir">
/// The destination directory into which to extract.
/// </param>
public void ExtractContents(string destDir)
{
while (true) {
TarEntry entry = this.tarIn.GetNextEntry();
if (entry == null) {
if (this.debug) {
Console.Error.WriteLine("READ EOF BLOCK");
}
break;
}
this.ExtractEntry(destDir, entry);
}
}
void EnsureDirectoryExists(string directoryName)
{
if (!Directory.Exists(directoryName)) {
try {
Directory.CreateDirectory(directoryName);
}
catch (Exception e) {
throw new TarException("Exception creating directory '" + directoryName + "', " + e.Message);
}
}
}
// TODO Assess how valid this test really is.
// No longer reads entire file into memory but is still a weak test!
// assumes that ascii 0-7, 14-31 or 255 are binary
// and that all non text files contain one of these values
bool IsBinary(string filename)
{
FileStream fs = File.OpenRead(filename);
int sampleSize = System.Math.Min(4096, (int)fs.Length);
byte[] content = new byte[sampleSize];
fs.Read(content, 0, sampleSize);
fs.Close();
foreach (byte b in content) {
if (b < 8 || (b > 13 && b < 32) || b == 255) {
return true;
}
}
return false;
}
/// <summary>
/// Extract an entry from the archive. This method assumes that the
/// tarIn stream has been properly set with a call to getNextEntry().
/// </summary>
/// <param name="destDir">
/// The destination directory into which to extract.
/// </param>
/// <param name="entry">
/// The TarEntry returned by tarIn.getNextEntry().
/// </param>
void ExtractEntry(string destDir, TarEntry entry)
{
if (this.verbose) {
OnProgressMessageEvent(entry, null);
}
string name = entry.Name;
if (Path.IsPathRooted(name) == true) {
// NOTE:
// for UNC names... \\machine\share\zoom\beet.txt gives \zoom\beet.txt
name = name.Substring(Path.GetPathRoot(name).Length);
}
name = name.Replace('/', Path.DirectorySeparatorChar);
string destFile = Path.Combine(destDir, name);
if (entry.IsDirectory) {
EnsureDirectoryExists(destFile);
} else {
string parentDirectory = Path.GetDirectoryName(destFile);
EnsureDirectoryExists(parentDirectory);
bool process = true;
FileInfo fileInfo = new FileInfo(destFile);
if (fileInfo.Exists) {
if (this.keepOldFiles) {
OnProgressMessageEvent(entry, "Destination file already exists");
process = false;
} else if ((fileInfo.Attributes & FileAttributes.ReadOnly) != 0) {
OnProgressMessageEvent(entry, "Destination file already exists, and is read-only");
process = false;
}
}
if (process) {
bool asciiTrans = false;
// TODO file may exist and be read-only at this point!
Stream outputStream = File.Create(destFile);
if (this.asciiTranslate) {
asciiTrans = !IsBinary(destFile);
// TODO do we need this stuff below?
// original java sourcecode :
// MimeType mime = null;
// string contentType = null;
// try {
// contentType = FileTypeMap.getDefaultFileTypeMap().getContentType( destFile );
//
// mime = new MimeType(contentType);
//
// if (mime.getPrimaryType().equalsIgnoreCase( "text" )) {
// asciiTrans = true;
// } else if ( this.transTyper != null ) {
// if ( this.transTyper.isAsciiFile( entry.getName() ) ) {
// asciiTrans = true;
// }
// }
// } catch (MimeTypeParseException ex) {
// }
//
// if (this.debug) {
// Console.Error.WriteLine(("EXTRACT TRANS? '" + asciiTrans + "' ContentType='" + contentType + "' PrimaryType='" + mime.getPrimaryType() + "'" );
// }
}
StreamWriter outw = null;
if (asciiTrans) {
outw = new StreamWriter(outputStream);
}
byte[] rdbuf = new byte[32 * 1024];
while (true) {
int numRead = this.tarIn.Read(rdbuf, 0, rdbuf.Length);
if (numRead <= 0) {
break;
}
if (asciiTrans) {
for (int off = 0, b = 0; b < numRead; ++b) {
if (rdbuf[b] == 10) {
string s = Encoding.ASCII.GetString(rdbuf, off, (b - off));
outw.WriteLine(s);
off = b + 1;
}
}
} else {
outputStream.Write(rdbuf, 0, numRead);
}
}
if (asciiTrans) {
outw.Close();
} else {
outputStream.Close();
}
}
}
}
/// <summary>
/// Write an entry to the archive. This method will call the putNextEntry
/// and then write the contents of the entry, and finally call closeEntry()
/// for entries that are files. For directories, it will call putNextEntry(),
/// and then, if the recurse flag is true, process each entry that is a
/// child of the directory.
/// </summary>
/// <param name="entry">
/// The TarEntry representing the entry to write to the archive.
/// </param>
/// <param name="recurse">
/// If true, process the children of directory entries.
/// </param>
public void WriteEntry(TarEntry entry, bool recurse)
{
bool asciiTrans = false;
string tempFileName = null;
string eFile = entry.File;
// Work on a copy of the entry so we can manipulate it.
// Note that we must distinguish how the entry was constructed.
//
if (eFile == null || eFile.Length == 0) {
entry = TarEntry.CreateTarEntry(entry.Name);
} else {
//
// The user may have explicitly set the entry's name to
// something other than the file's path, so we must save
// and restore it. This should work even when the name
// was set from the File's name.
//
string saveName = entry.Name;
entry = TarEntry.CreateEntryFromFile(eFile);
entry.Name = saveName;
}
if (this.verbose) {
OnProgressMessageEvent(entry, null);
}
if (this.asciiTranslate && !entry.IsDirectory) {
asciiTrans = !IsBinary(eFile);
// original java source :
// MimeType mime = null;
// string contentType = null;
//
// try {
// contentType = FileTypeMap.getDefaultFileTypeMap(). getContentType( eFile );
//
// mime = new MimeType( contentType );
//
// if ( mime.getPrimaryType().equalsIgnoreCase( "text" ) )
// {
// asciiTrans = true;
// }
// else if ( this.transTyper != null )
// {
// if ( this.transTyper.isAsciiFile( eFile ) )
// {
// asciiTrans = true;
// }
// }
// } catch ( MimeTypeParseException ex )
// {
// // IGNORE THIS ERROR...
// }
//
// if (this.debug) {
// Console.Error.WriteLine("CREATE TRANS? '" + asciiTrans + "' ContentType='" + contentType + "' PrimaryType='" + mime.getPrimaryType()+ "'" );
// }
if (asciiTrans) {
tempFileName = Path.GetTempFileName();
StreamReader inStream = File.OpenText(eFile);
// -jr- 22-Jun-2004 Was using BufferedStream but this is not available for compact framework
// Stream outStream = new BufferedStream(File.Create(tempFileName));
Stream outStream = File.Create(tempFileName);
while (true) {
string line = inStream.ReadLine();
if (line == null) {
break;
}
byte[] data = Encoding.ASCII.GetBytes(line);
outStream.Write(data, 0, data.Length);
outStream.WriteByte((byte)'\n');
}
inStream.Close();
outStream.Flush();
outStream.Close();
entry.Size = new FileInfo(tempFileName).Length;
eFile = tempFileName;
}
}
string newName = null;
if (this.rootPath != null) {
if (entry.Name.StartsWith(this.rootPath)) {
newName = entry.Name.Substring(this.rootPath.Length + 1 );
}
}
if (this.pathPrefix != null) {
newName = (newName == null) ? this.pathPrefix + "/" + entry.Name : this.pathPrefix + "/" + newName;
}
if (newName != null) {
entry.Name = newName;
}
this.tarOut.PutNextEntry(entry);
if (entry.IsDirectory) {
if (recurse) {
TarEntry[] list = entry.GetDirectoryEntries();
for (int i = 0; i < list.Length; ++i) {
this.WriteEntry(list[i], recurse);
}
}
} else {
Stream inputStream = File.OpenRead(eFile);
int numWritten = 0;
byte[] eBuf = new byte[32 * 1024];
while (true) {
int numRead = inputStream.Read(eBuf, 0, eBuf.Length);
if (numRead <=0) {
break;
}
this.tarOut.Write(eBuf, 0, numRead);
numWritten += numRead;
}
inputStream.Close();
if (tempFileName != null && tempFileName.Length > 0) {
File.Delete(tempFileName);
}
this.tarOut.CloseEntry();
}
}
}
}
/* The original Java file had this header:
** Authored by Timothy Gerard Endres
** <mailto:time@gjt.org> <http://www.trustice.com>
**
** This work has been placed into the public domain.
** You may use this work in any way and for any purpose you wish.
**
** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
** REDISTRIBUTION OF THIS SOFTWARE.
**
*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?