Skip to content

Commit 44ecb87

Browse files
authored
Agent: Add single file copying (#463)
Add a streaming rpc to copy single files in and out. This can easily be extended to support copying directories, but we need the guest agent to be able to tar/untar, and we'll need to figure out what that model is.
1 parent fb95398 commit 44ecb87

File tree

9 files changed

+1165
-8
lines changed

9 files changed

+1165
-8
lines changed

Sources/Containerization/LinuxContainer.swift

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//===----------------------------------------------------------------------===//
2-
// Copyright © 2025 Apple Inc. and the Containerization project authors.
2+
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -830,6 +830,59 @@ extension LinuxContainer {
830830
try await relayManager.start(port: port, socket: socket)
831831
try await relayAgent.relaySocket(port: port, configuration: socket)
832832
}
833+
834+
/// Default chunk size for file transfers (1MiB).
835+
public static let defaultCopyChunkSize = 1024 * 1024
836+
837+
/// Copy a file from the host into the container.
838+
public func copyIn(
839+
from source: URL,
840+
to destination: URL,
841+
mode: UInt32 = 0o644,
842+
createParents: Bool = true,
843+
chunkSize: Int = defaultCopyChunkSize,
844+
progress: ProgressHandler? = nil
845+
) async throws {
846+
try await self.state.withLock {
847+
let state = try $0.startedState("copyIn")
848+
849+
let guestPath = URL(filePath: self.root).appending(path: destination.path)
850+
try await state.vm.withAgent { agent in
851+
try await agent.copyIn(
852+
from: source,
853+
to: guestPath,
854+
mode: mode,
855+
createParents: createParents,
856+
chunkSize: chunkSize,
857+
progress: progress
858+
)
859+
}
860+
}
861+
}
862+
863+
/// Copy a file from the container to the host.
864+
public func copyOut(
865+
from source: URL,
866+
to destination: URL,
867+
createParents: Bool = true,
868+
chunkSize: Int = defaultCopyChunkSize,
869+
progress: ProgressHandler? = nil
870+
) async throws {
871+
try await self.state.withLock {
872+
let state = try $0.startedState("copyOut")
873+
874+
let guestPath = URL(filePath: self.root).appending(path: source.path)
875+
try await state.vm.withAgent { agent in
876+
try await agent.copyOut(
877+
from: guestPath,
878+
to: destination,
879+
createParents: createParents,
880+
chunkSize: chunkSize,
881+
progress: progress
882+
)
883+
}
884+
}
885+
}
833886
}
834887

835888
extension VirtualMachineInstance {

Sources/Containerization/SandboxContext/SandboxContext.grpc.swift

Lines changed: 214 additions & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)