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" 25ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root 26ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root#include <utils/Compat.h> 277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <utils/Log.h> 287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <utils/ObbFile.h> 297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root//#define DEBUG 1 317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kFooterTagSize 8 /* last two 32-bit integers */ 337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 343b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#define kFooterMinSize 33 /* 32-bit signature version (4 bytes) 3502ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * 32-bit package version (4 bytes) 3602ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * 32-bit flags (4 bytes) 373b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root * 64-bit salt (8 bytes) 383b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root * 32-bit package name size (4 bytes) 3902ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * >=1-character package name (1 byte) 4002ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * 32-bit footer size (4 bytes) 4102ca31fbae9f35dd30f79de6927fae11b549391aKenny Root * 32-bit footer marker (4 bytes) 427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */ 437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kMaxBufSize 32768 /* Maximum file read buffer */ 457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kSignature 0x01059983U /* ObbFile signature */ 477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kSigVersion 1 /* We only know about signature version 1 */ 497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* offsets in version 1 of the header */ 517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kPackageVersionOffset 4 5202ca31fbae9f35dd30f79de6927fae11b549391aKenny Root#define kFlagsOffset 8 533b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#define kSaltOffset 12 543b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#define kPackageNameLenOffset 20 553b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#define kPackageNameOffset 24 567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* 587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * TEMP_FAILURE_RETRY is defined by some, but not all, versions of 597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's 607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * not already defined, then define it here. 617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */ 627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifndef TEMP_FAILURE_RETRY 637cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* Used to retry syscalls that can return EINTR. */ 647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define TEMP_FAILURE_RETRY(exp) ({ \ 657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root typeof (exp) _rc; \ 667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root do { \ 677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root _rc = (exp); \ 687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } while (_rc == -1 && errno == EINTR); \ 697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root _rc; }) 707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif 717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootnamespace android { 747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 753b1abba6bbc895d63da3e82e9b158c01bd12edddKenny RootObbFile::ObbFile() 763b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root : mPackageName("") 773b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root , mVersion(-1) 783b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root , mFlags(0) 7902ca31fbae9f35dd30f79de6927fae11b549391aKenny Root{ 803b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root memset(mSalt, 0, sizeof(mSalt)); 817cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 827cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny RootObbFile::~ObbFile() { 847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 857cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::readFrom(const char* filename) 877cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 887cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root int fd; 897cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root bool success = false; 907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root fd = ::open(filename, O_RDONLY); 927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 9387315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("couldn't open file %s: %s", filename, strerror(errno)); 947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root goto out; 957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root success = readFrom(fd); 977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root close(fd); 987cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (!success) { 10087315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("failed to read from %s (fd=%d)\n", filename, fd); 1017cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 10287315aa1f0b64efcef416628215be89851cc4736Kenny Root 10387315aa1f0b64efcef416628215be89851cc4736Kenny Rootout: 1047cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return success; 1057cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 1067cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1077cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::readFrom(int fd) 1087cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 1097cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 11087315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("attempt to read from invalid fd\n"); 1117cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1127cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1137cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return parseObbFile(fd); 1157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 1167cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1177cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::parseObbFile(int fd) 1187cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 119ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root off64_t fileLength = lseek64(fd, 0, SEEK_END); 1207cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1217cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fileLength < kFooterMinSize) { 1227cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fileLength < 0) { 1237cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("error seeking in ObbFile: %s\n", strerror(errno)); 1247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } else { 1257cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("file is only %lld (less than %d minimum)\n", fileLength, kFooterMinSize); 1267cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root ssize_t actual; 1317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root size_t footerSize; 1327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root { 134ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root lseek64(fd, fileLength - kFooterTagSize, SEEK_SET); 1357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root char *footer = new char[kFooterTagSize]; 1377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root actual = TEMP_FAILURE_RETRY(read(fd, footer, kFooterTagSize)); 1387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (actual != kFooterTagSize) { 1397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't read footer signature: %s\n", strerror(errno)); 1407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root unsigned int fileSig = get4LE((unsigned char*)footer + sizeof(int32_t)); 1447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fileSig != kSignature) { 1457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("footer didn't match magic string (expected 0x%08x; got 0x%08x)\n", 1467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root kSignature, fileSig); 1477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root footerSize = get4LE((unsigned char*)footer); 1517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (footerSize > (size_t)fileLength - kFooterTagSize 1527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root || footerSize > kMaxBufSize) { 15387315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("claimed footer size is too large (0x%08zx; file size is 0x%08llx)\n", 1547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root footerSize, fileLength); 1557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 15787315aa1f0b64efcef416628215be89851cc4736Kenny Root 1586e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (footerSize < (kFooterMinSize - kFooterTagSize)) { 1596e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root LOGW("claimed footer size is too small (0x%zx; minimum size is 0x%x)\n", 1606e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root footerSize, kFooterMinSize - kFooterTagSize); 16187315aa1f0b64efcef416628215be89851cc4736Kenny Root return false; 16287315aa1f0b64efcef416628215be89851cc4736Kenny Root } 1637cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 165ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root off64_t fileOffset = fileLength - footerSize - kFooterTagSize; 166ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root if (lseek64(fd, fileOffset, SEEK_SET) != fileOffset) { 1677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("seek %lld failed: %s\n", fileOffset, strerror(errno)); 1687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1716e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root mFooterStart = fileOffset; 1726e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 17387315aa1f0b64efcef416628215be89851cc4736Kenny Root char* scanBuf = (char*)malloc(footerSize); 1747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (scanBuf == NULL) { 1757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't allocate scanBuf: %s\n", strerror(errno)); 1767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1777cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1787cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 17987315aa1f0b64efcef416628215be89851cc4736Kenny Root actual = TEMP_FAILURE_RETRY(read(fd, scanBuf, footerSize)); 1807cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root // readAmount is guaranteed to be less than kMaxBufSize 18187315aa1f0b64efcef416628215be89851cc4736Kenny Root if (actual != (ssize_t)footerSize) { 1827cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGI("couldn't read ObbFile footer: %s\n", strerror(errno)); 1837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 1847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1857cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1877cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifdef DEBUG 18887315aa1f0b64efcef416628215be89851cc4736Kenny Root for (int i = 0; i < footerSize; ++i) { 1893b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root LOGI("char: 0x%02x\n", scanBuf[i]); 1907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif 1927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root uint32_t sigVersion = get4LE((unsigned char*)scanBuf); 1947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (sigVersion != kSigVersion) { 1957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("Unsupported ObbFile version %d\n", sigVersion); 1967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 1977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1987cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset); 20102ca31fbae9f35dd30f79de6927fae11b549391aKenny Root mFlags = (int32_t) get4LE((unsigned char*)scanBuf + kFlagsOffset); 2027cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2033b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root memcpy(&mSalt, (unsigned char*)scanBuf + kSaltOffset, sizeof(mSalt)); 2043b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root 205ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root size_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset); 206ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root if (packageNameLen == 0 2077cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root || packageNameLen > (footerSize - kPackageNameOffset)) { 208ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root LOGW("bad ObbFile package name length (0x%04zx; 0x%04zx possible)\n", 20987315aa1f0b64efcef416628215be89851cc4736Kenny Root packageNameLen, footerSize - kPackageNameOffset); 2107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 2117cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2127cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2137cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root char* packageName = reinterpret_cast<char*>(scanBuf + kPackageNameOffset); 2157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root mPackageName = String8(const_cast<char*>(packageName), packageNameLen); 2167cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2177cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 21887315aa1f0b64efcef416628215be89851cc4736Kenny Root 21987315aa1f0b64efcef416628215be89851cc4736Kenny Root#ifdef DEBUG 22087315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGI("Obb scan succeeded: packageName=%s, version=%d\n", mPackageName.string(), mVersion); 22187315aa1f0b64efcef416628215be89851cc4736Kenny Root#endif 22287315aa1f0b64efcef416628215be89851cc4736Kenny Root 2237cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return true; 2247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 2257cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2267cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::writeTo(const char* filename) 2277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 2287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root int fd; 2297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root bool success = false; 2307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root fd = ::open(filename, O_WRONLY); 2327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 2337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root goto out; 2347cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root success = writeTo(fd); 2367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root close(fd); 2377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootout: 2397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (!success) { 2407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("failed to write to %s: %s\n", filename, strerror(errno)); 2417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return success; 2437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 2447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::writeTo(int fd) 2467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 2477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 2487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 251ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root lseek64(fd, 0, SEEK_END); 25287315aa1f0b64efcef416628215be89851cc4736Kenny Root 2537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (mPackageName.size() == 0 || mVersion == -1) { 2543b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root LOGW("tried to write uninitialized ObbFile data\n"); 2557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root unsigned char intBuf[sizeof(uint32_t)+1]; 2597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root memset(&intBuf, 0, sizeof(intBuf)); 2607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, kSigVersion); 2627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2633b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root LOGW("couldn't write signature version: %s\n", strerror(errno)); 2647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, mVersion); 2687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2693b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root LOGW("couldn't write package version\n"); 2707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 27302ca31fbae9f35dd30f79de6927fae11b549391aKenny Root put4LE(intBuf, mFlags); 27402ca31fbae9f35dd30f79de6927fae11b549391aKenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2753b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root LOGW("couldn't write package version\n"); 2763b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root return false; 2773b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } 2783b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root 2793b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root if (write(fd, mSalt, sizeof(mSalt)) != (ssize_t)sizeof(mSalt)) { 2803b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root LOGW("couldn't write salt: %s\n", strerror(errno)); 28102ca31fbae9f35dd30f79de6927fae11b549391aKenny Root return false; 28202ca31fbae9f35dd30f79de6927fae11b549391aKenny Root } 28302ca31fbae9f35dd30f79de6927fae11b549391aKenny Root 2847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root size_t packageNameLen = mPackageName.size(); 2857cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, packageNameLen); 2867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2873b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root LOGW("couldn't write package name length: %s\n", strerror(errno)); 2887cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2897cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, mPackageName.string(), packageNameLen) != (ssize_t)packageNameLen) { 2923b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root LOGW("couldn't write package name: %s\n", strerror(errno)); 2937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 29602ca31fbae9f35dd30f79de6927fae11b549391aKenny Root put4LE(intBuf, kPackageNameOffset + packageNameLen); 2977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2983b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root LOGW("couldn't write footer size: %s\n", strerror(errno)); 2997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 3007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 3017cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 3027cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, kSignature); 3037cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 3043b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root LOGW("couldn't write footer magic signature: %s\n", strerror(errno)); 3057cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 3067cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 3077cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 3087cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return true; 3097cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 3107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 3116e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootbool ObbFile::removeFrom(const char* filename) 3126e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root{ 3136e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root int fd; 3146e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root bool success = false; 3156e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3166e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fd = ::open(filename, O_RDWR); 3176e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (fd < 0) { 3186e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto out; 3196e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 3206e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root success = removeFrom(fd); 3216e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root close(fd); 3226e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3236e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootout: 3246e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (!success) { 3256e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root LOGW("failed to remove signature from %s: %s\n", filename, strerror(errno)); 3266e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 3276e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return success; 3286e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root} 3296e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3306e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootbool ObbFile::removeFrom(int fd) 3316e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root{ 3326e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (fd < 0) { 3336e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return false; 3346e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 3356e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3366e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (!readFrom(fd)) { 3376e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return false; 3386e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 3396e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3406e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root ftruncate(fd, mFooterStart); 3416e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3426e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return true; 3436e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root} 3446e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 346