From 6e7ac5f0bceddf51947fbf3b376e278df0735603 Mon Sep 17 00:00:00 2001 From: Kenny Root Date: Mon, 19 Jul 2010 10:31:34 -0700 Subject: Initial tool for OBB manipulation Add "obbtool" host command for adding, removing, and querying Opaque Binary Blob (OBB) information from a file. Change-Id: Id2ac41e687ad2a500c362616d6738a8ae7e8f5c3 --- tools/obbtool/Android.mk | 30 +++++++ tools/obbtool/Main.cpp | 225 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 255 insertions(+) create mode 100644 tools/obbtool/Android.mk create mode 100644 tools/obbtool/Main.cpp (limited to 'tools/obbtool') diff --git a/tools/obbtool/Android.mk b/tools/obbtool/Android.mk new file mode 100644 index 0000000..b02c1cb --- /dev/null +++ b/tools/obbtool/Android.mk @@ -0,0 +1,30 @@ +# +# 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 diff --git a/tools/obbtool/Main.cpp b/tools/obbtool/Main.cpp new file mode 100644 index 0000000..2a9bf04 --- /dev/null +++ b/tools/obbtool/Main.cpp @@ -0,0 +1,225 @@ +/* + * 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 +#include + +#include +#include +#include + +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; +} -- cgit v1.1