ObbFile.cpp revision 6e7ac5f0bceddf51947fbf3b376e278df0735603
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
1596e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root        if (footerSize < (kFooterMinSize - kFooterTagSize)) {
1606e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root            LOGW("claimed footer size is too small (0x%zx; minimum size is 0x%x)\n",
1616e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root                    footerSize, kFooterMinSize - kFooterTagSize);
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
1726e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    mFooterStart = fileOffset;
1736e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
17487315aa1f0b64efcef416628215be89851cc4736Kenny Root    char* scanBuf = (char*)malloc(footerSize);
1757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (scanBuf == NULL) {
1767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("couldn't allocate scanBuf: %s\n", strerror(errno));
1777cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
1787cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
1797cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
18087315aa1f0b64efcef416628215be89851cc4736Kenny Root    actual = TEMP_FAILURE_RETRY(read(fd, scanBuf, footerSize));
1817cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    // readAmount is guaranteed to be less than kMaxBufSize
18287315aa1f0b64efcef416628215be89851cc4736Kenny Root    if (actual != (ssize_t)footerSize) {
1837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGI("couldn't read ObbFile footer: %s\n", strerror(errno));
1847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        free(scanBuf);
1857cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
1867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
1877cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1887cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#ifdef DEBUG
18987315aa1f0b64efcef416628215be89851cc4736Kenny Root    for (int i = 0; i < footerSize; ++i) {
1907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGI("char: 0x%02x", scanBuf[i]);
1917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
1927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root#endif
1937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
1947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    uint32_t sigVersion = get4LE((unsigned char*)scanBuf);
1957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (sigVersion != kSigVersion) {
1967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("Unsupported ObbFile version %d\n", sigVersion);
1977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        free(scanBuf);
1987cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
1997cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2007cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2017cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset);
2027cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2037cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
2047cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (packageNameLen <= 0
2057cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root            || packageNameLen > (footerSize - kPackageNameOffset)) {
20687315aa1f0b64efcef416628215be89851cc4736Kenny Root        LOGW("bad ObbFile package name length (0x%04x; 0x%04x possible)\n",
20787315aa1f0b64efcef416628215be89851cc4736Kenny Root                packageNameLen, footerSize - kPackageNameOffset);
2087cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        free(scanBuf);
2097cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2107cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2117cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2127cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    char* packageName = reinterpret_cast<char*>(scanBuf + kPackageNameOffset);
2137cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    mPackageName = String8(const_cast<char*>(packageName), packageNameLen);
2147cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2157cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    free(scanBuf);
21687315aa1f0b64efcef416628215be89851cc4736Kenny Root
21787315aa1f0b64efcef416628215be89851cc4736Kenny Root#ifdef DEBUG
21887315aa1f0b64efcef416628215be89851cc4736Kenny Root    LOGI("Obb scan succeeded: packageName=%s, version=%d\n", mPackageName.string(), mVersion);
21987315aa1f0b64efcef416628215be89851cc4736Kenny Root#endif
22087315aa1f0b64efcef416628215be89851cc4736Kenny Root
2217cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    return true;
2227cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
2237cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2247cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::writeTo(const char* filename)
2257cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{
2267cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    int fd;
2277cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    bool success = false;
2287cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2297cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    fd = ::open(filename, O_WRONLY);
2307cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (fd < 0) {
2317cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        goto out;
2327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2337cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    success = writeTo(fd);
2347cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    close(fd);
2357cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2367cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootout:
2377cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (!success) {
2387cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("failed to write to %s: %s\n", filename, strerror(errno));
2397cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2407cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    return success;
2417cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
2427cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2437cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Rootbool ObbFile::writeTo(int fd)
2447cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root{
2457cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (fd < 0) {
2467cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2477cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2487cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
24987315aa1f0b64efcef416628215be89851cc4736Kenny Root    my_lseek64(fd, 0, SEEK_END);
25087315aa1f0b64efcef416628215be89851cc4736Kenny Root
2517cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (mPackageName.size() == 0 || mVersion == -1) {
2527cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("tried to write uninitialized ObbFile data");
2537cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2547cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2557cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2567cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    unsigned char intBuf[sizeof(uint32_t)+1];
2577cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    memset(&intBuf, 0, sizeof(intBuf));
2587cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2597cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    put4LE(intBuf, kSigVersion);
2607cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
2617cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("couldn't write signature version: %s", strerror(errno));
2627cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2637cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2647cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2657cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    put4LE(intBuf, mVersion);
2667cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
2677cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("couldn't write package version");
2687cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2697cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2707cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2717cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    size_t packageNameLen = mPackageName.size();
2727cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    put4LE(intBuf, packageNameLen);
2737cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
2747cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("couldn't write package name length: %s", strerror(errno));
2757cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2767cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2777cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2787cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, mPackageName.string(), packageNameLen) != (ssize_t)packageNameLen) {
2797cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("couldn't write package name: %s", strerror(errno));
2807cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2817cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2827cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2837cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    put4LE(intBuf, 3*sizeof(uint32_t) + packageNameLen);
2847cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
2857cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("couldn't write footer size: %s", strerror(errno));
2867cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2877cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2887cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2897cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    put4LE(intBuf, kSignature);
2907cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
2917cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        LOGW("couldn't write footer magic signature: %s", strerror(errno));
2927cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root        return false;
2937cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    }
2947cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2957cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root    return true;
2967cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
2977cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root
2986e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootbool ObbFile::removeFrom(const char* filename)
2996e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root{
3006e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    int fd;
3016e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    bool success = false;
3026e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3036e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    fd = ::open(filename, O_RDWR);
3046e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    if (fd < 0) {
3056e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root        goto out;
3066e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    }
3076e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    success = removeFrom(fd);
3086e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    close(fd);
3096e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3106e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootout:
3116e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    if (!success) {
3126e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root        LOGW("failed to remove signature from %s: %s\n", filename, strerror(errno));
3136e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    }
3146e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    return success;
3156e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root}
3166e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3176e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootbool ObbFile::removeFrom(int fd)
3186e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root{
3196e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    if (fd < 0) {
3206e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root        return false;
3216e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    }
3226e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3236e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    if (!readFrom(fd)) {
3246e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root        return false;
3256e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    }
3266e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3276e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    ftruncate(fd, mFooterStart);
3286e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3296e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root    return true;
3306e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root}
3316e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root
3327cee34a051eb0087322c8b965e498f88b1aa52d3Kenny Root}
333