1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2010 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License. 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <androidfw/ObbFile.h> 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/String8.h> 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <getopt.h> 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <stdio.h> 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <stdlib.h> 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <string.h> 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing namespace android; 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* gProgName = "obbtool"; 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char* gProgVersion = "1.0"; 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int wantUsage = 0; 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic int wantVersion = 0; 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define SALT_LEN 8 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define ADD_OPTS "n:v:os:" 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const struct option longopts[] = { 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski {"help", no_argument, &wantUsage, 1}, 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski {"version", no_argument, &wantVersion, 1}, 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* Args for "add" */ 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski {"name", required_argument, NULL, 'n'}, 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski {"version", required_argument, NULL, 'v'}, 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski {"overlay", optional_argument, NULL, 'o'}, 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski {"salt", required_argument, NULL, 's'}, 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski {NULL, 0, NULL, '\0'} 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass PackageInfo { 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic: 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PackageInfo() 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski : packageName(NULL) 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , packageVersion(-1) 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , overlay(false) 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , salted(false) 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memset(&salt, 0, sizeof(salt)); 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char* packageName; 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int packageVersion; 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool overlay; 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool salted; 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski unsigned char salt[SALT_LEN]; 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Print usage info. 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid usage(void) 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Opaque Binary Blob (OBB) Tool\n\n"); 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "Usage:\n"); 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " %s a[dd] [ OPTIONS ] FILENAME\n" 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " Adds an OBB signature to the file.\n\n", gProgName); 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " Options:\n" 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " -n <package name> sets the OBB package name (required)\n" 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " -v <OBB version> sets the OBB version (required)\n" 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " -o sets the OBB overlay flag\n" 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " -s <8 byte hex salt> sets the crypto key salt (if encrypted)\n" 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "\n"); 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " %s r[emove] FILENAME\n" 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " Removes the OBB signature from the file.\n\n", gProgName); 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " %s i[nfo] FILENAME\n" 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " Prints the OBB signature information of a file.\n\n", gProgName); 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 924eedc1018f46bf2ce1d8780a1fd6415700c4ee1dBrian Carlstromvoid doAdd(const char* filename, PackageInfo* info) { 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ObbFile *obb = new ObbFile(); 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (obb->readFrom(filename)) { 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s: OBB signature already present\n", filename); 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski obb->setPackageName(String8(info->packageName)); 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski obb->setVersion(info->packageVersion); 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski obb->setOverlay(info->overlay); 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (info->salted) { 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski obb->setSalt(info->salt, SALT_LEN); 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!obb->writeTo(filename)) { 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s: couldn't write OBB signature: %s\n", 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski filename, strerror(errno)); 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "OBB signature successfully written\n"); 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid doRemove(const char* filename) { 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ObbFile *obb = new ObbFile(); 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!obb->readFrom(filename)) { 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s: no OBB signature present\n", filename); 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!obb->removeFrom(filename)) { 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s: couldn't remove OBB signature\n", filename); 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "OBB signature successfully removed\n"); 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid doInfo(const char* filename) { 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ObbFile *obb = new ObbFile(); 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!obb->readFrom(filename)) { 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: %s: couldn't read OBB signature\n", filename); 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("OBB info for '%s':\n", filename); 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Package name: %s\n", obb->getPackageName().string()); 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" Version: %d\n", obb->getVersion()); 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" Flags: 0x%08x\n", obb->getFlags()); 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" Overlay: %s\n", obb->isOverlay() ? "true" : "false"); 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf(" Salt: "); 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t saltLen; 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const unsigned char* salt = obb->getSalt(&saltLen); 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (salt != NULL) { 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 0; i < SALT_LEN; i++) { 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("%02x", salt[i]); 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("\n"); 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("<empty>\n"); 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool fromHex(char h, unsigned char *b) { 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (h >= '0' && h <= '9') { 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *b = h - '0'; 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (h >= 'a' && h <= 'f') { 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *b = h - 'a' + 10; 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (h >= 'A' && h <= 'F') { 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *b = h - 'A' + 10; 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool hexToByte(char h1, char h2, unsigned char* b) { 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski unsigned char first, second; 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!fromHex(h1, &first)) return false; 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!fromHex(h2, &second)) return false; 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *b = (first << 4) | second; 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Parse args. 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiint main(int argc, char* const argv[]) 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int opt; 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int option_index = 0; 1854eedc1018f46bf2ce1d8780a1fd6415700c4ee1dBrian Carlstrom PackageInfo package_info; 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int result = 1; // pessimistically assume an error. 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (argc < 2) { 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski wantUsage = 1; 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((opt = getopt_long(argc, argv, ADD_OPTS, longopts, &option_index)) != -1) { 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski switch (opt) { 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 0: 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (longopts[option_index].flag) 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "'%s' requires an argument\n", longopts[option_index].name); 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski wantUsage = 1; 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 'n': 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package_info.packageName = optarg; 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 'v': { 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char* end; 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package_info.packageVersion = strtol(optarg, &end, 10); 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (*optarg == '\0' || *end != '\0') { 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: invalid version; should be integer!\n\n"); 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski wantUsage = 1; 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 'o': 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package_info.overlay = true; 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 's': 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strlen(optarg) != SALT_LEN * 2) { 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: salt must be 8 bytes in hex (e.g., ABCD65031337D00D)\n\n"); 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski wantUsage = 1; 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package_info.salted = true; 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski unsigned char b; 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 0, j = 0; i < SALT_LEN; i++, j+=2) { 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!hexToByte(optarg[j], optarg[j+1], &b)) { 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: salt must be in hex (e.g., ABCD65031337D00D)\n"); 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski wantUsage = 1; 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package_info.salt[i] = b; 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case '?': 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski wantUsage = 1; 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (wantVersion) { 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "%s %s\n", gProgName, gProgVersion); 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (wantUsage) { 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define CHECK_OP(name) \ 252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strncmp(op, name, opsize)) { \ 253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: unknown function '%s'!\n\n", op); \ 254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski wantUsage = 1; \ 255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; \ 256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (optind < argc) { 259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* op = argv[optind++]; 260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const int opsize = strlen(op); 261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (optind >= argc) { 263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: filename required!\n\n"); 264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski wantUsage = 1; 265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* filename = argv[optind++]; 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski switch (op[0]) { 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 'a': 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski CHECK_OP("add"); 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (package_info.packageName == NULL) { 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: arguments required 'packageName' and 'version'\n"); 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski doAdd(filename, &package_info); 278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 'r': 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski CHECK_OP("remove"); 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski doRemove(filename); 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 'i': 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski CHECK_OP("info"); 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski doInfo(filename); 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski default: 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: unknown command '%s'!\n\n", op); 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski wantUsage = 1; 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski goto bail; 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibail: 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (wantUsage) { 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski usage(); 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = 2; 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 302