Skip to content

Commit 6b950f4

Browse files
authored
Write file data into archive only for regular files (apple#1403)
## Type of Change - [x] Bug fix - [ ] New feature - [ ] Breaking change - [ ] Documentation update ## Motivation and Context Closes apple#1375 ## Testing - [x] Tested locally - [ ] Added/updated tests - [ ] Added/updated docs --------- Signed-off-by: Aditya Ramani <a_ramani@apple.com>
1 parent a1981c3 commit 6b950f4

2 files changed

Lines changed: 55 additions & 30 deletions

File tree

Sources/Services/ContainerAPIService/Client/Archiver.swift

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public final class Archiver: Sendable {
9696
guard let entry = try Self._createEntry(entryInfo: info) else {
9797
throw Error.failedToCreateEntry
9898
}
99-
hasher.update(data: try encoder.encode(info))
99+
hasher.update(data: try encoder.encode(entry))
100100
try Self._compressFile(item: info.pathOnHost, entry: entry, archiver: archiver, hasher: &hasher)
101101
}
102102
try archiver.finishEncoding()
@@ -110,30 +110,31 @@ public final class Archiver: Sendable {
110110

111111
// MARK: private functions
112112
private static func _compressFile(item: URL, entry: WriteEntry, archiver: ArchiveWriter, hasher: inout SHA256) throws {
113-
guard let stream = InputStream(url: item) else {
114-
return
115-
}
116-
117113
let writer = archiver.makeTransactionWriter()
118-
119114
let bufferSize = Int(1.mib())
120115
let readBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
121-
122-
stream.open()
123116
try writer.writeHeader(entry: entry)
124-
while true {
125-
let byteRead = stream.read(readBuffer, maxLength: bufferSize)
126-
if byteRead <= 0 {
127-
break
128-
} else {
129-
let data = Data(bytes: readBuffer, count: byteRead)
130-
hasher.update(data: data)
131-
try data.withUnsafeBytes { pointer in
132-
try writer.writeChunk(data: pointer)
117+
if entry.fileType == .regular {
118+
// We need to write the data into the archive only if its a regular file
119+
// Symlinks and directories require us to only write the archive header
120+
guard let stream = InputStream(url: item) else {
121+
throw Error.failedToCreateInputStream(item)
122+
}
123+
stream.open()
124+
while true {
125+
let byteRead = stream.read(readBuffer, maxLength: bufferSize)
126+
if byteRead <= 0 {
127+
break
128+
} else {
129+
let data = Data(bytesNoCopy: UnsafeMutableRawPointer(mutating: readBuffer), count: byteRead, deallocator: .none)
130+
hasher.update(data: data)
131+
try data.withUnsafeBytes { pointer in
132+
try writer.writeChunk(data: pointer)
133+
}
133134
}
134135
}
136+
stream.close()
135137
}
136-
stream.close()
137138
try writer.finish()
138139
}
139140

@@ -214,30 +215,54 @@ public final class Archiver: Sendable {
214215
let trimmedPath = String(decodedPath.suffix(from: pathPrefix.endIndex))
215216
return trimmedPath
216217
}
217-
218-
private static func _isSymbolicLink(_ path: URL) throws -> Bool {
219-
let resourceValues = try path.resourceValues(forKeys: [.isSymbolicLinkKey])
220-
if let isSymbolicLink = resourceValues.isSymbolicLink {
221-
if isSymbolicLink {
222-
return true
223-
}
224-
}
225-
return false
226-
}
227218
}
228219

229220
extension Archiver {
230221
public enum Error: Swift.Error, CustomStringConvertible {
231222
case failedToCreateEntry
232223
case fileDoesNotExist(_ url: URL)
224+
case failedToCreateInputStream(_ url: URL)
233225

234226
public var description: String {
235227
switch self {
236228
case .failedToCreateEntry:
237229
return "failed to create entry"
238230
case .fileDoesNotExist(let url):
239231
return "file \(url.path) does not exist"
232+
case .failedToCreateInputStream(let url):
233+
return "failed to create input stream for \(url.path)"
240234
}
241235
}
242236
}
243237
}
238+
239+
extension WriteEntry: @retroactive Encodable {
240+
enum CodingKeys: String, CodingKey {
241+
case path
242+
case fileType
243+
case size
244+
case permissions
245+
case owner
246+
case group
247+
case symlinkTarget
248+
case hardlink
249+
case creationDate
250+
case modificationDate
251+
case contentAccessDate
252+
}
253+
254+
public func encode(to encoder: any Encoder) throws {
255+
var container = encoder.container(keyedBy: CodingKeys.self)
256+
try container.encodeIfPresent(fileType.rawValue, forKey: .fileType)
257+
try container.encodeIfPresent(permissions, forKey: .permissions)
258+
try container.encodeIfPresent(path, forKey: .path)
259+
try container.encodeIfPresent(size, forKey: .size)
260+
try container.encodeIfPresent(owner, forKey: .owner)
261+
try container.encodeIfPresent(group, forKey: .group)
262+
try container.encodeIfPresent(symlinkTarget, forKey: .symlinkTarget)
263+
try container.encodeIfPresent(hardlink, forKey: .hardlink)
264+
try container.encodeIfPresent(creationDate, forKey: .creationDate)
265+
try container.encodeIfPresent(modificationDate, forKey: .modificationDate)
266+
try container.encodeIfPresent(contentAccessDate, forKey: .contentAccessDate)
267+
}
268+
}

Tests/CLITests/Subcommands/Build/CLIBuilderTest.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,13 +357,13 @@ extension TestCLIBuildBase {
357357
// test 1
358358
.directory("Test1Source"),
359359
.directory("Test1Source2"),
360-
.file("Test1Source/test.yaml", content: .zeroFilled(size: 1)),
360+
.file("Test1Source/test.yaml", content: .zeroFilled(size: 200)),
361361
.symbolicLink("Test1Source2/test.yaml", target: "Test1Source/test.yaml"),
362362

363363
// test 2
364364
.directory("Test2Source"),
365365
.directory("Test2Source2"),
366-
.file("Test2Source/Test/Test/test.yaml", content: .zeroFilled(size: 1)),
366+
.file("Test2Source/Test/Test/test.yaml", content: .zeroFilled(size: 300)),
367367
.symbolicLink("Test2Source2/Test/test.yaml", target: "Test2Source/Test/Test/test.yaml"),
368368

369369
// test 3

0 commit comments

Comments
 (0)