Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f5a8d96 authored by Kenny Root's avatar Kenny Root Committed by Android Git Automerger
Browse files

am 80328ba0: am 8ea71511: Merge "Initial tool for OBB manipulation" into gingerbread

Merge commit '80328ba0'

* commit '80328ba0':
  Initial tool for OBB manipulation
parents bf0cb26a 80328ba0
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ public:
    bool readFrom(int fd);
    bool writeTo(const char* filename);
    bool writeTo(int fd);
    bool removeFrom(const char* filename);
    bool removeFrom(int fd);

    const char* getFileName() const {
        return mFileName;
@@ -78,6 +80,8 @@ private:

    size_t mFileSize;

    size_t mFooterStart;

    unsigned char* mReadBuf;

    bool parseObbFile(int fd);
+39 −3
Original line number Diff line number Diff line
@@ -156,9 +156,9 @@ bool ObbFile::parseObbFile(int fd)
            return false;
        }

        if (footerSize < kFooterMinSize) {
            LOGW("claimed footer size is too small (%08zx; minimum size is 0x%x)\n",
                    footerSize, kFooterMinSize);
        if (footerSize < (kFooterMinSize - kFooterTagSize)) {
            LOGW("claimed footer size is too small (0x%zx; minimum size is 0x%x)\n",
                    footerSize, kFooterMinSize - kFooterTagSize);
            return false;
        }
    }
@@ -169,6 +169,8 @@ bool ObbFile::parseObbFile(int fd)
        return false;
    }

    mFooterStart = fileOffset;

    char* scanBuf = (char*)malloc(footerSize);
    if (scanBuf == NULL) {
        LOGW("couldn't allocate scanBuf: %s\n", strerror(errno));
@@ -293,4 +295,38 @@ bool ObbFile::writeTo(int fd)
    return true;
}

bool ObbFile::removeFrom(const char* filename)
{
    int fd;
    bool success = false;

    fd = ::open(filename, O_RDWR);
    if (fd < 0) {
        goto out;
    }
    success = removeFrom(fd);
    close(fd);

out:
    if (!success) {
        LOGW("failed to remove signature from %s: %s\n", filename, strerror(errno));
    }
    return success;
}

bool ObbFile::removeFrom(int fd)
{
    if (fd < 0) {
        return false;
    }

    if (!readFrom(fd)) {
        return false;
    }

    ftruncate(fd, mFooterStart);

    return true;
}

}
+30 −0
Original line number Diff line number Diff line
#
# Copyright 2010 The Android Open Source Project
#
# Opaque Binary Blob (OBB) Tool
#

# This tool is prebuilt if we're doing an app-only build.
ifeq ($(TARGET_BUILD_APPS),)

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
	Main.cpp

#LOCAL_C_INCLUDES +=

LOCAL_STATIC_LIBRARIES := \
	libutils \
	libcutils

ifeq ($(HOST_OS),linux)
LOCAL_LDLIBS += -lpthread
endif

LOCAL_MODULE := obbtool

include $(BUILD_HOST_EXECUTABLE)

endif # TARGET_BUILD_APPS

tools/obbtool/Main.cpp

0 → 100644
+225 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <utils/ObbFile.h>
#include <utils/String8.h>

#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>

using namespace android;

static const char* gProgName = "obbtool";
static const char* gProgVersion = "1.0";

static int wantUsage = 0;
static int wantVersion = 0;

#define ADD_OPTS "n:v:f:c:"
static const struct option longopts[] = {
    {"help",       no_argument, &wantUsage,   1},
    {"version",    no_argument, &wantVersion, 1},

    /* Args for "add" */
    {"name",       required_argument, NULL, 'n'},
    {"version",    required_argument, NULL, 'v'},
    {"filesystem", required_argument, NULL, 'f'},
    {"crypto",     required_argument, NULL, 'c'},

    {NULL, 0, NULL, '\0'}
};

struct package_info_t {
    char* packageName;
    int packageVersion;
    char* filesystem;
    char* crypto;
};

/*
 * Print usage info.
 */
void usage(void)
{
    fprintf(stderr, "Opaque Binary Blob (OBB) Tool\n\n");
    fprintf(stderr, "Usage:\n");
    fprintf(stderr,
        " %s a[dd] [ OPTIONS ] FILENAME\n"
        "   Adds an OBB signature to the file.\n\n", gProgName);
    fprintf(stderr,
        " %s r[emove] FILENAME\n"
        "   Removes the OBB signature from the file.\n\n", gProgName);
    fprintf(stderr,
        " %s i[nfo] FILENAME\n"
        "   Prints the OBB signature information of a file.\n\n", gProgName);
}

