mirror of
https://github.com/blacktop/ipsw.git
synced 2026-06-07 12:27:36 +00:00
feat: add --feat flag to ipsw diff to diff Feature Flags
This commit is contained in:
@@ -44,6 +44,7 @@ func init() {
|
||||
diffCmd.Flags().StringArrayP("kdk", "k", []string{}, "Path to KDKs to diff")
|
||||
diffCmd.Flags().Bool("launchd", false, "Diff launchd configs")
|
||||
diffCmd.Flags().Bool("fw", false, "Diff other firmwares")
|
||||
diffCmd.Flags().Bool("feat", false, "Diff feature flags")
|
||||
diffCmd.Flags().StringSliceP("filter", "f", []string{}, "Filter MachO sections to diff (e.g. __TEXT.__text)")
|
||||
diffCmd.Flags().StringP("output", "o", "", "Folder to save diff output")
|
||||
diffCmd.MarkFlagDirname("output")
|
||||
@@ -56,6 +57,7 @@ func init() {
|
||||
viper.BindPFlag("diff.kdk", diffCmd.Flags().Lookup("kdk"))
|
||||
viper.BindPFlag("diff.launchd", diffCmd.Flags().Lookup("launchd"))
|
||||
viper.BindPFlag("diff.fw", diffCmd.Flags().Lookup("fw"))
|
||||
viper.BindPFlag("diff.feat", diffCmd.Flags().Lookup("feat"))
|
||||
viper.BindPFlag("diff.filter", diffCmd.Flags().Lookup("filter"))
|
||||
viper.BindPFlag("diff.output", diffCmd.Flags().Lookup("output"))
|
||||
}
|
||||
@@ -115,6 +117,7 @@ var diffCmd = &cobra.Command{
|
||||
KDKs: viper.GetStringSlice("diff.kdk"),
|
||||
LaunchD: viper.GetBool("diff.launchd"),
|
||||
Firmware: viper.GetBool("diff.fw"),
|
||||
Features: viper.GetBool("diff.feat"),
|
||||
Filter: viper.GetStringSlice("diff.filter"),
|
||||
Output: viper.GetString("diff.output"),
|
||||
})
|
||||
|
||||
@@ -432,15 +432,15 @@ func PatchMachoMod(m *macho.File, machoPath, loadCommand string, args []string)
|
||||
}
|
||||
platform, err := types.GetPlatformByName(args[2])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse platform name %s: %v", args[2], err)
|
||||
return fmt.Errorf("failed to parse platform name '%s': %v", args[2], err)
|
||||
}
|
||||
var minos types.Version
|
||||
if err := minos.Set(args[3]); err != nil {
|
||||
return fmt.Errorf("failed to parse min OS versionc: %v", args[3], err)
|
||||
return fmt.Errorf("failed to parse min OS version '%s': %v", args[3], err)
|
||||
}
|
||||
var sdk types.Version
|
||||
if err := sdk.Set(args[4]); err != nil {
|
||||
return fmt.Errorf("failed to parse SDK version: %v", args[4], err)
|
||||
return fmt.Errorf("failed to parse SDK version '%s': %v", args[4], err)
|
||||
}
|
||||
var tools []types.BuildVersionTool
|
||||
if len(args) > 5 {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -21,6 +22,7 @@ import (
|
||||
"github.com/blacktop/ipsw/internal/commands/extract"
|
||||
kcmd "github.com/blacktop/ipsw/internal/commands/kernel"
|
||||
mcmd "github.com/blacktop/ipsw/internal/commands/macho"
|
||||
"github.com/blacktop/ipsw/internal/search"
|
||||
"github.com/blacktop/ipsw/internal/utils"
|
||||
"github.com/blacktop/ipsw/pkg/aea"
|
||||
"github.com/blacktop/ipsw/pkg/dyld"
|
||||
@@ -40,6 +42,12 @@ type mount struct {
|
||||
IsMounted bool
|
||||
}
|
||||
|
||||
type PlistDiff struct {
|
||||
New []string `json:"new,omitempty"`
|
||||
Removed []string `json:"removed,omitempty"`
|
||||
Updated map[string]string `json:"changed,omitempty"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Title string
|
||||
IpswOld string
|
||||
@@ -47,6 +55,7 @@ type Config struct {
|
||||
KDKs []string
|
||||
LaunchD bool
|
||||
Firmware bool
|
||||
Features bool
|
||||
Filter []string
|
||||
Output string
|
||||
}
|
||||
@@ -84,6 +93,7 @@ type Diff struct {
|
||||
Machos *mcmd.MachoDiff `json:"machos,omitempty"`
|
||||
Firmwares *mcmd.MachoDiff `json:"firmwares,omitempty"`
|
||||
Launchd string `json:"launchd,omitempty"`
|
||||
Features *PlistDiff `json:"features,omitempty"`
|
||||
|
||||
tmpDir string `json:"-"`
|
||||
conf *Config
|
||||
@@ -254,6 +264,13 @@ func (d *Diff) Diff() (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if d.conf.Features {
|
||||
log.Info("Diffing Feature Flags")
|
||||
if err := d.parseFeatureFlags(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Diffing ENTITLEMENTS")
|
||||
d.Ents, err = d.parseEntitlements()
|
||||
if err != nil {
|
||||
@@ -555,3 +572,79 @@ func (d *Diff) parseFirmwares() (err error) {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Diff) parseFeatureFlags() (err error) {
|
||||
d.Features = &PlistDiff{
|
||||
Updated: make(map[string]string),
|
||||
}
|
||||
conf := &mcmd.DiffConfig{
|
||||
Markdown: true,
|
||||
Color: false,
|
||||
DiffTool: "git",
|
||||
}
|
||||
|
||||
oldPlists := make(map[string]string)
|
||||
if err := search.ForEachPlistInIPSW(d.Old.IPSWPath, "/System/Library/FeatureFlags", func(path string, content string) error {
|
||||
oldPlists[path] = content
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var prevFiles []string
|
||||
for f := range oldPlists {
|
||||
prevFiles = append(prevFiles, f)
|
||||
}
|
||||
slices.Sort(prevFiles)
|
||||
|
||||
newPlists := make(map[string]string)
|
||||
if err := search.ForEachPlistInIPSW(d.New.IPSWPath, "/System/Library/FeatureFlags", func(path string, content string) error {
|
||||
newPlists[path] = content
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var nextFiles []string
|
||||
for f := range newPlists {
|
||||
nextFiles = append(nextFiles, f)
|
||||
}
|
||||
slices.Sort(nextFiles)
|
||||
|
||||
/* DIFF IPSW */
|
||||
d.Features.New = utils.Difference(nextFiles, prevFiles)
|
||||
d.Features.Removed = utils.Difference(prevFiles, nextFiles)
|
||||
// gc
|
||||
prevFiles = []string{}
|
||||
|
||||
for _, f2 := range nextFiles {
|
||||
dat2 := newPlists[f2]
|
||||
if dat1, ok := oldPlists[f2]; ok {
|
||||
if strings.EqualFold(dat2, dat1) {
|
||||
continue
|
||||
}
|
||||
var out string
|
||||
if conf.Markdown {
|
||||
out, err = utils.GitDiff(dat1+"\n", dat2+"\n", &utils.GitDiffConfig{Color: conf.Color, Tool: conf.DiffTool})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out, err = utils.GitDiff(dat1+"\n", dat2+"\n", &utils.GitDiffConfig{Color: conf.Color, Tool: conf.DiffTool})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(out) == 0 { // no diff
|
||||
continue
|
||||
}
|
||||
if conf.Markdown {
|
||||
d.Features.Updated[f2] = "```diff\n" + out + "\n```\n"
|
||||
} else {
|
||||
d.Features.Updated[f2] = out
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+89
-16
@@ -35,22 +35,24 @@ func (d *Diff) Markdown() error {
|
||||
)
|
||||
|
||||
// SECTION: Kernel
|
||||
out.WriteString(
|
||||
fmt.Sprintf(
|
||||
"## Kernel\n\n"+
|
||||
"### Version\n\n"+
|
||||
"| iOS | Version | Build | Date |\n"+
|
||||
"| :-- | :------ | :---- | :--- |\n"+
|
||||
"| %s *(%s)* | %s | %s | %s |\n"+
|
||||
"| %s *(%s)* | %s | %s | %s |\n\n",
|
||||
d.Old.Version, d.Old.Build,
|
||||
d.Old.Kernel.Version.KernelVersion.Darwin, d.Old.Kernel.Version.KernelVersion.XNU,
|
||||
d.Old.Kernel.Version.KernelVersion.Date.Format("Mon, 02Jan2006 15:04:05 MST"),
|
||||
d.New.Version, d.New.Build,
|
||||
d.New.Kernel.Version.KernelVersion.Darwin, d.New.Kernel.Version.KernelVersion.XNU,
|
||||
d.New.Kernel.Version.KernelVersion.Date.Format("Mon, 02Jan2006 15:04:05 MST"),
|
||||
),
|
||||
)
|
||||
if d.Old.Kernel.Version != nil && d.New.Kernel.Version != nil {
|
||||
out.WriteString(
|
||||
fmt.Sprintf(
|
||||
"## Kernel\n\n"+
|
||||
"### Version\n\n"+
|
||||
"| iOS | Version | Build | Date |\n"+
|
||||
"| :-- | :------ | :---- | :--- |\n"+
|
||||
"| %s *(%s)* | %s | %s | %s |\n"+
|
||||
"| %s *(%s)* | %s | %s | %s |\n\n",
|
||||
d.Old.Version, d.Old.Build,
|
||||
d.Old.Kernel.Version.KernelVersion.Darwin, d.Old.Kernel.Version.KernelVersion.XNU,
|
||||
d.Old.Kernel.Version.KernelVersion.Date.Format("Mon, 02Jan2006 15:04:05 MST"),
|
||||
d.New.Version, d.New.Build,
|
||||
d.New.Kernel.Version.KernelVersion.Darwin, d.New.Kernel.Version.KernelVersion.XNU,
|
||||
d.New.Kernel.Version.KernelVersion.Date.Format("Mon, 02Jan2006 15:04:05 MST"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// SUB-SECTION: Kexts
|
||||
if d.Kexts != nil && (len(d.Kexts.New) > 0 || len(d.Kexts.Removed) > 0 || len(d.Kexts.Updated) > 0) {
|
||||
@@ -351,6 +353,77 @@ func (d *Diff) Markdown() error {
|
||||
}
|
||||
}
|
||||
|
||||
// SUB-SECTION: Feature Flags
|
||||
if d.Features != nil && (len(d.Features.New) > 0 || len(d.Features.Removed) > 0 || len(d.Features.Updated) > 0) {
|
||||
out.WriteString("### Feature Flags\n\n")
|
||||
if len(d.Features.New) > 0 {
|
||||
out.WriteString(fmt.Sprintf("#### 🆕 NEW (%d)\n\n", len(d.Features.New)))
|
||||
if len(d.Features.New) > 30 {
|
||||
out.WriteString("<details>\n" +
|
||||
" <summary><i>View NEW</i></summary>\n\n")
|
||||
}
|
||||
for _, k := range d.Features.New {
|
||||
out.WriteString(fmt.Sprintf("- `%s`\n", k))
|
||||
}
|
||||
if len(d.Features.New) > 30 {
|
||||
out.WriteString("\n</details>\n")
|
||||
}
|
||||
out.WriteString("\n")
|
||||
}
|
||||
if len(d.Features.Removed) > 0 {
|
||||
out.WriteString(fmt.Sprintf("#### ❌ Removed (%d)\n\n", len(d.Features.Removed)))
|
||||
if len(d.Features.Removed) > 30 {
|
||||
out.WriteString("<details>\n" +
|
||||
" <summary><i>View Removed</i></summary>\n\n")
|
||||
}
|
||||
for _, k := range d.Features.Removed {
|
||||
out.WriteString(fmt.Sprintf("- `%s`\n", k))
|
||||
}
|
||||
if len(d.Features.Removed) > 30 {
|
||||
out.WriteString("\n</details>\n")
|
||||
}
|
||||
out.WriteString("\n")
|
||||
}
|
||||
if len(d.Features.Updated) > 0 {
|
||||
out.WriteString(fmt.Sprintf("#### ⬆️ Updated (%d)\n\n", len(d.Features.Updated)))
|
||||
out.WriteString("<details>\n" +
|
||||
" <summary><i>View Updated</i></summary>\n\n")
|
||||
if len(d.Features.Updated) < 20 {
|
||||
for k, v := range d.Features.Updated {
|
||||
out.WriteString(fmt.Sprintf("#### %s\n\n", filepath.Base(k)))
|
||||
out.WriteString(fmt.Sprintf("> `%s`\n\n", k))
|
||||
out.WriteString(fmt.Sprintf("%s\n", v))
|
||||
}
|
||||
} else {
|
||||
if err := os.MkdirAll(filepath.Join(d.conf.Output, "Features"), 0o750); err != nil {
|
||||
return err
|
||||
}
|
||||
keys := make([]string, 0, len(d.Features.Updated))
|
||||
for k := range d.Features.Updated {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
fname := filepath.Join(d.conf.Output, "Features", strings.ReplaceAll(filepath.Base(k), " ", "_")+".md")
|
||||
if _, err := os.Stat(fname); os.IsExist(err) {
|
||||
fname = filepath.Join(d.conf.Output, "Features", fmt.Sprintf("%s.%d.md", strings.ReplaceAll(filepath.Base(k), " ", "_"), rand.Intn(20)))
|
||||
}
|
||||
log.Debugf("Creating diff dylib Markdown file: %s", fname)
|
||||
f, err := os.Create(fname)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create diff file: %w", err)
|
||||
}
|
||||
fmt.Fprintf(f, "## %s\n\n", filepath.Base(k))
|
||||
fmt.Fprintf(f, "> `%s`\n\n", k)
|
||||
fmt.Fprintf(f, d.Features.Updated[k])
|
||||
f.Close()
|
||||
out.WriteString(fmt.Sprintf("- [%s](%s)\n", k, filepath.Join("FEATURES", strings.ReplaceAll(filepath.Base(k), " ", "_")+".md")))
|
||||
}
|
||||
}
|
||||
out.WriteString("\n</details>\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
out.WriteString("## EOF\n")
|
||||
|
||||
// Write TOC.md
|
||||
|
||||
+130
-29
@@ -20,7 +20,8 @@ import (
|
||||
"github.com/blacktop/ipsw/pkg/info"
|
||||
)
|
||||
|
||||
func scanDmg(ipswPath, dmgPath, dmgType string, handler func(string, *macho.File) error) error {
|
||||
// TODO: make this an array of handlers to perform multiple actions on each file
|
||||
func scanDmg(ipswPath, dmgPath, dmgType string, handler func(string, string) error) error {
|
||||
// check if filesystem DMG already exists (due to previous mount command)
|
||||
if _, err := os.Stat(dmgPath); os.IsNotExist(err) {
|
||||
dmgs, err := utils.Unzip(ipswPath, "", func(f *zip.File) bool {
|
||||
@@ -62,13 +63,40 @@ func scanDmg(ipswPath, dmgPath, dmgType string, handler func(string, *macho.File
|
||||
}
|
||||
|
||||
var files []string
|
||||
// Use a map to keep track of visited directories to avoid infinite loops
|
||||
visited := make(map[string]bool)
|
||||
if err := filepath.Walk(mountPoint, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
log.Errorf("failed to walk mount %s: %v", path, err)
|
||||
return nil
|
||||
}
|
||||
if !info.IsDir() {
|
||||
files = append(files, path)
|
||||
if info.Mode()&os.ModeSymlink != 0 { // follow symlinks
|
||||
// Resolve the symlink
|
||||
if linkPath, err := filepath.EvalSymlinks(path); err == nil {
|
||||
// Get the info of the target file/directory
|
||||
info, err = os.Stat(linkPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// If it's a directory and not visited, follow it
|
||||
if info.IsDir() && !visited[linkPath] {
|
||||
visited[linkPath] = true
|
||||
return filepath.Walk(linkPath, func(subPath string, subInfo os.FileInfo, subErr error) error {
|
||||
if subErr != nil {
|
||||
return subErr
|
||||
}
|
||||
files = append(files, subPath)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !info.IsDir() {
|
||||
if !visited[path] {
|
||||
visited[path] = true
|
||||
files = append(files, path)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
@@ -77,28 +105,7 @@ func scanDmg(ipswPath, dmgPath, dmgType string, handler func(string, *macho.File
|
||||
|
||||
for _, file := range files {
|
||||
if err := func() error {
|
||||
if ok, _ := magic.IsMachO(file); ok {
|
||||
var m *macho.File
|
||||
// UNIVERSAL MACHO
|
||||
if fat, err := macho.OpenFat(file); err == nil {
|
||||
defer fat.Close()
|
||||
m = fat.Arches[len(fat.Arches)-1].File
|
||||
} else { // SINGLE MACHO
|
||||
if errors.Is(err, macho.ErrNotFat) {
|
||||
m, err = macho.Open(file)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer m.Close()
|
||||
} else { // NOT a macho file
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err := handler(strings.TrimPrefix(file, mountPoint), m); err != nil {
|
||||
return fmt.Errorf("failed to handle macho %s: %w", file, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return handler(mountPoint, file)
|
||||
}(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -109,6 +116,31 @@ func scanDmg(ipswPath, dmgPath, dmgType string, handler func(string, *macho.File
|
||||
|
||||
// ForEachMachoInIPSW walks the IPSW and calls the handler for each macho file found
|
||||
func ForEachMachoInIPSW(ipswPath string, handler func(string, *macho.File) error) error {
|
||||
scanMacho := func(mountPoint, machoPath string) error {
|
||||
if ok, _ := magic.IsMachO(machoPath); ok {
|
||||
var m *macho.File
|
||||
// UNIVERSAL MACHO
|
||||
if fat, err := macho.OpenFat(machoPath); err == nil {
|
||||
defer fat.Close()
|
||||
m = fat.Arches[len(fat.Arches)-1].File
|
||||
} else { // SINGLE MACHO
|
||||
if errors.Is(err, macho.ErrNotFat) {
|
||||
m, err = macho.Open(machoPath)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer m.Close()
|
||||
} else { // NOT a macho file
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err := handler(strings.TrimPrefix(machoPath, mountPoint), m); err != nil {
|
||||
return fmt.Errorf("failed to handle macho %s: %w", machoPath, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
i, err := info.Parse(ipswPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse IPSW: %v", err)
|
||||
@@ -116,25 +148,25 @@ func ForEachMachoInIPSW(ipswPath string, handler func(string, *macho.File) error
|
||||
|
||||
if fsOS, err := i.GetFileSystemOsDmg(); err == nil {
|
||||
log.Info("Scanning filesystem")
|
||||
if err := scanDmg(ipswPath, fsOS, "filesystem", handler); err != nil {
|
||||
if err := scanDmg(ipswPath, fsOS, "filesystem", scanMacho); err != nil {
|
||||
return fmt.Errorf("failed to scan files in filesystem %s: %w", fsOS, err)
|
||||
}
|
||||
}
|
||||
if systemOS, err := i.GetSystemOsDmg(); err == nil {
|
||||
log.Info("Scanning SystemOS")
|
||||
if err := scanDmg(ipswPath, systemOS, "SystemOS", handler); err != nil {
|
||||
if err := scanDmg(ipswPath, systemOS, "SystemOS", scanMacho); err != nil {
|
||||
return fmt.Errorf("failed to scan files in SystemOS %s: %w", systemOS, err)
|
||||
}
|
||||
}
|
||||
if appOS, err := i.GetAppOsDmg(); err == nil {
|
||||
log.Info("Scanning AppOS")
|
||||
if err := scanDmg(ipswPath, appOS, "AppOS", handler); err != nil {
|
||||
if err := scanDmg(ipswPath, appOS, "AppOS", scanMacho); err != nil {
|
||||
return fmt.Errorf("failed to scan files in AppOS %s: %w", appOS, err)
|
||||
}
|
||||
}
|
||||
if excOS, err := i.GetExclaveOSDmg(); err == nil {
|
||||
log.Info("Scanning ExclaveOS")
|
||||
if err := scanDmg(ipswPath, excOS, "ExclaveOS", handler); err != nil {
|
||||
if err := scanDmg(ipswPath, excOS, "ExclaveOS", scanMacho); err != nil {
|
||||
return fmt.Errorf("failed to scan files in ExclaveOS %s: %w", excOS, err)
|
||||
}
|
||||
}
|
||||
@@ -186,3 +218,72 @@ func ForEachIm4pInIPSW(ipswPath string, handler func(string, *macho.File) error)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ForEachPlistInIPSW(ipswPath string, directory string, handler func(string, string) error) error {
|
||||
i, err := info.Parse(ipswPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse IPSW: %v", err)
|
||||
}
|
||||
|
||||
scanPlist := func(mountPoint, plistPath string) error {
|
||||
// filter to only scan a specific directory (if provided)
|
||||
if directory != "" && !strings.Contains(plistPath, directory) {
|
||||
return nil
|
||||
}
|
||||
if strings.HasSuffix(plistPath, ".plist") {
|
||||
// settings := make(map[string]interface{})
|
||||
data, err := os.ReadFile(plistPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read plist %s: %v", plistPath, err)
|
||||
}
|
||||
// TODO: add support for binary plists
|
||||
// pdata, err := plist.MarshalIndent(data, plist.XMLFormat, " ")
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("failed to marshal plist %s: %v", plistPath, err)
|
||||
// }
|
||||
// if err := plist.NewDecoder(bytes.NewReader(data)).Decode(&settings); err != nil {
|
||||
// return fmt.Errorf("failed to decode plist %s: %v", plistPath, err)
|
||||
// }
|
||||
// jdata, err := json.MarshalIndent(settings, "", " ")
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("failed to marshal plist %s: %v", plistPath, err)
|
||||
// }
|
||||
plistPath = strings.TrimPrefix(plistPath, mountPoint)
|
||||
plistPath, err = filepath.Rel(directory, plistPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get relative path for %s: %v", plistPath, err)
|
||||
}
|
||||
if err := handler(strings.TrimPrefix(plistPath, mountPoint), string(data)); err != nil {
|
||||
return fmt.Errorf("failed to handle plist %s: %v", plistPath, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if fsOS, err := i.GetFileSystemOsDmg(); err == nil {
|
||||
log.Info("Scanning filesystem")
|
||||
if err := scanDmg(ipswPath, fsOS, "filesystem", scanPlist); err != nil {
|
||||
return fmt.Errorf("failed to scan files in filesystem %s: %w", fsOS, err)
|
||||
}
|
||||
}
|
||||
if systemOS, err := i.GetSystemOsDmg(); err == nil {
|
||||
log.Info("Scanning SystemOS")
|
||||
if err := scanDmg(ipswPath, systemOS, "SystemOS", scanPlist); err != nil {
|
||||
return fmt.Errorf("failed to scan files in SystemOS %s: %w", systemOS, err)
|
||||
}
|
||||
}
|
||||
if appOS, err := i.GetAppOsDmg(); err == nil {
|
||||
log.Info("Scanning AppOS")
|
||||
if err := scanDmg(ipswPath, appOS, "AppOS", scanPlist); err != nil {
|
||||
return fmt.Errorf("failed to scan files in AppOS %s: %w", appOS, err)
|
||||
}
|
||||
}
|
||||
if excOS, err := i.GetExclaveOSDmg(); err == nil {
|
||||
log.Info("Scanning ExclaveOS")
|
||||
if err := scanDmg(ipswPath, excOS, "ExclaveOS", scanPlist); err != nil {
|
||||
return fmt.Errorf("failed to scan files in ExclaveOS %s: %w", excOS, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user