-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: [CrashReportMover] support to export crash report
* [AFC] add func `WriteFile` * [AFC] should close `AfcFile`
- Loading branch information
1 parent
d73a058
commit f7e28cd
Showing
10 changed files
with
374 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package giDevice | ||
|
||
import ( | ||
"fmt" | ||
"github.com/electricbubble/gidevice/pkg/libimobiledevice" | ||
"howett.net/plist" | ||
"io" | ||
"os" | ||
"path" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
var _ CrashReportMover = (*crashReportMover)(nil) | ||
|
||
func newCrashReportMover(client *libimobiledevice.CrashReportMoverClient) *crashReportMover { | ||
return &crashReportMover{ | ||
client: client, | ||
} | ||
} | ||
|
||
type crashReportMover struct { | ||
client *libimobiledevice.CrashReportMoverClient | ||
afc Afc | ||
} | ||
|
||
func (c *crashReportMover) readPing() (err error) { | ||
var data []byte | ||
if data, err = c.client.InnerConn().Read(4); err != nil { | ||
return err | ||
} | ||
if string(data) != "ping" { | ||
return fmt.Errorf("crashReportMover ping: %v", data) | ||
} | ||
|
||
return | ||
} | ||
|
||
func (c *crashReportMover) Move(hostDir string, opts ...CrashReportMoverOption) (err error) { | ||
opt := defaultCrashReportMoverOption() | ||
for _, fn := range opts { | ||
fn(opt) | ||
} | ||
|
||
toExtract := make([]string, 0, 64) | ||
|
||
fn := func(cwd string, info *AfcFileInfo) { | ||
if info.IsDir() { | ||
return | ||
} | ||
if cwd == "." { | ||
cwd = "" | ||
} | ||
|
||
devFilename := path.Join(cwd, info.Name()) | ||
hostElem := strings.Split(devFilename, "/") | ||
hostFilename := filepath.Join(hostDir, filepath.Join(hostElem...)) | ||
hostFilename = strings.TrimSuffix(hostFilename, ".synced") | ||
|
||
if opt.extract && strings.HasSuffix(hostFilename, ".plist") { | ||
toExtract = append(toExtract, hostFilename) | ||
} | ||
|
||
var afcFile *AfcFile | ||
if afcFile, err = c.afc.Open(devFilename, AfcFileModeRdOnly); err != nil { | ||
debugLog(fmt.Sprintf("crashReportMover open %s: %s", devFilename, err)) | ||
return | ||
} | ||
defer func() { | ||
if err = afcFile.Close(); err != nil { | ||
debugLog(fmt.Sprintf("crashReportMover device file close: %s", err)) | ||
} | ||
}() | ||
|
||
if err = os.MkdirAll(filepath.Dir(hostFilename), 0755); err != nil { | ||
debugLog(fmt.Sprintf("crashReportMover mkdir %s: %s", filepath.Dir(hostFilename), err)) | ||
return | ||
} | ||
var hostFile *os.File | ||
if hostFile, err = os.Create(hostFilename); err != nil { | ||
debugLog(fmt.Sprintf("crashReportMover create %s: %s", hostFilename, err)) | ||
return | ||
} | ||
defer func() { | ||
if err = hostFile.Close(); err != nil { | ||
debugLog(fmt.Sprintf("crashReportMover host file close: %s", err)) | ||
} | ||
}() | ||
|
||
if _, err = io.Copy(hostFile, afcFile); err != nil { | ||
debugLog(fmt.Sprintf("crashReportMover copy %s", err)) | ||
return | ||
} | ||
|
||
opt.whenDone(devFilename) | ||
|
||
if opt.keep { | ||
return | ||
} | ||
|
||
if err = c.afc.Remove(devFilename); err != nil { | ||
debugLog(fmt.Sprintf("crashReportMover remove %s: %s", devFilename, err)) | ||
return | ||
} | ||
} | ||
if err = c.walkDir(".", fn); err != nil { | ||
return err | ||
} | ||
|
||
if !opt.extract { | ||
return nil | ||
} | ||
|
||
for _, name := range toExtract { | ||
data, err := os.ReadFile(name) | ||
if err != nil { | ||
debugLog(fmt.Sprintf("crashReportMover extract read %s: %s", name, err)) | ||
continue | ||
} | ||
m := make(map[string]interface{}) | ||
if _, err = plist.Unmarshal(data, &m); err != nil { | ||
debugLog(fmt.Sprintf("crashReportMover extract plist %s: %s", name, err)) | ||
continue | ||
} | ||
|
||
desc, ok := m["description"] | ||
if !ok { | ||
continue | ||
} | ||
hostExtCrash := strings.TrimSuffix(name, ".plist") + ".crash" | ||
if err = os.WriteFile(hostExtCrash, []byte(fmt.Sprintf("%v", desc)), 0755); err != nil { | ||
debugLog(fmt.Sprintf("crashReportMover extract save %s: %s", name, err)) | ||
continue | ||
} | ||
} | ||
|
||
return | ||
} | ||
|
||
func (c *crashReportMover) walkDir(dirname string, fn func(path string, info *AfcFileInfo)) (err error) { | ||
var names []string | ||
if names, err = c.afc.ReadDir(dirname); err != nil { | ||
return err | ||
} | ||
|
||
cwd := dirname | ||
|
||
for _, n := range names { | ||
if n == "." || n == ".." { | ||
continue | ||
} | ||
|
||
var info *AfcFileInfo | ||
if info, err = c.afc.Stat(path.Join(cwd, n)); err != nil { | ||
return err | ||
} | ||
if info.IsDir() { | ||
if err = c.walkDir(path.Join(cwd, info.name), fn); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
fn(cwd, info) | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package giDevice | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"testing" | ||
) | ||
|
||
var crashReportMoverSrv CrashReportMover | ||
|
||
func setupCrashReportMoverSrv(t *testing.T) { | ||
setupLockdownSrv(t) | ||
|
||
var err error | ||
if lockdownSrv, err = dev.lockdownService(); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if crashReportMoverSrv, err = lockdownSrv.CrashReportMoverService(); err != nil { | ||
t.Fatal(err) | ||
} | ||
} | ||
|
||
func Test_crashReportMover_Move(t *testing.T) { | ||
setupCrashReportMoverSrv(t) | ||
|
||
SetDebug(true) | ||
userHomeDir, _ := os.UserHomeDir() | ||
// err := crashReportMoverSrv.Move(userHomeDir + "/Documents/temp/2021-04/out_gidevice") | ||
// err := crashReportMoverSrv.Move(userHomeDir+"/Documents/temp/2021-04/out_gidevice", | ||
err := crashReportMoverSrv.Move(userHomeDir+"/Documents/temp/2021-04/out_gidevice_extract", | ||
WithKeepCrashReport(true), | ||
WithExtractRawCrashReport(true), | ||
WithWhenMoveIsDone(func(filename string) { | ||
fmt.Println("Copy:", filename) | ||
}), | ||
) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.