void doAdd(const char* filename, struct package_info_t* info) {
    ObbFile *obb = new ObbFile();
    if (obb->readFrom(filename)) {
        fprintf(stderr, "ERROR: %s: OBB signature already present\n", filename);
        return;
    }

    obb->setPackageName(String8(info->packageName));
    obb->setVersion(info->packageVersion);

    if (!obb->writeTo(filename)) {
        fprintf(stderr, "ERROR: %s: couldn't write OBB signature: %s\n",
                filename, strerror(errno));
        return;
    }

    fprintf(stderr, "OBB signature successfully written\n");
}

void doRemove(const char* filename) {
    ObbFile *obb = new ObbFile();
    if (!obb->readFrom(filename)) {
        fprintf(stderr, "ERROR: %s: no OBB signature present\n", filename);
        return;
    }

    if (!obb->removeFrom(filename)) {
        fprintf(stderr, "ERROR: %s: couldn't remove OBB signature\n", filename);
        return;
    }

    fprintf(stderr, "OBB signature successfully removed\n");
}

void doInfo(const char* filename) {
    ObbFile *obb = new ObbFile();
    if (!obb->readFrom(filename)) {
        fprintf(stderr, "ERROR: %s: couldn't read OBB signature\n", filename);
        return;
    }

    printf("OBB info for '%s':\n", filename);
    printf("Package name: %s\n", obb->getPackageName().string());
    printf("     Version: %d\n", obb->getVersion());
}

/*
 * Parse args.
 */
int main(int argc, char* const argv[])
{
    const char *prog = argv[0];
    struct options *options;
    int opt;
    int option_index = 0;
    struct package_info_t package_info;

    int result = 1;    // pessimistically assume an error.

    if (argc < 2) {
        wantUsage = 1;
        goto bail;
    }

    while ((opt = getopt_long(argc, argv, ADD_OPTS, longopts, &option_index)) != -1) {
        switch (opt) {
        case 0:
            if (longopts[option_index].flag)
                break;
            fprintf(stderr, "'%s' requires an argument\n", longopts[option_index].name);
            wantUsage = 1;
            goto bail;
        case 'n':
            package_info.packageName = optarg;
            break;
        case 'v':
            char *end;
            package_info.packageVersion = strtol(optarg, &end, 10);
            if (*optarg == '\0' || *end != '\0') {
                fprintf(stderr, "ERROR: invalid version; should be integer!\n\n");
                wantUsage = 1;
                goto bail;
            }
            break;
        case 'f':
            package_info.filesystem = optarg;
            break;
        case 'c':
            package_info.crypto = optarg;
            break;
        case '?':
            wantUsage = 1;
            goto bail;
        }
    }

    if (wantVersion) {
        fprintf(stderr, "%s %s\n", gProgName, gProgVersion);
    }

    if (wantUsage) {
        goto bail;
    }

#define CHECK_OP(name) \
    if (strncmp(op, name, opsize)) { \
        fprintf(stderr, "ERROR: unknown function '%s'!\n\n", op); \
        wantUsage = 1; \
        goto bail; \
    }

    if (optind < argc) {
        const char* op = argv[optind++];
        const int opsize = strlen(op);

        if (optind >= argc) {
            fprintf(stderr, "ERROR: filename required!\n\n");
            wantUsage = 1;
            goto bail;
        }

        const char* filename = argv[optind++];

        switch (op[0]) {
        case 'a':
            CHECK_OP("add");
            if (package_info.packageName == NULL) {
                fprintf(stderr, "ERROR: arguments required 'packageName' and 'version'\n");
                goto bail;
            }
            doAdd(filename, &package_info);
            break;
        case 'r':
            CHECK_OP("remove");
            doRemove(filename);
            break;
        case 'i':
            CHECK_OP("info");
            doInfo(filename);
            break;
        default:
            fprintf(stderr, "ERROR: unknown command '%s'!\n\n", op);
            wantUsage = 1;
            goto bail;
        }
    }

bail:
    if (wantUsage) {
        usage();
        result = 2;
    }

    return result;
}