mirror of
https://github.com/quamotion/dotnet-packaging.git
synced 2026-05-18 11:26:40 +00:00
Support writing data to a cpio file.
This commit is contained in:
@@ -104,6 +104,72 @@ namespace Packaging.Targets.IO
|
||||
get { return this.entryDataLength == 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an entry to the <see cref="CpioFile"/>
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="CpioHeader"/> with the item metaata. The <see cref="CpioHeader.Signature"/>,
|
||||
/// <see cref="CpioHeader.NameSize"/> and <see cref="CpioHeader.Filesize"/> values are overwritten.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// The file name of the entry.
|
||||
/// </param>
|
||||
/// <param name="data">
|
||||
/// A <see cref="Stream"/> which contains the file data.
|
||||
/// </param>
|
||||
public void Write(CpioHeader header, string name, Stream data)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(data));
|
||||
}
|
||||
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(name);
|
||||
|
||||
// We make sure the magic and size fields have the correct values. All other fields
|
||||
// are the responsibility of the caller.
|
||||
header.Signature = "070701";
|
||||
header.NameSize = (uint)(nameBytes.Length + 1);
|
||||
header.FileSize = (uint)data.Length;
|
||||
|
||||
this.stream.WriteStruct(header);
|
||||
this.stream.Write(nameBytes, 0, nameBytes.Length);
|
||||
|
||||
// The pathname is followed by NUL bytes so that the total size of the fixed
|
||||
// header plus pathname is a multiple of four.
|
||||
var headerSize = Marshal.SizeOf<CpioHeader>() + nameBytes.Length;
|
||||
var paddingSize = PaddingSize(headerSize);
|
||||
|
||||
for (int i = 0; i < paddingSize; i++)
|
||||
{
|
||||
this.stream.WriteByte(0);
|
||||
}
|
||||
|
||||
data.Position = 0;
|
||||
data.CopyTo(this.stream);
|
||||
|
||||
// The file data is padded to a multiple of four bytes.
|
||||
paddingSize = PaddingSize((int)data.Length);
|
||||
|
||||
for (int i = 0; i < paddingSize; i++)
|
||||
{
|
||||
this.stream.WriteByte(0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the trailer entry.
|
||||
/// </summary>
|
||||
public void WriteTrailer()
|
||||
{
|
||||
this.Write(CpioHeader.Empty, "TRAILER!!!", new MemoryStream(Array.Empty<byte>()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next entry in the <see cref="CpioFile"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Packaging.Targets.IO
|
||||
/// whether this archive is written with little-endian or big-endian integers,
|
||||
/// or ASCII.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 6)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 6)] // 0 through 5
|
||||
private char[] signature;
|
||||
|
||||
/// <summary>
|
||||
@@ -24,25 +24,25 @@ namespace Packaging.Targets.IO
|
||||
/// refer to the same file. Programs that synthesize cpio archives
|
||||
/// should be careful to set these to distinct values for each entry.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 6 through 13
|
||||
private char[] ino;
|
||||
|
||||
/// <summary>
|
||||
/// The mode specifies both the regular permissions and the file type.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 14 through 21
|
||||
private char[] mode;
|
||||
|
||||
/// <summary>
|
||||
/// The numeric user id of the owner.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 22 through 29
|
||||
private char[] uid;
|
||||
|
||||
/// <summary>
|
||||
/// The numeric group id of the owner.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 30 through 37
|
||||
private char[] gid;
|
||||
|
||||
/// <summary>
|
||||
@@ -50,7 +50,7 @@ namespace Packaging.Targets.IO
|
||||
/// value of at least two here. Note that hardlinked files include
|
||||
/// file data with every copy in the archive.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 38 through 45
|
||||
private char[] nlink;
|
||||
|
||||
/// <summary>
|
||||
@@ -60,7 +60,7 @@ namespace Packaging.Targets.IO
|
||||
/// first followed by the least-significant 16 bits.Each of the two
|
||||
/// 16 bit values are stored in machine-native byte order.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 46 through 53
|
||||
private char[] mtime;
|
||||
|
||||
/// <summary>
|
||||
@@ -68,13 +68,13 @@ namespace Packaging.Targets.IO
|
||||
/// to four gigabyte file sizes.See mtime above for a description
|
||||
/// of the storage of four-byte integers.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 54 through 61
|
||||
private char[] filesize;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 62 through 69
|
||||
private char[] devMajor;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 70 through 77
|
||||
private char[] devMinor;
|
||||
|
||||
/// <summary>
|
||||
@@ -82,135 +82,176 @@ namespace Packaging.Targets.IO
|
||||
/// the associated device number. For all other entry types,
|
||||
/// it should be set to zero by writers and ignored by readers.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 78 through 85
|
||||
private char[] rdevMajor;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 86 through 93
|
||||
private char[] rdevMinor;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes in the pathname that follows the header.
|
||||
/// This count includes the trailing NUL byte.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 94 through 101
|
||||
private char[] namesize;
|
||||
|
||||
/// <summary>
|
||||
/// This field is always set to zero by writers and ignored by readers.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)] // 102 through 109
|
||||
private char[] check;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="signature"/> field as a <see cref="string"/>.
|
||||
/// Gets an empty <see cref="CpioHeader"/> entry.
|
||||
/// </summary>
|
||||
public static CpioHeader Empty
|
||||
{
|
||||
get
|
||||
{
|
||||
return new CpioHeader()
|
||||
{
|
||||
Check = 0,
|
||||
DevMajor = 0,
|
||||
DevMinor = 0,
|
||||
FileSize = 0,
|
||||
Gid = 0,
|
||||
Ino = 0,
|
||||
Mode = 0,
|
||||
Mtime = 0,
|
||||
NameSize = 0,
|
||||
Nlink = 1,
|
||||
RDevMajor = 0,
|
||||
RDevMinor = 0,
|
||||
Signature = "070701",
|
||||
Uid = 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the <see cref="signature"/> field as a <see cref="string"/>.
|
||||
/// </summary>
|
||||
public string Signature
|
||||
{
|
||||
get { return new string(this.signature); }
|
||||
set { this.signature = value.ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="ino"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="ino"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint Ino
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.ino), 16); }
|
||||
set { this.ino = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="mode"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="mode"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint Mode
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.mode), 16); }
|
||||
set { this.mode = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="uid"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="uid"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint Uid
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.uid), 16); }
|
||||
set { this.uid = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="gid"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="gid"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint Gid
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.gid), 16); }
|
||||
set { this.gid = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="nlink"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="nlink"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint Nlink
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.nlink), 16); }
|
||||
set { this.nlink = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="mtime"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="mtime"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint Mtime
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.mtime), 16); }
|
||||
set { this.mtime = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="filesize"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="filesize"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint FileSize
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.filesize), 16); }
|
||||
set { this.filesize = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="devMajor"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="devMajor"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint DevMajor
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.devMajor), 16); }
|
||||
set { this.devMajor = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="devMinor"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="devMinor"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint DevMinor
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.devMinor), 16); }
|
||||
set { this.devMinor = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="rdevMajor"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="rdevMajor"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint RDevMajor
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.rdevMajor), 16); }
|
||||
set { this.rdevMajor = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="rdevMinor"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="rdevMinor"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint RDevMinor
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.rdevMinor), 16); }
|
||||
set { this.rdevMinor = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="namesize"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="namesize"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint NameSize
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.namesize), 16); }
|
||||
set { this.namesize = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="check"/> field as a <see cref="uint"/>.
|
||||
/// Gets or sets the value of the <see cref="check"/> field as a <see cref="uint"/>.
|
||||
/// </summary>
|
||||
public uint Check
|
||||
{
|
||||
get { return Convert.ToUInt32(new string(this.check), 16); }
|
||||
set { this.check = value.ToString("x8").ToCharArray(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user