mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-10-02 08:04:32 +08:00
Seed RootHide loader links for bootstrap tools
This commit is contained in:
@@ -49,7 +49,13 @@ script runs. For this minimal vphone bootstrap, vphoned writes a real installed
|
||||
`Library/dpkg/status`; Irisin's installed list, resolver, and helper then read
|
||||
the same record. If the status already contains firmware from another
|
||||
bootstrap, vphoned preserves it. A vphoned-owned record is updated after an
|
||||
iOS version change when vphoned starts. `POST /v1/bootstrap/firmware` (RPC `bootstrap.firmware`)
|
||||
iOS version change when vphoned starts. For RootHide, vphoned also creates
|
||||
the `.jbroot` loader links in the bootstrap root and standard executable and
|
||||
library directories. On startup it repairs missing links for an existing
|
||||
completed installation without replacing links that point elsewhere. These
|
||||
links let `@loader_path/.jbroot/usr/lib/...` dependencies resolve when a
|
||||
package manager later installs tools such as `dash`.
|
||||
`POST /v1/bootstrap/firmware` (RPC `bootstrap.firmware`)
|
||||
repairs the record for a bootstrap already identified by the completion marker
|
||||
without running another install. The reply includes the tag,
|
||||
bootstrap path, registration record, and launchd status. A successful bootstrap
|
||||
|
||||
@@ -238,6 +238,7 @@ enum GuestIrisinInstaller {
|
||||
for (source, target) in components {
|
||||
replaced.append(try replace(source, at: target))
|
||||
}
|
||||
if layout == "roothide" { try ensureRootHideLinks(root: root) }
|
||||
let registration = try registerApp(installedApp.path)
|
||||
let loaded = try loadServices([installedPlist.path], load: true, override: false)
|
||||
var started: [String: Any]?
|
||||
@@ -312,8 +313,15 @@ enum GuestIrisinInstaller {
|
||||
"firmware_version": firmware.version, "dpkg_database_updated": firmware.updated]
|
||||
}
|
||||
|
||||
static func refreshFirmwareOnStartup() {
|
||||
static func refreshBootstrapOnStartup() {
|
||||
guard itemExists(completionMarker) else { return }
|
||||
do {
|
||||
if let installation = try completedBootstrap(), installation.layout == "roothide" {
|
||||
try ensureRootHideLinks(root: installation.root)
|
||||
}
|
||||
} catch {
|
||||
NSLog("vphoned: could not repair RootHide loader links: %@", String(describing: error))
|
||||
}
|
||||
do {
|
||||
_ = try repairFirmwareRecord()
|
||||
} catch {
|
||||
@@ -321,6 +329,45 @@ enum GuestIrisinInstaller {
|
||||
}
|
||||
}
|
||||
|
||||
/// RootHide's @loader_path references resolve through a .jbroot link in
|
||||
/// each directory containing bootstrap Mach-O files. Seed the standard
|
||||
/// directories before a package manager installs its first shell.
|
||||
private static func ensureRootHideLinks(root: String) throws {
|
||||
guard try directoryExistsWithoutSymlink(root) else {
|
||||
throw GuestAPIError.operationFailed("RootHide bootstrap root is missing: \(root)")
|
||||
}
|
||||
let files = FileManager.default
|
||||
|
||||
func link(_ path: String, target: String) throws {
|
||||
var info = stat()
|
||||
if lstat(path, &info) == 0 {
|
||||
guard info.st_mode & mode_t(S_IFMT) == mode_t(S_IFLNK),
|
||||
try files.destinationOfSymbolicLink(atPath: path) == target else {
|
||||
throw GuestAPIError.operationFailed("RootHide loader link has an unexpected target: \(path)")
|
||||
}
|
||||
return
|
||||
}
|
||||
guard errno == ENOENT else {
|
||||
throw GuestAPIError.operationFailed("Could not inspect RootHide loader link: \(path)")
|
||||
}
|
||||
try files.createSymbolicLink(atPath: path, withDestinationPath: target)
|
||||
}
|
||||
|
||||
try link(root + "/.jbroot", target: ".")
|
||||
for relative in ["bin", "sbin", "usr/bin", "usr/sbin", "usr/lib", "usr/libexec"] {
|
||||
var directory = root
|
||||
for component in relative.split(separator: "/") {
|
||||
directory += "/" + component
|
||||
if try !directoryExistsWithoutSymlink(directory) {
|
||||
try files.createDirectory(atPath: directory, withIntermediateDirectories: false)
|
||||
}
|
||||
}
|
||||
let depth = relative.split(separator: "/").count
|
||||
let target = String(repeating: "../", count: depth) + ".jbroot"
|
||||
try link(directory + "/.jbroot", target: target)
|
||||
}
|
||||
}
|
||||
|
||||
/// This vphone bootstrap has no firmware maintainer script. Write the
|
||||
/// virtual package into the same dpkg status file Irisin and its helper read.
|
||||
private static func ensureFirmwareRecord(root: String) throws -> (version: String, updated: Bool) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import VphonedNative
|
||||
|
||||
vp_native_bootstrap_cached_binary()
|
||||
vp_vcam_start()
|
||||
GuestIrisinInstaller.refreshFirmwareOnStartup()
|
||||
GuestIrisinInstaller.refreshBootstrapOnStartup()
|
||||
|
||||
let group = MultiThreadedEventLoopGroup(numberOfThreads: 2)
|
||||
let filePool = NIOThreadPool(numberOfThreads: 2)
|
||||
|
||||
Reference in New Issue
Block a user