187 lines
6.0 KiB
C#
187 lines
6.0 KiB
C#
using PacketIO;
|
|
|
|
namespace Archiver.Lib;
|
|
|
|
public static class ArchiveEncoder
|
|
{
|
|
public static async ValueTask Encode(string inputPath, string outputPath)
|
|
{
|
|
if (!Directory.Exists(inputPath))
|
|
{
|
|
throw new FileNotFoundException($"{inputPath} does not exist", inputPath);
|
|
}
|
|
|
|
using (FileStream fs = new FileStream(outputPath, FileMode.OpenOrCreate))
|
|
{
|
|
byte[] buffer = CreateFileHeader();
|
|
await fs.WriteAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
|
|
|
|
FileAttributes attributes = File.GetAttributes(inputPath);
|
|
if (attributes.HasFlag(FileAttributes.Directory))
|
|
{
|
|
DirectoryInfo dirInfo = new DirectoryInfo(inputPath);
|
|
PacketDirectoryModel model = await CreatePacketDirectory(dirInfo).ConfigureAwait(false);
|
|
try
|
|
{
|
|
await TreePacketFile.WriteTreeFiles(fs, model.PacketDirectory).ConfigureAwait(false);
|
|
}
|
|
finally
|
|
{
|
|
DisposeFiles(model);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FileInfo fileInfo = new FileInfo(inputPath);
|
|
PacketFileModel model = await CreatePacketFile(fileInfo).ConfigureAwait(false);
|
|
try
|
|
{
|
|
await TreePacketFile.WriteTreeFiles(fs, model.PacketFile).ConfigureAwait(false);
|
|
}
|
|
finally
|
|
{
|
|
DisposeFiles(model);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static async ValueTask Encode(IEnumerable<string> inputFiles, string outputPath)
|
|
{
|
|
using (FileStream fs = new FileStream(outputPath, FileMode.OpenOrCreate))
|
|
{
|
|
byte[] buffer = CreateFileHeader();
|
|
await fs.WriteAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
|
|
|
|
foreach (string inputPath in inputFiles)
|
|
{
|
|
FileAttributes attributes = File.GetAttributes(inputPath);
|
|
if (attributes.HasFlag(FileAttributes.Directory))
|
|
{
|
|
DirectoryInfo dirInfo = new DirectoryInfo(inputPath);
|
|
PacketDirectoryModel model = await CreatePacketDirectory(dirInfo).ConfigureAwait(false);
|
|
try
|
|
{
|
|
await TreePacketFile.WriteTreeFiles(fs, model.PacketDirectory).ConfigureAwait(false);
|
|
}
|
|
finally
|
|
{
|
|
DisposeFiles(model);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FileInfo fileInfo = new FileInfo(inputPath);
|
|
PacketFileModel model = await CreatePacketFile(fileInfo).ConfigureAwait(false);
|
|
try
|
|
{
|
|
await TreePacketFile.WriteTreeFiles(fs, model.PacketFile).ConfigureAwait(false);
|
|
}
|
|
finally
|
|
{
|
|
DisposeFiles(model);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static bool IsArchiveFile(string inputPath)
|
|
{
|
|
FileAttributes attributes = File.GetAttributes(inputPath);
|
|
if (attributes.HasFlag(FileAttributes.Directory))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
using (FileStream fs = File.OpenRead(inputPath))
|
|
{
|
|
byte[] buffer = new byte[CreateFileHeader().Length];
|
|
int c = fs.Read(buffer, 0, buffer.Length);
|
|
if (c <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return buffer.SequenceEqual(CreateFileHeader());
|
|
}
|
|
}
|
|
|
|
internal static byte[] CreateFileHeader()
|
|
{
|
|
byte[] header = new byte[]
|
|
{
|
|
0xCC, 0xDE, 0xFF, 0x00,
|
|
};
|
|
return header;
|
|
}
|
|
|
|
private static void DisposeFiles(PacketDirectoryModel dirModel)
|
|
{
|
|
dirModel.PacketDirectory.Dispose();
|
|
foreach (PacketDirectoryModel subDirModel in dirModel.Directories)
|
|
{
|
|
DisposeFiles(subDirModel);
|
|
}
|
|
|
|
foreach (PacketFileModel fileModel in dirModel.Files)
|
|
{
|
|
DisposeFiles(fileModel);
|
|
}
|
|
}
|
|
|
|
private static void DisposeFiles(PacketFileModel fileModel)
|
|
{
|
|
fileModel.PacketFile.Dispose();
|
|
fileModel.TempFile.Dispose();
|
|
}
|
|
|
|
private static async ValueTask<PacketDirectoryModel> CreatePacketDirectory(DirectoryInfo dirInfo)
|
|
{
|
|
PacketDirectory packetDirectory = new PacketDirectory(dirInfo.Name);
|
|
PacketDirectoryModel dirModel = new PacketDirectoryModel()
|
|
{
|
|
PacketDirectory = packetDirectory,
|
|
Files = new List<PacketFileModel>(),
|
|
};
|
|
|
|
foreach (FileInfo fileInfo in dirInfo.EnumerateFiles())
|
|
{
|
|
PacketFileModel model = await CreatePacketFile(fileInfo).ConfigureAwait(false);
|
|
dirModel.Files.Add(model);
|
|
packetDirectory.AddFile(model.PacketFile);
|
|
}
|
|
|
|
foreach (DirectoryInfo subInfo in dirInfo.EnumerateDirectories())
|
|
{
|
|
PacketDirectoryModel subDirModel = await CreatePacketDirectory(subInfo).ConfigureAwait(false);
|
|
dirModel.Directories.Add(subDirModel);
|
|
packetDirectory.AddFile(subDirModel.PacketDirectory);
|
|
}
|
|
|
|
return dirModel;
|
|
}
|
|
|
|
private static async ValueTask<PacketFileModel> CreatePacketFile(FileInfo fileInfo)
|
|
{
|
|
TempFile tempFile = new TempFile();
|
|
Stream outputStream = tempFile.Open(FileMode.Open);
|
|
|
|
using (FileStream sourceStream = fileInfo.OpenRead())
|
|
{
|
|
await sourceStream.CopyToAsync(outputStream).ConfigureAwait(false);
|
|
}
|
|
|
|
outputStream.Seek(0, SeekOrigin.Begin);
|
|
PacketFile file = new PacketFile(fileInfo.Name, outputStream);
|
|
PacketFileModel model = new PacketFileModel()
|
|
{
|
|
TempFile = tempFile,
|
|
PacketFile = file,
|
|
};
|
|
|
|
return model;
|
|
}
|
|
}
|
|
|