mirror of
https://github.com/blacktop/ipsw.git
synced 2026-05-08 12:22:26 +00:00
fix: add MountedFilesystemRoot helper and apply it consistently
This commit is contained in:
@@ -496,6 +496,26 @@ func Mount(image, mountPoint string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MountedFilesystemRoot returns the root directory of a mounted filesystem.
|
||||
// apfs-fuse exposes APFS volume contents below <mountPoint>/root; hdiutil and
|
||||
// hfsfuse expose the volume contents directly at <mountPoint>.
|
||||
func MountedFilesystemRoot(mountPoint string) string {
|
||||
mountPoint = filepath.Clean(mountPoint)
|
||||
|
||||
rootPath := filepath.Join(mountPoint, "root")
|
||||
rootInfo, err := os.Stat(rootPath)
|
||||
if err != nil || !rootInfo.IsDir() {
|
||||
return mountPoint
|
||||
}
|
||||
|
||||
systemPath := filepath.Join(mountPoint, "System")
|
||||
if _, err := os.Stat(systemPath); !os.IsNotExist(err) {
|
||||
return mountPoint
|
||||
}
|
||||
|
||||
return rootPath
|
||||
}
|
||||
|
||||
// mountLinux mounts a DMG on Linux using the appropriate FUSE tool based on filesystem type
|
||||
func mountLinux(image, mountPoint string) error {
|
||||
// First, try to detect the filesystem type
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
@@ -45,6 +46,33 @@ func TestSanitizeArchivePath(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMountedFilesystemRoot(t *testing.T) {
|
||||
t.Run("apfs fuse root", func(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
if err := os.MkdirAll(filepath.Join(root, "root", "System"), 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if got, want := MountedFilesystemRoot(root), filepath.Join(root, "root"); got != want {
|
||||
t.Fatalf("MountedFilesystemRoot() = %q, want %q", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("direct system wins", func(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
if err := os.MkdirAll(filepath.Join(root, "root", "System"), 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Join(root, "System"), 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if got, want := MountedFilesystemRoot(root), filepath.Clean(root); got != want {
|
||||
t.Fatalf("MountedFilesystemRoot() = %q, want %q", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDifference(t *testing.T) {
|
||||
type args struct {
|
||||
a []string
|
||||
|
||||
+1
-8
@@ -34,14 +34,7 @@ func GetDscPathsInMount(mountPoint string, driverKit, all bool) ([]string, error
|
||||
var matches []string
|
||||
var re *regexp.Regexp
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
// apfs-fuse mounts volume at mountPoint + "/root", but hfsfuse mounts directly
|
||||
// Check if /root subdirectory exists to determine mount structure
|
||||
rootPath := filepath.Join(mountPoint, "root")
|
||||
if _, err := os.Stat(rootPath); err == nil {
|
||||
mountPoint = rootPath
|
||||
}
|
||||
}
|
||||
mountPoint = utils.MountedFilesystemRoot(mountPoint)
|
||||
|
||||
if driverKit {
|
||||
re = regexp.MustCompile(filepath.Join(mountPoint, DriverKitCacheRegex))
|
||||
|
||||
+8
-5
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
"github.com/blacktop/go-plist"
|
||||
"github.com/blacktop/ipsw/internal/commands/mount"
|
||||
"github.com/blacktop/ipsw/internal/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -156,10 +157,12 @@ func WalkIPSW(path string, cfg *IPSWConfig) ([]Record, []SkippedVolume, error) {
|
||||
}
|
||||
|
||||
func WalkVolume(root, volume string) ([]Record, error) {
|
||||
volumeRoot := utils.MountedFilesystemRoot(root)
|
||||
|
||||
var candidates []plistCandidate
|
||||
seen := make(map[string]struct{})
|
||||
addCandidate := func(kind, path string) {
|
||||
rel := relativePlistPath(root, path)
|
||||
rel := relativePlistPath(volumeRoot, path)
|
||||
key := kind + "\x00" + rel
|
||||
if _, ok := seen[key]; ok {
|
||||
return
|
||||
@@ -169,7 +172,7 @@ func WalkVolume(root, volume string) ([]Record, error) {
|
||||
}
|
||||
|
||||
for _, spec := range launchdPlistDirs {
|
||||
matches, err := filepath.Glob(filepath.Join(root, filepath.FromSlash(spec.dir), "*.plist"))
|
||||
matches, err := filepath.Glob(filepath.Join(volumeRoot, filepath.FromSlash(spec.dir), "*.plist"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -178,7 +181,7 @@ func WalkVolume(root, volume string) ([]Record, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
|
||||
if err := filepath.WalkDir(volumeRoot, func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
return nil
|
||||
@@ -188,7 +191,7 @@ func WalkVolume(root, volume string) ([]Record, error) {
|
||||
if d.IsDir() || d.Name() != "Info.plist" {
|
||||
return nil
|
||||
}
|
||||
rel := relativePlistPath(root, path)
|
||||
rel := relativePlistPath(volumeRoot, path)
|
||||
switch {
|
||||
case isXPCInfoPlist(rel):
|
||||
addCandidate(SourceKindXPCBundle, path)
|
||||
@@ -209,7 +212,7 @@ func WalkVolume(root, volume string) ([]Record, error) {
|
||||
|
||||
records := make([]Record, 0, len(candidates))
|
||||
for _, candidate := range candidates {
|
||||
record, ok := recordFromFile(root, volume, candidate.kind, candidate.path)
|
||||
record, ok := recordFromFile(volumeRoot, volume, candidate.kind, candidate.path)
|
||||
if ok {
|
||||
records = append(records, record)
|
||||
}
|
||||
|
||||
@@ -126,6 +126,40 @@ func TestWalkVolumeXPCBundleLayouts(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWalkVolumeAPFSFuseRootPrefix(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
writePlist(t, root, "/root/System/Library/LaunchDaemons/com.apple.rooted.plist", map[string]any{
|
||||
"Label": "com.apple.rooted",
|
||||
"Program": "/usr/libexec/rooted",
|
||||
}, plist.XMLFormat)
|
||||
writePlist(t, root, "/root/Applications/Foo.app/XPCServices/FooService.xpc/Info.plist", map[string]any{
|
||||
"CFBundleIdentifier": "com.apple.FooService",
|
||||
"CFBundleExecutable": "FooService",
|
||||
"XPCService": map[string]any{
|
||||
"ServiceType": "Application",
|
||||
},
|
||||
}, plist.XMLFormat)
|
||||
|
||||
records, err := WalkVolume(root, "FileSystem")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(records) != 2 {
|
||||
t.Fatalf("expected launchd and XPC records under apfs-fuse root, got %d", len(records))
|
||||
}
|
||||
if findRecord(records, "/System/Library/LaunchDaemons/com.apple.rooted.plist") == nil {
|
||||
t.Fatalf("missing launchd daemon with normalized path: %#v", records)
|
||||
}
|
||||
if findRecord(records, "/Applications/Foo.app/XPCServices/FooService.xpc/Info.plist") == nil {
|
||||
t.Fatalf("missing XPC bundle with normalized path: %#v", records)
|
||||
}
|
||||
for _, record := range records {
|
||||
if strings.HasPrefix(record.PlistPath, "/root/") {
|
||||
t.Fatalf("plist_path kept apfs-fuse root prefix: %#v", record)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWalkVolumeAppXPCAndPlainApp(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
writePlist(t, root, "/Applications/HasService.app/Info.plist", map[string]any{
|
||||
|
||||
Reference in New Issue
Block a user