Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rar5 read FHEXTRA_REDIR and expose via RarEntry #814

Merged
merged 1 commit into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 19 additions & 7 deletions src/SharpCompress/Common/Rar/Headers/FileHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ private void ReadFromReaderV5(MarkingBinaryReader reader)
const ushort FHEXTRA_HASH = 0x02;
const ushort FHEXTRA_HTIME = 0x03;
// const ushort FHEXTRA_VERSION = 0x04;
// const ushort FHEXTRA_REDIR = 0x05;
const ushort FHEXTRA_REDIR = 0x05;
// const ushort FHEXTRA_UOWNER = 0x06;
// const ushort FHEXTRA_SUBDATA = 0x07;

Expand All @@ -120,7 +120,6 @@ private void ReadFromReaderV5(MarkingBinaryReader reader)
var type = reader.ReadRarVIntUInt16();
switch (type)
{
//TODO
case FHEXTRA_CRYPT: // file encryption

{
Expand Down Expand Up @@ -171,11 +170,17 @@ private void ReadFromReaderV5(MarkingBinaryReader reader)
//
// }
// break;
// case FHEXTRA_REDIR: // file system redirection
// {
//
// }
// break;
case FHEXTRA_REDIR: // file system redirection

{
RedirType = reader.ReadRarVIntByte();
RedirFlags = reader.ReadRarVIntByte();
var nn = reader.ReadRarVIntUInt16();
var bb = reader.ReadBytes(nn);
RedirTargetName = ConvertPathV5(Encoding.UTF8.GetString(bb, 0, bb.Length));
}
break;
//TODO
// case FHEXTRA_UOWNER: // unix owner
// {
//
Expand All @@ -189,6 +194,7 @@ private void ReadFromReaderV5(MarkingBinaryReader reader)

default:
// skip unknown record types to allow new record types to be added in the future
//Console.WriteLine($"unhandled rar header field type {type}");
break;
}
// drain any trailing bytes of extra record
Expand Down Expand Up @@ -437,6 +443,12 @@ internal byte[] FileCrc

public bool IsSolid { get; private set; }

public byte RedirType { get; private set; }
public bool IsRedir => RedirType != 0;
public byte RedirFlags { get; private set; }
public bool IsRedirDirectory => (RedirFlags & RedirFlagV5.DIRECTORY) != 0;
public string RedirTargetName { get; private set; }

// unused for UnpackV1 implementation (limitation)
internal size_t WindowSize { get; private set; }

Expand Down
14 changes: 14 additions & 0 deletions src/SharpCompress/Common/Rar/Headers/Flags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,17 @@ internal static class EndArchiveFlagsV5
{
public const ushort HAS_NEXT_VOLUME = 0x0001;
}

internal static class RedirTypeV5
{
public const byte UNIX_SYMLINK = 0x0001;
public const byte WIN_SYMLINK = 0x0002;
public const byte WIN_JUNCTION = 0x0003;
public const byte HARD_LINK = 0x0004;
public const byte FILE_COPY = 0x0005;
}

internal static class RedirFlagV5
{
public const byte DIRECTORY = 0x0001;
}
4 changes: 4 additions & 0 deletions src/SharpCompress/Common/Rar/RarEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ public abstract class RarEntry : Entry

public override bool IsSplitAfter => FileHeader.IsSplitAfter;

public bool IsRedir => FileHeader.IsRedir;

public string RedirTargetName => FileHeader.RedirTargetName;

public override string ToString() =>
string.Format(
"Entry Path: {0} Compressed Size: {1} Uncompressed Size: {2} CRC: {3}",
Expand Down
7 changes: 7 additions & 0 deletions src/SharpCompress/Compressors/Rar/RarStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ public override int Read(byte[] buffer, int offset, int count)
fetch = false;
}
_position += outTotal;
if (count > 0 && outTotal == 0 && _position != Length)
{
// sanity check, eg if we try to decompress a redir entry
throw new InvalidOperationException(
$"unpacked file size does not match header: expected {Length} found {_position}"
);
}
return outTotal;
}

Expand Down
6 changes: 6 additions & 0 deletions src/SharpCompress/Readers/Rar/RarReader.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -64,6 +65,11 @@ protected override IEnumerable<RarReaderEntry> GetEntries(Stream stream)

protected override EntryStream GetEntryStream()
{
if (Entry.IsRedir)
{
throw new InvalidOperationException("no stream for redirect entry");
}

var stream = new MultiVolumeReadOnlyStream(
CreateFilePartEnumerableForCurrentEntry().Cast<RarFilePart>(),
this
Expand Down