ObbFile.cpp revision 02ca31fbae9f35dd30f79de6927fae11b549391a
17cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* 27cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * Copyright (C) 2010 The Android Open Source Project 37cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 47cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 57cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * you may not use this file except in compliance with the License. 67cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * You may obtain a copy of the License at 77cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 87cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * http://www.apache.org/licenses/LICENSE-2.0 97cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * Unless required by applicable law or agreed to in writing, software 117cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * distributed under the License is distributed on an "AS IS" BASIS, 127cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * See the License for the specific language governing permissions and 147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * limitations under the License. 157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */ 167cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 177cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <errno.h> 187cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <fcntl.h> 197cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <stdint.h> 207cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <stdlib.h> 217cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <string.h> 227cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <unistd.h> 237cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define LOG_TAG "ObbFile" 257cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <utils/Log.h> 267cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <utils/ObbFile.h> 277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root//#define DEBUG 1 297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kFooterTagSize 8 /* last two 32-bit integers */ 317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 3202ca31fbae9f35dd30f79de6927fae11b549391aKenny Root#define kFooterMinSize 25 /* 32-bit signature version (4 bytes) 3302ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * 32-bit package version (4 bytes) 3402ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * 32-bit flags (4 bytes) 3502ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * 32-bit package name size (4-bytes) 3602ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * >=1-character package name (1 byte) 3702ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * 32-bit footer size (4 bytes) 3802ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * 32-bit footer marker (4 bytes) 397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */ 407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kMaxBufSize 32768 /* Maximum file read buffer */ 427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kSignature 0x01059983U /* ObbFile signature */ 447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kSigVersion 1 /* We only know about signature version 1 */ 467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* offsets in version 1 of the header */ 487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kPackageVersionOffset 4 4902ca31fbae9f35dd30f79de6927fae11b549391aKenny Root#define kFlagsOffset 8 5002ca31fbae9f35dd30f79de6927fae11b549391aKenny Root#define kPackageNameLenOffset 12 5102ca31fbae9f35dd30f79de6927fae11b549391aKenny Root#define kPackageNameOffset 16 527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* 547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * TEMP_FAILURE_RETRY is defined by some, but not all, versions of 557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's 567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * not already defined, then define it here. 577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */ 587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifndef TEMP_FAILURE_RETRY 597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* Used to retry syscalls that can return EINTR. */ 607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define TEMP_FAILURE_RETRY(exp) ({ \ 617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root typeof (exp) _rc; \ 627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root do { \ 637cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root _rc = (exp); \ 647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } while (_rc == -1 && errno == EINTR); \ 657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root _rc; }) 667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif 677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* 697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * Work around situations where off_t is 64-bit and use off64_t in 707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * situations where it's 32-bit. 717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */ 727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifdef OFF_T_IS_64_BIT 737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define my_lseek64 lseek 747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Roottypedef off_t my_off64_t; 757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#else 767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define my_lseek64 lseek64 777cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Roottypedef off64_t my_off64_t; 787cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif 797cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 807cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootnamespace android { 817cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 827cee34a051eb0087322c8b965e498f88b1aa52d3Kenny RootObbFile::ObbFile() : 8302ca31fbae9f35dd30f79de6927fae11b549391aKenny Root mPackageName(""), 8402ca31fbae9f35dd30f79de6927fae11b549391aKenny Root mVersion(-1), 8502ca31fbae9f35dd30f79de6927fae11b549391aKenny Root mFlags(0) 8602ca31fbae9f35dd30f79de6927fae11b549391aKenny Root{ 877cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 887cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 897cee34a051eb0087322c8b965e498f88b1aa52d3Kenny RootObbFile::~ObbFile() { 907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::readFrom(const char* filename) 937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root int fd; 957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root bool success = false; 967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root fd = ::open(filename, O_RDONLY); 987cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 9987315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("couldn't open file %s: %s", filename, strerror(errno)); 1007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root goto out; 1017cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1027cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root success = readFrom(fd); 1037cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root close(fd); 1047cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1057cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (!success) { 10687315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("failed to read from %s (fd=%d)\n", filename, fd); 1077cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 10887315aa1f0b64efcef416628215be89851cc4736Kenny Root 10987315aa1f0b64efcef416628215be89851cc4736Kenny Rootout: 1107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return success; 1117cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 1127cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1137cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::readFrom(int fd) 1147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 1157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 11687315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("attempt to read from invalid fd\n"); 1177cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1187cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1197cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1207cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return parseObbFile(fd); 1217cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 1227cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1237cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::parseObbFile(int fd) 1247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 1257cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root my_off64_t fileLength = my_lseek64(fd, 0, SEEK_END); 1267cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fileLength < kFooterMinSize) { 1287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fileLength < 0) { 1297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("error seeking in ObbFile: %s\n", strerror(errno)); 1307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } else { 1317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("file is only %lld (less than %d minimum)\n", fileLength, kFooterMinSize); 1327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1347cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root ssize_t actual; 1377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root size_t footerSize; 1387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root { 1407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root my_lseek64(fd, fileLength - kFooterTagSize, SEEK_SET); 1417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root char *footer = new char[kFooterTagSize]; 1437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root actual = TEMP_FAILURE_RETRY(read(fd, footer, kFooterTagSize)); 1447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (actual != kFooterTagSize) { 1457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't read footer signature: %s\n", strerror(errno)); 1467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root unsigned int fileSig = get4LE((unsigned char*)footer + sizeof(int32_t)); 1507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fileSig != kSignature) { 1517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("footer didn't match magic string (expected 0x%08x; got 0x%08x)\n", 1527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root kSignature, fileSig); 1537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root footerSize = get4LE((unsigned char*)footer); 1577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (footerSize > (size_t)fileLength - kFooterTagSize 1587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root || footerSize > kMaxBufSize) { 15987315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("claimed footer size is too large (0x%08zx; file size is 0x%08llx)\n", 1607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root footerSize, fileLength); 1617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 16387315aa1f0b64efcef416628215be89851cc4736Kenny Root 1646e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (footerSize < (kFooterMinSize - kFooterTagSize)) { 1656e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root LOGW("claimed footer size is too small (0x%zx; minimum size is 0x%x)\n", 1666e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root footerSize, kFooterMinSize - kFooterTagSize); 16787315aa1f0b64efcef416628215be89851cc4736Kenny Root return false; 16887315aa1f0b64efcef416628215be89851cc4736Kenny Root } 1697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root my_off64_t fileOffset = fileLength - footerSize - kFooterTagSize; 1727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (my_lseek64(fd, fileOffset, SEEK_SET) != fileOffset) { 1737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("seek %lld failed: %s\n", fileOffset, strerror(errno)); 1747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1776e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root mFooterStart = fileOffset; 1786e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 17987315aa1f0b64efcef416628215be89851cc4736Kenny Root char* scanBuf = (char*)malloc(footerSize); 1807cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (scanBuf == NULL) { 1817cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't allocate scanBuf: %s\n", strerror(errno)); 1827cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 18587315aa1f0b64efcef416628215be89851cc4736Kenny Root actual = TEMP_FAILURE_RETRY(read(fd, scanBuf, footerSize)); 1867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root // readAmount is guaranteed to be less than kMaxBufSize 18787315aa1f0b64efcef416628215be89851cc4736Kenny Root if (actual != (ssize_t)footerSize) { 1887cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGI("couldn't read ObbFile footer: %s\n", strerror(errno)); 1897cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 1907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifdef DEBUG 19487315aa1f0b64efcef416628215be89851cc4736Kenny Root for (int i = 0; i < footerSize; ++i) { 1957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGI("char: 0x%02x", scanBuf[i]); 1967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif 1987cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root uint32_t sigVersion = get4LE((unsigned char*)scanBuf); 2007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (sigVersion != kSigVersion) { 2017cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("Unsupported ObbFile version %d\n", sigVersion); 2027cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 2037cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2047cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2057cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2067cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset); 20702ca31fbae9f35dd30f79de6927fae11b549391aKenny Root mFlags = (int32_t) get4LE((unsigned char*)scanBuf + kFlagsOffset); 2087cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2097cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset); 2107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (packageNameLen <= 0 2117cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root || packageNameLen > (footerSize - kPackageNameOffset)) { 21287315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("bad ObbFile package name length (0x%04x; 0x%04x possible)\n", 21387315aa1f0b64efcef416628215be89851cc4736Kenny Root packageNameLen, footerSize - kPackageNameOffset); 2147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 2157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2167cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2177cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2187cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root char* packageName = reinterpret_cast<char*>(scanBuf + kPackageNameOffset); 2197cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root mPackageName = String8(const_cast<char*>(packageName), packageNameLen); 2207cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2217cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 22287315aa1f0b64efcef416628215be89851cc4736Kenny Root 22387315aa1f0b64efcef416628215be89851cc4736Kenny Root#ifdef DEBUG 22487315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGI("Obb scan succeeded: packageName=%s, version=%d\n", mPackageName.string(), mVersion); 22587315aa1f0b64efcef416628215be89851cc4736Kenny Root#endif 22687315aa1f0b64efcef416628215be89851cc4736Kenny Root 2277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return true; 2287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 2297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::writeTo(const char* filename) 2317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 2327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root int fd; 2337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root bool success = false; 2347cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root fd = ::open(filename, O_WRONLY); 2367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 2377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root goto out; 2387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root success = writeTo(fd); 2407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root close(fd); 2417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootout: 2437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (!success) { 2447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("failed to write to %s: %s\n", filename, strerror(errno)); 2457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return success; 2477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 2487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::writeTo(int fd) 2507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 2517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 2527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 25587315aa1f0b64efcef416628215be89851cc4736Kenny Root my_lseek64(fd, 0, SEEK_END); 25687315aa1f0b64efcef416628215be89851cc4736Kenny Root 2577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (mPackageName.size() == 0 || mVersion == -1) { 2587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("tried to write uninitialized ObbFile data"); 2597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root unsigned char intBuf[sizeof(uint32_t)+1]; 2637cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root memset(&intBuf, 0, sizeof(intBuf)); 2647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, kSigVersion); 2667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write signature version: %s", strerror(errno)); 2687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, mVersion); 2727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write package version"); 2747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 27702ca31fbae9f35dd30f79de6927fae11b549391aKenny Root put4LE(intBuf, mFlags); 27802ca31fbae9f35dd30f79de6927fae11b549391aKenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 27902ca31fbae9f35dd30f79de6927fae11b549391aKenny Root LOGW("couldn't write package version"); 28002ca31fbae9f35dd30f79de6927fae11b549391aKenny Root return false; 28102ca31fbae9f35dd30f79de6927fae11b549391aKenny Root } 28202ca31fbae9f35dd30f79de6927fae11b549391aKenny Root 2837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root size_t packageNameLen = mPackageName.size(); 2847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, packageNameLen); 2857cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write package name length: %s", strerror(errno)); 2877cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2887cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2897cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, mPackageName.string(), packageNameLen) != (ssize_t)packageNameLen) { 2917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write package name: %s", strerror(errno)); 2927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 29502ca31fbae9f35dd30f79de6927fae11b549391aKenny Root put4LE(intBuf, kPackageNameOffset + packageNameLen); 2967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write footer size: %s", strerror(errno)); 2987cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 3007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 3017cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, kSignature); 3027cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 3037cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write footer magic signature: %s", strerror(errno)); 3047cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 3057cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 3067cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 3077cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return true; 3087cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 3097cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 3106e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootbool ObbFile::removeFrom(const char* filename) 3116e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root{ 3126e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root int fd; 3136e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root bool success = false; 3146e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3156e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fd = ::open(filename, O_RDWR); 3166e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (fd < 0) { 3176e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto out; 3186e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 3196e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root success = removeFrom(fd); 3206e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root close(fd); 3216e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3226e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootout: 3236e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (!success) { 3246e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root LOGW("failed to remove signature from %s: %s\n", filename, strerror(errno)); 3256e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 3266e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return success; 3276e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root} 3286e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3296e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootbool ObbFile::removeFrom(int fd) 3306e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root{ 3316e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (fd < 0) { 3326e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return false; 3336e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 3346e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3356e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (!readFrom(fd)) { 3366e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return false; 3376e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 3386e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3396e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root ftruncate(fd, mFooterStart); 3406e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3416e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return true; 3426e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root} 3436e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 345