mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
[TAR] Remove TarEntryInfo.blockStartIndex
To accomplish this, we added a second associated value to ParsingResult.entryInfo and rewrote TarContainer.open in similar way to TarContainer.info.
This commit is contained in:
@@ -52,7 +52,7 @@ public class TarContainer: Container {
|
||||
} else if specialEntryType == .longName || specialEntryType == .longLinkName {
|
||||
return .gnu
|
||||
}
|
||||
case .entryInfo(let info):
|
||||
case .entryInfo(let info, _):
|
||||
// TODO: Probably this case (depending on how info.format is set) is already covered by the above.
|
||||
switch info.format {
|
||||
case .pax:
|
||||
@@ -175,25 +175,42 @@ public class TarContainer: Container {
|
||||
- Returns: Array of `TarEntry`.
|
||||
*/
|
||||
public static func open(container data: Data) throws -> [TarEntry] {
|
||||
let infos = try info(container: data)
|
||||
// TAR container should be at least 512 bytes long (when it contains only one header).
|
||||
guard data.count >= 512
|
||||
else { throw TarError.tooSmallFileIsPassed }
|
||||
|
||||
var parser = TarParser(data)
|
||||
var entries = [TarEntry]()
|
||||
|
||||
for entryInfo in infos {
|
||||
if entryInfo.type == .directory {
|
||||
var entry = TarEntry(info: entryInfo, data: nil)
|
||||
entry.info.size = 0
|
||||
entries.append(entry)
|
||||
} else {
|
||||
let dataStartIndex = entryInfo.blockStartIndex + 512
|
||||
let dataEndIndex = dataStartIndex + entryInfo.size!
|
||||
// Verify that data is not truncated.
|
||||
// The data.startIndex inequality is strict since by this point at least one header (i.e. 512 bytes)
|
||||
// has been processed. The data.endIndex inequality is strict since there can be a 1024 bytes-long EOF
|
||||
// marker block which isn't included into any entry.
|
||||
guard dataStartIndex > data.startIndex && dataEndIndex < data.endIndex
|
||||
else { throw TarError.wrongField }
|
||||
let entryData = data.subdata(in: dataStartIndex..<dataEndIndex)
|
||||
entries.append(TarEntry(info: entryInfo, data: entryData))
|
||||
parsingLoop: while true {
|
||||
let result = try parser.next()
|
||||
switch result {
|
||||
case .specialEntry:
|
||||
continue parsingLoop
|
||||
case .entryInfo(let info, let blockStartIndex):
|
||||
if info.type == .directory {
|
||||
var entry = TarEntry(info: info, data: nil)
|
||||
entry.info.size = 0
|
||||
entries.append(entry)
|
||||
} else {
|
||||
let dataStartIndex = blockStartIndex + 512
|
||||
let dataEndIndex = dataStartIndex + info.size!
|
||||
// Verify that data is not truncated.
|
||||
// The data.startIndex inequality is strict since by this point at least one header (i.e. 512 bytes)
|
||||
// has been processed. The data.endIndex inequality is strict since there can be a 1024 bytes-long EOF
|
||||
// marker block which isn't included into any entry.
|
||||
guard dataStartIndex > data.startIndex && dataEndIndex < data.endIndex
|
||||
else { throw TarError.wrongField }
|
||||
let entryData = data.subdata(in: dataStartIndex..<dataEndIndex)
|
||||
entries.append(TarEntry(info: info, data: entryData))
|
||||
}
|
||||
case .truncated:
|
||||
// We don't have an error with a more suitable name.
|
||||
throw TarError.wrongField
|
||||
case .finished:
|
||||
fallthrough
|
||||
case .eofMarker:
|
||||
break parsingLoop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +243,7 @@ public class TarContainer: Container {
|
||||
switch result {
|
||||
case .specialEntry:
|
||||
continue parsingLoop
|
||||
case .entryInfo(let info):
|
||||
case .entryInfo(let info, _):
|
||||
entries.append(info)
|
||||
case .truncated:
|
||||
// We don't have an error with a more suitable name.
|
||||
|
||||
@@ -169,9 +169,6 @@ public struct TarEntryInfo: ContainerEntryInfo {
|
||||
|
||||
let format: TarContainer.Format
|
||||
|
||||
// TODO: Remove
|
||||
let blockStartIndex: Int
|
||||
|
||||
/**
|
||||
Initializes the entry's info with its name and type.
|
||||
|
||||
@@ -186,13 +183,10 @@ public struct TarEntryInfo: ContainerEntryInfo {
|
||||
self.linkName = ""
|
||||
// These properties are only used when entry is loaded from the container.
|
||||
self.format = .pax
|
||||
self.blockStartIndex = 0
|
||||
}
|
||||
|
||||
init(_ header: TarHeader, _ global: TarExtendedHeader?, _ local: TarExtendedHeader?,
|
||||
_ longName: String?, _ longLinkName: String?) {
|
||||
// TODO: Remove
|
||||
self.blockStartIndex = header.blockStartIndex
|
||||
// General notes for all the properties processing below:
|
||||
// 1. There might be a corresponding field in either global or local extended PAX header.
|
||||
// 2. We still need to read general TAR fields so we can't eliminate auxiliary local let-variables.
|
||||
|
||||
@@ -15,7 +15,7 @@ struct TarParser {
|
||||
case eofMarker
|
||||
case finished
|
||||
case specialEntry(TarHeader.SpecialEntryType)
|
||||
case entryInfo(TarEntryInfo)
|
||||
case entryInfo(TarEntryInfo, Int)
|
||||
}
|
||||
|
||||
private let reader: LittleEndianByteReader
|
||||
@@ -70,7 +70,7 @@ struct TarParser {
|
||||
lastLocalExtendedHeader = nil
|
||||
longName = nil
|
||||
longLinkName = nil
|
||||
return .entryInfo(info)
|
||||
return .entryInfo(info, header.blockStartIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user