ObbFile.cpp revision 87315aa1f0b64efcef416628215be89851cc4736
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 327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kFooterMinSize 21 /* 32-bit signature version 337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 32-bit package version 347cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 32-bit package name size 357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 1-character package name 367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 32-bit footer size 377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * 32-bit footer marker 387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */ 397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kMaxBufSize 32768 /* Maximum file read buffer */ 417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kSignature 0x01059983U /* ObbFile signature */ 437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kSigVersion 1 /* We only know about signature version 1 */ 457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* offsets in version 1 of the header */ 477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kPackageVersionOffset 4 487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kPackageNameLenOffset 8 497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kPackageNameOffset 12 507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* 527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * TEMP_FAILURE_RETRY is defined by some, but not all, versions of 537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's 547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * not already defined, then define it here. 557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */ 567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifndef TEMP_FAILURE_RETRY 577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* Used to retry syscalls that can return EINTR. */ 587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define TEMP_FAILURE_RETRY(exp) ({ \ 597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root typeof (exp) _rc; \ 607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root do { \ 617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root _rc = (exp); \ 627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } while (_rc == -1 && errno == EINTR); \ 637cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root _rc; }) 647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif 657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* 677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * Work around situations where off_t is 64-bit and use off64_t in 687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * situations where it's 32-bit. 697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */ 707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifdef OFF_T_IS_64_BIT 717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define my_lseek64 lseek 727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Roottypedef off_t my_off64_t; 737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#else 747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define my_lseek64 lseek64 757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Roottypedef off64_t my_off64_t; 767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif 777cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 787cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootnamespace android { 797cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 807cee34a051eb0087322c8b965e498f88b1aa52d3Kenny RootObbFile::ObbFile() : 817cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root mVersion(-1) { 827cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny RootObbFile::~ObbFile() { 857cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 877cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::readFrom(const char* filename) 887cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 897cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root int fd; 907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root bool success = false; 917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root fd = ::open(filename, O_RDONLY); 937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 9487315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("couldn't open file %s: %s", filename, strerror(errno)); 957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root goto out; 967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root success = readFrom(fd); 987cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root close(fd); 997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (!success) { 10187315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("failed to read from %s (fd=%d)\n", filename, fd); 1027cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 10387315aa1f0b64efcef416628215be89851cc4736Kenny Root 10487315aa1f0b64efcef416628215be89851cc4736Kenny Rootout: 1057cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return success; 1067cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 1077cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1087cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::readFrom(int fd) 1097cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 1107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 11187315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("attempt to read from invalid fd\n"); 1127cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1137cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return parseObbFile(fd); 1167cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 1177cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1187cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::parseObbFile(int fd) 1197cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 1207cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root my_off64_t fileLength = my_lseek64(fd, 0, SEEK_END); 1217cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1227cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fileLength < kFooterMinSize) { 1237cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fileLength < 0) { 1247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("error seeking in ObbFile: %s\n", strerror(errno)); 1257cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } else { 1267cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("file is only %lld (less than %d minimum)\n", fileLength, kFooterMinSize); 1277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root ssize_t actual; 1327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root size_t footerSize; 1337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1347cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root { 1357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root my_lseek64(fd, fileLength - kFooterTagSize, SEEK_SET); 1367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root char *footer = new char[kFooterTagSize]; 1387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root actual = TEMP_FAILURE_RETRY(read(fd, footer, kFooterTagSize)); 1397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (actual != kFooterTagSize) { 1407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't read footer signature: %s\n", strerror(errno)); 1417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root unsigned int fileSig = get4LE((unsigned char*)footer + sizeof(int32_t)); 1457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fileSig != kSignature) { 1467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("footer didn't match magic string (expected 0x%08x; got 0x%08x)\n", 1477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root kSignature, fileSig); 1487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root footerSize = get4LE((unsigned char*)footer); 1527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (footerSize > (size_t)fileLength - kFooterTagSize 1537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root || footerSize > kMaxBufSize) { 15487315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("claimed footer size is too large (0x%08zx; file size is 0x%08llx)\n", 1557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root footerSize, fileLength); 1567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 15887315aa1f0b64efcef416628215be89851cc4736Kenny Root 15987315aa1f0b64efcef416628215be89851cc4736Kenny Root if (footerSize < kFooterMinSize) { 16087315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("claimed footer size is too small (%08zx; minimum size is 0x%x)\n", 16187315aa1f0b64efcef416628215be89851cc4736Kenny Root footerSize, kFooterMinSize); 16287315aa1f0b64efcef416628215be89851cc4736Kenny Root return false; 16387315aa1f0b64efcef416628215be89851cc4736Kenny Root } 1647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root my_off64_t fileOffset = fileLength - footerSize - kFooterTagSize; 1677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (my_lseek64(fd, fileOffset, SEEK_SET) != fileOffset) { 1687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("seek %lld failed: %s\n", fileOffset, strerror(errno)); 1697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 17287315aa1f0b64efcef416628215be89851cc4736Kenny Root char* scanBuf = (char*)malloc(footerSize); 1737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (scanBuf == NULL) { 1747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't allocate scanBuf: %s\n", strerror(errno)); 1757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1777cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 17887315aa1f0b64efcef416628215be89851cc4736Kenny Root actual = TEMP_FAILURE_RETRY(read(fd, scanBuf, footerSize)); 1797cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root // readAmount is guaranteed to be less than kMaxBufSize 18087315aa1f0b64efcef416628215be89851cc4736Kenny Root if (actual != (ssize_t)footerSize) { 1817cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGI("couldn't read ObbFile footer: %s\n", strerror(errno)); 1827cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 1837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1857cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifdef DEBUG 18787315aa1f0b64efcef416628215be89851cc4736Kenny Root for (int i = 0; i < footerSize; ++i) { 1887cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGI("char: 0x%02x", scanBuf[i]); 1897cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif 1917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root uint32_t sigVersion = get4LE((unsigned char*)scanBuf); 1937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (sigVersion != kSigVersion) { 1947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("Unsupported ObbFile version %d\n", sigVersion); 1957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 1967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 1977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 1987cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 1997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset); 2007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2017cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset); 2027cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (packageNameLen <= 0 2037cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root || packageNameLen > (footerSize - kPackageNameOffset)) { 20487315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGW("bad ObbFile package name length (0x%04x; 0x%04x possible)\n", 20587315aa1f0b64efcef416628215be89851cc4736Kenny Root packageNameLen, footerSize - kPackageNameOffset); 2067cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 2077cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2087cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2097cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root char* packageName = reinterpret_cast<char*>(scanBuf + kPackageNameOffset); 2117cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root mPackageName = String8(const_cast<char*>(packageName), packageNameLen); 2127cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2137cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root free(scanBuf); 21487315aa1f0b64efcef416628215be89851cc4736Kenny Root 21587315aa1f0b64efcef416628215be89851cc4736Kenny Root#ifdef DEBUG 21687315aa1f0b64efcef416628215be89851cc4736Kenny Root LOGI("Obb scan succeeded: packageName=%s, version=%d\n", mPackageName.string(), mVersion); 21787315aa1f0b64efcef416628215be89851cc4736Kenny Root#endif 21887315aa1f0b64efcef416628215be89851cc4736Kenny Root 2197cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return true; 2207cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 2217cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2227cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::writeTo(const char* filename) 2237cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 2247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root int fd; 2257cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root bool success = false; 2267cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root fd = ::open(filename, O_WRONLY); 2287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 2297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root goto out; 2307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root success = writeTo(fd); 2327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root close(fd); 2337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2347cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootout: 2357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (!success) { 2367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("failed to write to %s: %s\n", filename, strerror(errno)); 2377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return success; 2397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 2407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::writeTo(int fd) 2427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{ 2437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (fd < 0) { 2447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 24787315aa1f0b64efcef416628215be89851cc4736Kenny Root my_lseek64(fd, 0, SEEK_END); 24887315aa1f0b64efcef416628215be89851cc4736Kenny Root 2497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (mPackageName.size() == 0 || mVersion == -1) { 2507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("tried to write uninitialized ObbFile data"); 2517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root unsigned char intBuf[sizeof(uint32_t)+1]; 2557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root memset(&intBuf, 0, sizeof(intBuf)); 2567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, kSigVersion); 2587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write signature version: %s", strerror(errno)); 2607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2637cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, mVersion); 2647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write package version"); 2667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root size_t packageNameLen = mPackageName.size(); 2707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, packageNameLen); 2717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write package name length: %s", strerror(errno)); 2737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, mPackageName.string(), packageNameLen) != (ssize_t)packageNameLen) { 2777cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write package name: %s", strerror(errno)); 2787cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2797cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2807cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2817cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, 3*sizeof(uint32_t) + packageNameLen); 2827cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write footer size: %s", strerror(errno)); 2847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2857cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2877cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root put4LE(intBuf, kSignature); 2887cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { 2897cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root LOGW("couldn't write footer magic signature: %s", strerror(errno)); 2907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return false; 2917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root } 2927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root return true; 2947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 2957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root 2967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root} 297