support downloading and unpacking GrapheneOS images
This commit is contained in:
parent
22256ea40b
commit
1d00936a4a
3 changed files with 39 additions and 9 deletions
|
@ -388,7 +388,11 @@ async function unpackFactoryImage(factoryImagePath: string, image: DeviceImage,
|
|||
// There's a TOCTOU race (file is accessed after check), but it affects all other generated files too.
|
||||
// Fixing it for this particular case is not worth the complexity increase
|
||||
} else {
|
||||
throw new Error(`SHA-256 mismatch for '${image.fileName}': expected ${image.sha256} got ${sha256}`)
|
||||
if (image.skipSha256Check) {
|
||||
console.warn(`skipping SHA-256 check for ${image.fileName}, SHA-256: ${sha256}`)
|
||||
} else {
|
||||
throw new Error(`SHA-256 mismatch for '${image.fileName}': expected ${image.sha256} got ${sha256}`)
|
||||
}
|
||||
}
|
||||
|
||||
let fd = await fs.open(factoryImagePath, 'r')
|
||||
|
@ -400,9 +404,15 @@ async function unpackFactoryImage(factoryImagePath: string, image: DeviceImage,
|
|||
let entry: yauzl.Entry = entryP
|
||||
let entryName = entry.filename
|
||||
|
||||
let isInnerZip =
|
||||
entryName.includes(`-${image.buildId.toLowerCase()}/image-${image.deviceConfig.device.name}`) &&
|
||||
entryName.endsWith(`-${image.buildId.toLowerCase()}.zip`)
|
||||
let isInnerZip = false
|
||||
|
||||
let deviceName = image.deviceConfig.device.name
|
||||
if (image.isGrapheneOS) {
|
||||
isInnerZip = entryName.includes(`/image-${deviceName}-`) && entryName.endsWith('.zip')
|
||||
} else {
|
||||
isInnerZip = entryName.includes(`-${image.buildId.toLowerCase()}/image-${deviceName}`) &&
|
||||
entryName.endsWith(`-${image.buildId.toLowerCase()}.zip`)
|
||||
}
|
||||
|
||||
if (!isInnerZip) {
|
||||
continue
|
||||
|
|
|
@ -5,6 +5,8 @@ import { DeviceConfig, getDeviceBuildId } from '../config/device'
|
|||
import { IMAGE_DOWNLOAD_DIR } from '../config/paths'
|
||||
import { BuildIndex, DEFAULT_BASE_DOWNLOAD_URL, ImageType } from './build-index'
|
||||
|
||||
const GRAPHENEOS_PSEUDO_BUILD_ID_PREFIX = 'gos-'
|
||||
|
||||
export class DeviceImage {
|
||||
constructor(
|
||||
readonly deviceConfig: DeviceConfig,
|
||||
|
@ -13,8 +15,9 @@ export class DeviceImage {
|
|||
readonly fileName: string,
|
||||
readonly sha256: string,
|
||||
readonly url: string,
|
||||
) {
|
||||
}
|
||||
readonly skipSha256Check: boolean,
|
||||
readonly isGrapheneOS: boolean,
|
||||
) {}
|
||||
|
||||
getPath() {
|
||||
return path.join(IMAGE_DOWNLOAD_DIR, this.fileName)
|
||||
|
@ -32,6 +35,15 @@ export class DeviceImage {
|
|||
let deviceBuildId = getDeviceBuildId(deviceConfig, buildId)
|
||||
let buildProps = index.get(deviceBuildId)
|
||||
if (buildProps === undefined) {
|
||||
if (buildId.startsWith(GRAPHENEOS_PSEUDO_BUILD_ID_PREFIX)) {
|
||||
let fileName = deviceConfig.device.name + '-factory-' +
|
||||
buildId.substring(GRAPHENEOS_PSEUDO_BUILD_ID_PREFIX.length) + '.zip'
|
||||
|
||||
let url = 'https://releases.grapheneos.org/' + fileName
|
||||
|
||||
return new DeviceImage(deviceConfig, type, buildId, fileName, 'no sha256', url, true, true)
|
||||
}
|
||||
|
||||
throw new Error(`no images for '${deviceBuildId}'`)
|
||||
}
|
||||
|
||||
|
@ -54,7 +66,7 @@ export class DeviceImage {
|
|||
fileName = ending
|
||||
url = DEFAULT_BASE_DOWNLOAD_URL + fileName
|
||||
}
|
||||
return new DeviceImage(deviceConfig, type, buildId, fileName, sha256, url)
|
||||
return new DeviceImage(deviceConfig, type, buildId, fileName, sha256, url, false, false)
|
||||
}
|
||||
|
||||
static async getMissing(arr: DeviceImage[]) {
|
||||
|
|
|
@ -70,13 +70,21 @@ async function downloadImage(image: DeviceImage, outDir: string) {
|
|||
|
||||
let sha256Digest: string = sha256.digest('hex')
|
||||
console.log('SHA-256: ' + sha256Digest)
|
||||
assert(sha256Digest === image.sha256, 'SHA256 mismatch, expected ' + image.sha256)
|
||||
if (image.skipSha256Check) {
|
||||
console.warn('skipping SHA-256 check for ' + completeOutFile)
|
||||
} else {
|
||||
assert(sha256Digest === image.sha256, 'SHA256 mismatch, expected ' + image.sha256)
|
||||
}
|
||||
|
||||
await fs.rename(tmpOutFile, completeOutFile)
|
||||
}
|
||||
|
||||
function logTermsAndConditionsNotice(images: DeviceImage[]) {
|
||||
if (images.filter(i => i.type === ImageType.Factory || i.type === ImageType.Ota).length == 0) {
|
||||
if (
|
||||
images.filter(i => {
|
||||
return !i.isGrapheneOS && (i.type === ImageType.Factory || i.type === ImageType.Ota)
|
||||
}).length == 0
|
||||
) {
|
||||
// vendor images show T&C notice themselves as part of unpacking
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue