39 lines
1.6 KiB
C#
39 lines
1.6 KiB
C#
using System.Formats.Tar;
|
|
using System.IO.Compression;
|
|
|
|
if (args.Length < 3)
|
|
{
|
|
Console.Error.WriteLine("usage: Monitor.Tar <source-directory> <archive-path> <executable-relative-path>...");
|
|
return 2;
|
|
}
|
|
|
|
string sourceDirectory = Path.GetFullPath(args[0]);
|
|
string archivePath = Path.GetFullPath(args[1]);
|
|
HashSet<string> executables = args.Skip(2).Select(path => path.Replace('\\', '/')).ToHashSet(StringComparer.Ordinal);
|
|
UnixFileMode executableMode = UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
|
|
UnixFileMode.GroupRead | UnixFileMode.GroupExecute |
|
|
UnixFileMode.OtherRead | UnixFileMode.OtherExecute;
|
|
UnixFileMode regularMode = UnixFileMode.UserRead | UnixFileMode.UserWrite |
|
|
UnixFileMode.GroupRead | UnixFileMode.OtherRead;
|
|
|
|
Directory.CreateDirectory(Path.GetDirectoryName(archivePath)!);
|
|
using FileStream fileStream = File.Create(archivePath);
|
|
using GZipStream gzipStream = new(fileStream, CompressionLevel.Optimal, leaveOpen: true);
|
|
using TarWriter writer = new(gzipStream, TarEntryFormat.Pax, leaveOpen: true);
|
|
|
|
foreach (string filePath in Directory.EnumerateFiles(sourceDirectory, "*", SearchOption.AllDirectories))
|
|
{
|
|
string relativePath = Path.GetRelativePath(sourceDirectory, filePath).Replace('\\', '/');
|
|
PaxTarEntry entry = new(TarEntryType.RegularFile, relativePath)
|
|
{
|
|
Mode = executables.Contains(relativePath) ? executableMode : regularMode,
|
|
DataStream = File.OpenRead(filePath)
|
|
};
|
|
using (entry.DataStream)
|
|
{
|
|
writer.WriteEntry(entry);
|
|
}
|
|
}
|
|
|
|
return 0;
|