diff --git a/README.md b/README.md index d119c0f..582afa8 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,28 @@ Android OTA payload extractor written in Go. ## Usage ``` -./android-ota-payload-extractor +./android-ota-payload-extractor [(optional) file to extract 1] [(optional) file to extract 2] ... +``` + +Example (extract boot and vendor images from raven-ota.zip): + +``` +./android-ota-payload-extractor.exe raven-ota.zip boot vendor ``` It can parse `payload.bin` directly, or automatically extract from OTA zip files. +When files to extract are not specified, it will extract all files in the payload. + ![Demo GIF](demo.gif) ## About Inspired by https://github.com/cyxx/extract_android_ota_payload. -Extracting images from Android OTA packages is extremely useful for various purposes. For example, patching the boot image to install Magisk without TWRP. Using the python script above, however, is often a pain in the ass because of Python and its dependencies, especially for inexperienced Windows users. +Extracting images from Android OTA packages is very useful for various purposes. For example, patching the boot +image to install Magisk without TWRP. However, using the above Python script is often a pain in the ass because of +Python and its dependencies, especially for inexperienced Windows users. -This project aims to provide everyone a faster & cross-platform Android OTA payload extractor that's a lot easier to use - just drag and drop the ROM file onto the program. \ No newline at end of file +This project aims to provide everyone with a faster & cross-platform Android OTA payload extractor that's much easier to +use - just drag and drop the ROM file onto the program. \ No newline at end of file diff --git a/README.zh.md b/README.zh.md index a895f04..69d2a2f 100644 --- a/README.zh.md +++ b/README.zh.md @@ -9,15 +9,21 @@ Go 编写的 Android OTA 镜像解压工具 ### 命令行 ``` -./android-ota-payload-extractor +./android-ota-payload-extractor [(optional) file to extract 1] [(optional) file to extract 2] ... ``` -### 拖拽 +样例(从 raven-ota.zip 解压 boot 和 vendor): -![Demo GIF](demo.gif) +``` +./android-ota-payload-extractor.exe raven-ota.zip boot vendor +``` 支持单独解压出来的 payload.bin,也支持直接用整个 ROM zip 包。 +如果没有指定要解压的文件,默认会解压 payload 中包含的所有文件。 + +![Demo GIF](demo.gif) + ## About 灵感基于: https://github.com/cyxx/extract_android_ota_payload diff --git a/main.go b/main.go index deea077..9881bb1 100644 --- a/main.go +++ b/main.go @@ -6,11 +6,12 @@ import ( "compress/bzip2" "encoding/binary" "fmt" - "github.com/golang/protobuf/proto" - "github.com/xi2/xz" "io" "log" "os" + + "github.com/golang/protobuf/proto" + "github.com/xi2/xz" ) const ( @@ -24,10 +25,11 @@ const ( func main() { if len(os.Args) < 2 { - fmt.Printf("Usage: %s \n", os.Args[0]) + fmt.Printf("Usage: %s [(optional) file to extract...]\n", os.Args[0]) os.Exit(1) } filename := os.Args[1] + extractFiles := os.Args[2:] f, err := os.Open(filename) if err != nil { log.Fatalf("Failed to open file: %s", err) @@ -60,7 +62,7 @@ func main() { _ = zr.Close() _, _ = f.Seek(0, 0) } - parsePayload(f) + parsePayload(f, extractFiles) } func isZip(f *os.File) bool { @@ -79,7 +81,7 @@ func findPayload(zr *zip.ReadCloser) (io.ReadCloser, error) { return nil, nil } -func parsePayload(r io.ReadSeeker) { +func parsePayload(r io.ReadSeeker, extractFiles []string) { log.Println("Parsing payload...") // magic magic := make([]byte, len(payloadMagic)) @@ -122,14 +124,14 @@ func parsePayload(r io.ReadSeeker) { log.Printf("Block size: %d, Partition count: %d\n", *manifest.BlockSize, len(manifest.Partitions)) // extract partitions - extractPartitions(&manifest, r, 24+manifestLen+uint64(metadataSigLen)) + extractPartitions(&manifest, r, 24+manifestLen+uint64(metadataSigLen), extractFiles) // done log.Println("Done!") } -func extractPartitions(manifest *DeltaArchiveManifest, r io.ReadSeeker, baseOffset uint64) { +func extractPartitions(manifest *DeltaArchiveManifest, r io.ReadSeeker, baseOffset uint64, extractFiles []string) { for _, p := range manifest.Partitions { - if p.PartitionName == nil { + if p.PartitionName == nil || (len(extractFiles) > 0 && !contains(extractFiles, *p.PartitionName)) { continue } log.Printf("Extracting %s (%d ops) ...", *p.PartitionName, len(p.Operations)) @@ -211,3 +213,12 @@ func extractPartition(p *PartitionUpdate, outFilename string, r io.ReadSeeker, b } } } + +func contains(ss []string, s string) bool { + for _, v := range ss { + if v == s { + return true + } + } + return false +}