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