summary refs log tree commit diff
path: root/Rhea.Nar
diff options
context:
space:
mode:
Diffstat (limited to 'Rhea.Nar')
-rw-r--r--Rhea.Nar/NarConsts.cs44
-rw-r--r--Rhea.Nar/NarWriter.cs80
-rw-r--r--Rhea.Nar/Rhea.Nar.csproj2
3 files changed, 82 insertions, 44 deletions
diff --git a/Rhea.Nar/NarConsts.cs b/Rhea.Nar/NarConsts.cs
new file mode 100644

index 0000000..f821449 --- /dev/null +++ b/Rhea.Nar/NarConsts.cs
@@ -0,0 +1,44 @@ +namespace Rhea.Nar; + +/// <summary>Common strings/flags in NAR archives</summary> +public static class NarConsts +{ + /// <summary>Nix archive header</summary> + public static readonly byte[] Header = NarWriter.GetLengthPrefixedPadded("nix-archive-1"u8); + + /// <summary>Start of object marker</summary> + public static readonly byte[] LeftParen = NarWriter.GetLengthPrefixedPadded("("u8); + + /// <summary>End of object marker</summary> + public static readonly byte[] RightParen = NarWriter.GetLengthPrefixedPadded(")"u8); + + /// <summary>Indicates the node is a regular file</summary> + public static readonly byte[] Regular = NarWriter.GetLengthPrefixedPadded("regular"u8); + + /// <summary>Indicates the node is a directory</summary> + public static readonly byte[] Directory = NarWriter.GetLengthPrefixedPadded("directory"u8); + + /// <summary>Indicates the node is a symlink</summary> + public static readonly byte[] Symlink = NarWriter.GetLengthPrefixedPadded("symlink"u8); + + /// <summary>Indicates a directory entry</summary> + public static readonly byte[] Entry = NarWriter.GetLengthPrefixedPadded("entry"u8); + + /// <summary>Indicates a directory entry</summary> + public static readonly byte[] Node = NarWriter.GetLengthPrefixedPadded("node"u8); + + /// <summary>Indicates the name of a directory entry</summary> + public static readonly byte[] Name = NarWriter.GetLengthPrefixedPadded("name"u8); + + /// <summary>Indicates the target of a symlink</summary> + public static readonly byte[] Target = NarWriter.GetLengthPrefixedPadded("target"u8); + + /// <summary>Indicates the type of an entry</summary> + public static readonly byte[] Type = NarWriter.GetLengthPrefixedPadded("type"u8); + + /// <summary>Indicates that a regular file is executable</summary> + public static readonly byte[] Executable = NarWriter.GetLengthPrefixedPadded("executable"u8); + + /// <summary>Indicates the start of regular file contents</summary> + public static readonly byte[] Contents = NarWriter.GetLengthPrefixedPadded("contents"u8); +} \ No newline at end of file diff --git a/Rhea.Nar/NarWriter.cs b/Rhea.Nar/NarWriter.cs
index 424f52a..49b5eb6 100644 --- a/Rhea.Nar/NarWriter.cs +++ b/Rhea.Nar/NarWriter.cs
@@ -1,31 +1,8 @@ -using System.IO.Enumeration; -using System.Runtime.InteropServices; using ArcaneLibs; using ArcaneLibs.Extensions; namespace Rhea.Nar; -public ref struct NarConsts -{ - public static readonly byte[] Header = NarWriter.GetLengthPrefixedPadded("nix-archive-1"u8); - - public static readonly byte[] LeftParen = NarWriter.GetLengthPrefixedPadded("("u8); - public static readonly byte[] RightParen = NarWriter.GetLengthPrefixedPadded(")"u8); - - public static readonly byte[] Regular = NarWriter.GetLengthPrefixedPadded("regular"u8); - public static readonly byte[] Directory = NarWriter.GetLengthPrefixedPadded("directory"u8); - public static readonly byte[] Symlink = NarWriter.GetLengthPrefixedPadded("symlink"u8); - - public static readonly byte[] Entry = NarWriter.GetLengthPrefixedPadded("entry"u8); - public static readonly byte[] Name = NarWriter.GetLengthPrefixedPadded("name"u8); - public static readonly byte[] Target = NarWriter.GetLengthPrefixedPadded("target"u8); - public static readonly byte[] Node = NarWriter.GetLengthPrefixedPadded("node"u8); - public static readonly byte[] Type = NarWriter.GetLengthPrefixedPadded("type"u8); - public static readonly byte[] Executable = NarWriter.GetLengthPrefixedPadded("executable"u8); - - public static readonly byte[] Contents = NarWriter.GetLengthPrefixedPadded("contents"u8); -} - public class NarWriter { public Span<byte> GetHeader() @@ -42,19 +19,19 @@ public class NarWriter public IEnumerable<byte[]> GetNarStreamContentsInner(string path) { FileAttributes fattr = File.GetAttributes(path); - if (fattr.HasFlag(FileAttributes.Directory)) - foreach (var chunk in GetNarDirectoryContents(new DirectoryInfo(path))) - yield return chunk; - else + var linkTarget = new FileInfo(path).LinkTarget; + if (string.IsNullOrWhiteSpace(linkTarget)) { - var linkTarget = new FileInfo(path).LinkTarget; - if (string.IsNullOrWhiteSpace(linkTarget)) - foreach (var chunk in GetNarFileContents(new FileInfo(path))) + if (fattr.HasFlag(FileAttributes.Directory)) + foreach (var chunk in GetNarDirectoryContents(new DirectoryInfo(path))) yield return chunk; else - foreach (var chunk in GetNarSymlinkContents(new FileInfo(path))) + foreach (var chunk in GetNarFileContents(new FileInfo(path))) yield return chunk; } + else + foreach (var chunk in GetNarSymlinkContents(new FileInfo(path))) + yield return chunk; } private IEnumerable<byte[]> GetNarDirectoryContents(DirectoryInfo de) @@ -62,15 +39,19 @@ public class NarWriter yield return NarConsts.LeftParen; yield return NarConsts.Type; yield return NarConsts.Directory; - - foreach (var fe in FileUtils.EnumerateDirectory(de.FullName).OrderBy(x => x.Name)) + + foreach (var fe in FileUtils.EnumerateDirectory(de.FullName) + // .OrderBy(x=>x is DirectoryInfo ? 0 : 1) + // .ThenBy(x => x.Name, StringComparer.InvariantCultureIgnoreCase) + .OrderBy(x => x.Name, StringComparer.Ordinal) + ) { yield return NarConsts.Entry; yield return NarConsts.LeftParen; yield return NarConsts.Name; yield return GetLengthPrefixedPadded(fe.Name.AsBytes().ToArray()); - + yield return NarConsts.Node; foreach (var chunk in GetNarStreamContentsInner(fe.FullName)) yield return chunk; @@ -83,14 +64,26 @@ public class NarWriter private IEnumerable<byte[]> GetNarSymlinkContents(FileInfo fe) { - yield return NarConsts.LeftParen; + // yield return NarConsts.LeftParen; + // + // yield return NarConsts.Type; + // yield return NarConsts.Symlink; + // yield return NarConsts.Target; + // yield return GetLengthPrefixedPadded(fe.LinkTarget!.AsBytes().ToArray()); + // + // yield return NarConsts.RightParen; - yield return NarConsts.Type; - yield return NarConsts.Symlink; - yield return NarConsts.Target; - yield return GetLengthPrefixedPadded(fe.LinkTarget!.AsBytes().ToArray()); + yield return + [ + ..NarConsts.LeftParen, - yield return NarConsts.RightParen; + ..NarConsts.Type, + ..NarConsts.Symlink, + ..NarConsts.Target, + ..GetLengthPrefixedPadded(fe.LinkTarget!.AsBytes().ToArray()), + + ..NarConsts.RightParen + ]; } private IEnumerable<byte[]> GetNarFileContents(FileInfo fe) @@ -104,7 +97,10 @@ public class NarWriter || fe.UnixFileMode.HasFlag(UnixFileMode.GroupExecute) || fe.UnixFileMode.HasFlag(UnixFileMode.OtherExecute) ) + { yield return NarConsts.Executable; + yield return new byte[8]; + } var targetLength = Math.Ceiling(fe.Length / 8d) * 8UL; yield return NarConsts.Contents; @@ -135,11 +131,7 @@ public class NarWriter { byte[] unpadded = [..BitConverter.GetBytes((ulong)data.Length), .. data]; var targetLength = Math.Ceiling(unpadded.Length / 8d) * 8; - // Console.Write($"{unpadded.Length:X2} - "); - // unpadded.HexDump(); Array.Resize(ref unpadded, (int)targetLength); - // Console.Write($"{unpadded.Length:X2} - "); - // unpadded.HexDump(); return unpadded; } diff --git a/Rhea.Nar/Rhea.Nar.csproj b/Rhea.Nar/Rhea.Nar.csproj
index bcfc328..7057327 100644 --- a/Rhea.Nar/Rhea.Nar.csproj +++ b/Rhea.Nar/Rhea.Nar.csproj
@@ -5,6 +5,8 @@ <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <PublishAot>true</PublishAot> + <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> <ItemGroup>