diff options
Diffstat (limited to 'tools/obbtool/Main.cpp')
| -rw-r--r-- | tools/obbtool/Main.cpp | 224 | 
1 files changed, 224 insertions, 0 deletions
| diff --git a/tools/obbtool/Main.cpp b/tools/obbtool/Main.cpp new file mode 100644 index 000000000000..49e077fc2af6 --- /dev/null +++ b/tools/obbtool/Main.cpp @@ -0,0 +1,224 @@ +/* + * 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:o" +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'}, +    {"overlay",    optional_argument, NULL, 'o'}, + +    {NULL, 0, NULL, '\0'} +}; + +struct package_info_t { +    char* packageName; +    int packageVersion; +    bool overlay; +}; + +/* + * 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); +    obb->setOverlay(info->overlay); + +    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()); +    printf("       Flags: 0x%08x\n", obb->getFlags()); +    printf("     Overlay: %s\n", obb->isOverlay() ? "true" : "false"); +} + +/* + * 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 'o': +            package_info.overlay = true; +            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; +} | 
