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
26b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ObbFile.h>
27ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root#include <utils/Compat.h>
287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#include <utils/Log.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) {
938564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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) {
1008564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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) {
1108564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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) {
1238564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("error seeking in ObbFile: %s\n", strerror(errno));
1247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        } else {
1258564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("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) {
1398564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("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) {
1458564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("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) {
1538564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("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)) {
1598564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("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) {
1678564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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) {
1758564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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) {
1826215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block        ALOGI("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) {
1896215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block        ALOGI("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) {
1958564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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)) {
2088564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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
2206215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block    ALOGI("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) {
2408564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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) {
2548564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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)) {
2638564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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)) {
2698564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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)) {
2758564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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)) {
2808564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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)) {
2878564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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) {
2928564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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)) {
2988564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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)) {
3048564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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) {
3258564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("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