ObbFile.cpp revision 3b1abba6bbc895d63da3e82e9b158c01bd12eddd
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
323b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#define kFooterMinSize 33 /* 32-bit signature version (4 bytes)
3302ca31fbae9f35dd30f79de6927fae11b549391aKenny Root                           * 32-bit package version (4 bytes)
3402ca31fbae9f35dd30f79de6927fae11b549391aKenny Root                           * 32-bit flags (4 bytes)
353b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root                           * 64-bit salt (8 bytes)
363b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root                           * 32-bit package name size (4 bytes)
3702ca31fbae9f35dd30f79de6927fae11b549391aKenny Root                           * >=1-character package name (1 byte)
3802ca31fbae9f35dd30f79de6927fae11b549391aKenny Root                           * 32-bit footer size (4 bytes)
3902ca31fbae9f35dd30f79de6927fae11b549391aKenny Root                           * 32-bit footer marker (4 bytes)
407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root                           */
417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kMaxBufSize    32768 /* Maximum file read buffer */
437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kSignature     0x01059983U /* ObbFile signature */
457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kSigVersion    1 /* We only know about signature version 1 */
477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* offsets in version 1 of the header */
497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define kPackageVersionOffset 4
5002ca31fbae9f35dd30f79de6927fae11b549391aKenny Root#define kFlagsOffset          8
513b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#define kSaltOffset           12
523b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#define kPackageNameLenOffset 20
533b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#define kPackageNameOffset    24
547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/*
567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * not already defined, then define it here.
597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */
607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifndef TEMP_FAILURE_RETRY
617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/* Used to retry syscalls that can return EINTR. */
627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define TEMP_FAILURE_RETRY(exp) ({         \
637cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    typeof (exp) _rc;                      \
647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    do {                                   \
657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        _rc = (exp);                       \
667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    } while (_rc == -1 && errno == EINTR); \
677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    _rc; })
687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif
697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root/*
717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * Work around situations where off_t is 64-bit and use off64_t in
727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root * situations where it's 32-bit.
737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root */
747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifdef OFF_T_IS_64_BIT
757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define my_lseek64 lseek
767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Roottypedef off_t my_off64_t;
777cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#else
787cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#define my_lseek64 lseek64
797cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Roottypedef off64_t my_off64_t;
807cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif
817cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
827cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootnamespace android {
837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
843b1abba6bbc895d63da3e82e9b158c01bd12edddKenny RootObbFile::ObbFile()
853b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        : mPackageName("")
863b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        , mVersion(-1)
873b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        , mFlags(0)
8802ca31fbae9f35dd30f79de6927fae11b549391aKenny Root{
893b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root    memset(mSalt, 0, sizeof(mSalt));
907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny RootObbFile::~ObbFile() {
937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::readFrom(const char* filename)
967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{
977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    int fd;
987cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    bool success = false;
997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    fd = ::open(filename, O_RDONLY);
1017cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (fd < 0) {
10287315aa1f0b64efcef416628215be89851cc4736Kenny Root        LOGW("couldn't open file %s: %s", filename, strerror(errno));
1037cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        goto out;
1047cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
1057cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    success = readFrom(fd);
1067cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    close(fd);
1077cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1087cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (!success) {
10987315aa1f0b64efcef416628215be89851cc4736Kenny Root        LOGW("failed to read from %s (fd=%d)\n", filename, fd);
1107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
11187315aa1f0b64efcef416628215be89851cc4736Kenny Root
11287315aa1f0b64efcef416628215be89851cc4736Kenny Rootout:
1137cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    return success;
1147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
1157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1167cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::readFrom(int fd)
1177cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{
1187cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (fd < 0) {
11987315aa1f0b64efcef416628215be89851cc4736Kenny Root        LOGW("attempt to read from invalid fd\n");
1207cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
1217cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
1227cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1237cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    return parseObbFile(fd);
1247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
1257cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1267cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::parseObbFile(int fd)
1277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{
1287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    my_off64_t fileLength = my_lseek64(fd, 0, SEEK_END);
1297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (fileLength < kFooterMinSize) {
1317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        if (fileLength < 0) {
1327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root            LOGW("error seeking in ObbFile: %s\n", strerror(errno));
1337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        } else {
1347cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root            LOGW("file is only %lld (less than %d minimum)\n", fileLength, kFooterMinSize);
1357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        }
1367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
1377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
1387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    ssize_t actual;
1407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    size_t footerSize;
1417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    {
1437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        my_lseek64(fd, fileLength - kFooterTagSize, SEEK_SET);
1447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        char *footer = new char[kFooterTagSize];
1467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        actual = TEMP_FAILURE_RETRY(read(fd, footer, kFooterTagSize));
1477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        if (actual != kFooterTagSize) {
1487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root            LOGW("couldn't read footer signature: %s\n", strerror(errno));
1497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root            return false;
1507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        }
1517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        unsigned int fileSig = get4LE((unsigned char*)footer + sizeof(int32_t));
1537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        if (fileSig != kSignature) {
1547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root            LOGW("footer didn't match magic string (expected 0x%08x; got 0x%08x)\n",
1557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root                    kSignature, fileSig);
1567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root            return false;
1577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        }
1587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        footerSize = get4LE((unsigned char*)footer);
1607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        if (footerSize > (size_t)fileLength - kFooterTagSize
1617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root                || footerSize > kMaxBufSize) {
16287315aa1f0b64efcef416628215be89851cc4736Kenny Root            LOGW("claimed footer size is too large (0x%08zx; file size is 0x%08llx)\n",
1637cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root                    footerSize, fileLength);
1647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root            return false;
1657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        }
16687315aa1f0b64efcef416628215be89851cc4736Kenny Root
1676e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root        if (footerSize < (kFooterMinSize - kFooterTagSize)) {
1686e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root            LOGW("claimed footer size is too small (0x%zx; minimum size is 0x%x)\n",
1696e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root                    footerSize, kFooterMinSize - kFooterTagSize);
17087315aa1f0b64efcef416628215be89851cc4736Kenny Root            return false;
17187315aa1f0b64efcef416628215be89851cc4736Kenny Root        }
1727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
1737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    my_off64_t fileOffset = fileLength - footerSize - kFooterTagSize;
1757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (my_lseek64(fd, fileOffset, SEEK_SET) != fileOffset) {
1767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("seek %lld failed: %s\n", fileOffset, strerror(errno));
1777cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
1787cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
1797cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1806e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    mFooterStart = fileOffset;
1816e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
18287315aa1f0b64efcef416628215be89851cc4736Kenny Root    char* scanBuf = (char*)malloc(footerSize);
1837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (scanBuf == NULL) {
1847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("couldn't allocate scanBuf: %s\n", strerror(errno));
1857cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
1867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
1877cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
18887315aa1f0b64efcef416628215be89851cc4736Kenny Root    actual = TEMP_FAILURE_RETRY(read(fd, scanBuf, footerSize));
1897cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    // readAmount is guaranteed to be less than kMaxBufSize
19087315aa1f0b64efcef416628215be89851cc4736Kenny Root    if (actual != (ssize_t)footerSize) {
1917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGI("couldn't read ObbFile footer: %s\n", strerror(errno));
1927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        free(scanBuf);
1937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
1947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
1957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifdef DEBUG
19787315aa1f0b64efcef416628215be89851cc4736Kenny Root    for (int i = 0; i < footerSize; ++i) {
1983b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        LOGI("char: 0x%02x\n", scanBuf[i]);
1997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif
2017cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2027cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    uint32_t sigVersion = get4LE((unsigned char*)scanBuf);
2037cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (sigVersion != kSigVersion) {
2047cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("Unsupported ObbFile version %d\n", sigVersion);
2057cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        free(scanBuf);
2067cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2077cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2087cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2097cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset);
21002ca31fbae9f35dd30f79de6927fae11b549391aKenny Root    mFlags = (int32_t) get4LE((unsigned char*)scanBuf + kFlagsOffset);
2117cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2123b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root    memcpy(&mSalt, (unsigned char*)scanBuf + kSaltOffset, sizeof(mSalt));
2133b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root
2147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
2157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (packageNameLen <= 0
2167cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root            || packageNameLen > (footerSize - kPackageNameOffset)) {
21787315aa1f0b64efcef416628215be89851cc4736Kenny Root        LOGW("bad ObbFile package name length (0x%04x; 0x%04x possible)\n",
21887315aa1f0b64efcef416628215be89851cc4736Kenny Root                packageNameLen, footerSize - kPackageNameOffset);
2197cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        free(scanBuf);
2207cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2217cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2227cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2237cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    char* packageName = reinterpret_cast<char*>(scanBuf + kPackageNameOffset);
2247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    mPackageName = String8(const_cast<char*>(packageName), packageNameLen);
2257cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2267cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    free(scanBuf);
22787315aa1f0b64efcef416628215be89851cc4736Kenny Root
22887315aa1f0b64efcef416628215be89851cc4736Kenny Root#ifdef DEBUG
22987315aa1f0b64efcef416628215be89851cc4736Kenny Root    LOGI("Obb scan succeeded: packageName=%s, version=%d\n", mPackageName.string(), mVersion);
23087315aa1f0b64efcef416628215be89851cc4736Kenny Root#endif
23187315aa1f0b64efcef416628215be89851cc4736Kenny Root
2327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    return true;
2337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
2347cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::writeTo(const char* filename)
2367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{
2377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    int fd;
2387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    bool success = false;
2397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    fd = ::open(filename, O_WRONLY);
2417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (fd < 0) {
2427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        goto out;
2437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    success = writeTo(fd);
2457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    close(fd);
2467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootout:
2487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (!success) {
2497cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("failed to write to %s: %s\n", filename, strerror(errno));
2507cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    return success;
2527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
2537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::writeTo(int fd)
2557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{
2567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (fd < 0) {
2577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
26087315aa1f0b64efcef416628215be89851cc4736Kenny Root    my_lseek64(fd, 0, SEEK_END);
26187315aa1f0b64efcef416628215be89851cc4736Kenny Root
2627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (mPackageName.size() == 0 || mVersion == -1) {
2633b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        LOGW("tried to write uninitialized ObbFile data\n");
2647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    unsigned char intBuf[sizeof(uint32_t)+1];
2687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    memset(&intBuf, 0, sizeof(intBuf));
2697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    put4LE(intBuf, kSigVersion);
2717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
2723b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        LOGW("couldn't write signature version: %s\n", strerror(errno));
2737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    put4LE(intBuf, mVersion);
2777cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
2783b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        LOGW("couldn't write package version\n");
2797cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2807cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2817cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
28202ca31fbae9f35dd30f79de6927fae11b549391aKenny Root    put4LE(intBuf, mFlags);
28302ca31fbae9f35dd30f79de6927fae11b549391aKenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
2843b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        LOGW("couldn't write package version\n");
2853b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        return false;
2863b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root    }
2873b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root
2883b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root    if (write(fd, mSalt, sizeof(mSalt)) != (ssize_t)sizeof(mSalt)) {
2893b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        LOGW("couldn't write salt: %s\n", strerror(errno));
29002ca31fbae9f35dd30f79de6927fae11b549391aKenny Root        return false;
29102ca31fbae9f35dd30f79de6927fae11b549391aKenny Root    }
29202ca31fbae9f35dd30f79de6927fae11b549391aKenny Root
2937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    size_t packageNameLen = mPackageName.size();
2947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    put4LE(intBuf, packageNameLen);
2957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
2963b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        LOGW("couldn't write package name length: %s\n", strerror(errno));
2977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2987cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
3007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, mPackageName.string(), packageNameLen) != (ssize_t)packageNameLen) {
3013b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        LOGW("couldn't write package name: %s\n", strerror(errno));
3027cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
3037cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
3047cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
30502ca31fbae9f35dd30f79de6927fae11b549391aKenny Root    put4LE(intBuf, kPackageNameOffset + packageNameLen);
3067cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
3073b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        LOGW("couldn't write footer size: %s\n", strerror(errno));
3087cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
3097cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
3107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
3117cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    put4LE(intBuf, kSignature);
3127cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
3133b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root        LOGW("couldn't write footer magic signature: %s\n", strerror(errno));
3147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
3157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
3167cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
3177cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    return true;
3187cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
3197cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
3206e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootbool ObbFile::removeFrom(const char* filename)
3216e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root{
3226e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    int fd;
3236e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    bool success = false;
3246e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3256e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    fd = ::open(filename, O_RDWR);
3266e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    if (fd < 0) {
3276e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root        goto out;
3286e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    }
3296e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    success = removeFrom(fd);
3306e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    close(fd);
3316e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3326e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootout:
3336e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    if (!success) {
3346e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root        LOGW("failed to remove signature from %s: %s\n", filename, strerror(errno));
3356e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    }
3366e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    return success;
3376e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root}
3386e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3396e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootbool ObbFile::removeFrom(int fd)
3406e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root{
3416e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    if (fd < 0) {
3426e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root        return false;
3436e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    }
3446e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3456e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    if (!readFrom(fd)) {
3466e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root        return false;
3476e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    }
3486e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3496e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    ftruncate(fd, mFooterStart);
3506e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3516e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    return true;
3526e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root}
3536e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
355