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