Skip to content

Commit

Permalink
feat: extract only specified partitions (closes tobyxdd#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
tobyxdd committed Mar 9, 2023
1 parent 73721ae commit 669874c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 14 deletions.
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,28 @@ Android OTA payload extractor written in Go.
## Usage

```
./android-ota-payload-extractor <OTA.zip or payload.bin>
./android-ota-payload-extractor <OTA.zip or payload.bin> [(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.
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.
12 changes: 9 additions & 3 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@ Go 编写的 Android OTA 镜像解压工具
### 命令行

```
./android-ota-payload-extractor <OTA.zip or payload.bin>
./android-ota-payload-extractor <OTA.zip or payload.bin> [(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
Expand Down
27 changes: 19 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -24,10 +25,11 @@ const (

func main() {
if len(os.Args) < 2 {
fmt.Printf("Usage: %s <input>\n", os.Args[0])
fmt.Printf("Usage: %s <input> [(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)
Expand Down Expand Up @@ -60,7 +62,7 @@ func main() {
_ = zr.Close()
_, _ = f.Seek(0, 0)
}
parsePayload(f)
parsePayload(f, extractFiles)
}

func isZip(f *os.File) bool {
Expand All @@ -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))
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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
}

0 comments on commit 669874c

Please sign in to comment.