Skip to content

Commit 669874c

Browse files
committed
feat: extract only specified partitions (closes #3)
1 parent 73721ae commit 669874c

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

README.md

+14-3
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,28 @@ Android OTA payload extractor written in Go.
99
## Usage
1010

1111
```
12-
./android-ota-payload-extractor <OTA.zip or payload.bin>
12+
./android-ota-payload-extractor <OTA.zip or payload.bin> [(optional) file to extract 1] [(optional) file to extract 2] ...
13+
```
14+
15+
Example (extract boot and vendor images from raven-ota.zip):
16+
17+
```
18+
./android-ota-payload-extractor.exe raven-ota.zip boot vendor
1319
```
1420

1521
It can parse `payload.bin` directly, or automatically extract from OTA zip files.
1622

23+
When files to extract are not specified, it will extract all files in the payload.
24+
1725
![Demo GIF](demo.gif)
1826

1927
## About
2028

2129
Inspired by https://github.com/cyxx/extract_android_ota_payload.
2230

23-
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.
31+
Extracting images from Android OTA packages is very useful for various purposes. For example, patching the boot
32+
image to install Magisk without TWRP. However, using the above Python script is often a pain in the ass because of
33+
Python and its dependencies, especially for inexperienced Windows users.
2434

25-
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.
35+
This project aims to provide everyone with a faster & cross-platform Android OTA payload extractor that's much easier to
36+
use - just drag and drop the ROM file onto the program.

README.zh.md

+9-3
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,21 @@ Go 编写的 Android OTA 镜像解压工具
99
### 命令行
1010

1111
```
12-
./android-ota-payload-extractor <OTA.zip or payload.bin>
12+
./android-ota-payload-extractor <OTA.zip or payload.bin> [(optional) file to extract 1] [(optional) file to extract 2] ...
1313
```
1414

15-
### 拖拽
15+
样例(从 raven-ota.zip 解压 boot 和 vendor):
1616

17-
![Demo GIF](demo.gif)
17+
```
18+
./android-ota-payload-extractor.exe raven-ota.zip boot vendor
19+
```
1820

1921
支持单独解压出来的 payload.bin,也支持直接用整个 ROM zip 包。
2022

23+
如果没有指定要解压的文件,默认会解压 payload 中包含的所有文件。
24+
25+
![Demo GIF](demo.gif)
26+
2127
## About
2228

2329
灵感基于: https://github.com/cyxx/extract_android_ota_payload

main.go

+19-8
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import (
66
"compress/bzip2"
77
"encoding/binary"
88
"fmt"
9-
"github.com/golang/protobuf/proto"
10-
"github.com/xi2/xz"
119
"io"
1210
"log"
1311
"os"
12+
13+
"github.com/golang/protobuf/proto"
14+
"github.com/xi2/xz"
1415
)
1516

1617
const (
@@ -24,10 +25,11 @@ const (
2425

2526
func main() {
2627
if len(os.Args) < 2 {
27-
fmt.Printf("Usage: %s <input>\n", os.Args[0])
28+
fmt.Printf("Usage: %s <input> [(optional) file to extract...]\n", os.Args[0])
2829
os.Exit(1)
2930
}
3031
filename := os.Args[1]
32+
extractFiles := os.Args[2:]
3133
f, err := os.Open(filename)
3234
if err != nil {
3335
log.Fatalf("Failed to open file: %s", err)
@@ -60,7 +62,7 @@ func main() {
6062
_ = zr.Close()
6163
_, _ = f.Seek(0, 0)
6264
}
63-
parsePayload(f)
65+
parsePayload(f, extractFiles)
6466
}
6567

6668
func isZip(f *os.File) bool {
@@ -79,7 +81,7 @@ func findPayload(zr *zip.ReadCloser) (io.ReadCloser, error) {
7981
return nil, nil
8082
}
8183

82-
func parsePayload(r io.ReadSeeker) {
84+
func parsePayload(r io.ReadSeeker, extractFiles []string) {
8385
log.Println("Parsing payload...")
8486
// magic
8587
magic := make([]byte, len(payloadMagic))
@@ -122,14 +124,14 @@ func parsePayload(r io.ReadSeeker) {
122124
log.Printf("Block size: %d, Partition count: %d\n",
123125
*manifest.BlockSize, len(manifest.Partitions))
124126
// extract partitions
125-
extractPartitions(&manifest, r, 24+manifestLen+uint64(metadataSigLen))
127+
extractPartitions(&manifest, r, 24+manifestLen+uint64(metadataSigLen), extractFiles)
126128
// done
127129
log.Println("Done!")
128130
}
129131

130-
func extractPartitions(manifest *DeltaArchiveManifest, r io.ReadSeeker, baseOffset uint64) {
132+
func extractPartitions(manifest *DeltaArchiveManifest, r io.ReadSeeker, baseOffset uint64, extractFiles []string) {
131133
for _, p := range manifest.Partitions {
132-
if p.PartitionName == nil {
134+
if p.PartitionName == nil || (len(extractFiles) > 0 && !contains(extractFiles, *p.PartitionName)) {
133135
continue
134136
}
135137
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
211213
}
212214
}
213215
}
216+
217+
func contains(ss []string, s string) bool {
218+
for _, v := range ss {
219+
if v == s {
220+
return true
221+
}
222+
}
223+
return false
224+
}

0 commit comments

Comments
 (0)