16e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root/* 26e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * Copyright (C) 2010 The Android Open Source Project 36e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * 46e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 56e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * you may not use this file except in compliance with the License. 66e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * You may obtain a copy of the License at 76e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * 86e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * http://www.apache.org/licenses/LICENSE-2.0 96e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * 106e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * Unless required by applicable law or agreed to in writing, software 116e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * distributed under the License is distributed on an "AS IS" BASIS, 126e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * See the License for the specific language governing permissions and 146e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * limitations under the License. 156e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root */ 166e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 17b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ObbFile.h> 186e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root#include <utils/String8.h> 196e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 206e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root#include <getopt.h> 216e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root#include <stdio.h> 226e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root#include <stdlib.h> 233b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#include <string.h> 246e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 256e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootusing namespace android; 266e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 276e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootstatic const char* gProgName = "obbtool"; 286e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootstatic const char* gProgVersion = "1.0"; 296e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 306e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootstatic int wantUsage = 0; 316e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootstatic int wantVersion = 0; 326e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 333b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#define SALT_LEN 8 343b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root 353b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root#define ADD_OPTS "n:v:os:" 366e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootstatic const struct option longopts[] = { 376e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root {"help", no_argument, &wantUsage, 1}, 386e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root {"version", no_argument, &wantVersion, 1}, 396e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 406e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root /* Args for "add" */ 416e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root {"name", required_argument, NULL, 'n'}, 426e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root {"version", required_argument, NULL, 'v'}, 4302ca31fbae9f35dd30f79de6927fae11b549391aKenny Root {"overlay", optional_argument, NULL, 'o'}, 443b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root {"salt", required_argument, NULL, 's'}, 456e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 466e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root {NULL, 0, NULL, '\0'} 476e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root}; 486e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 493b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Rootclass PackageInfo { 503b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Rootpublic: 513b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root PackageInfo() 523b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root : packageName(NULL) 533b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root , packageVersion(-1) 543b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root , overlay(false) 553b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root , salted(false) 563b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root { 573b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root memset(&salt, 0, sizeof(salt)); 583b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } 593b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root 606e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root char* packageName; 616e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root int packageVersion; 6202ca31fbae9f35dd30f79de6927fae11b549391aKenny Root bool overlay; 633b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root bool salted; 643b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root unsigned char salt[SALT_LEN]; 656e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root}; 666e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 676e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root/* 686e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * Print usage info. 696e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root */ 706e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootvoid usage(void) 716e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root{ 726e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "Opaque Binary Blob (OBB) Tool\n\n"); 736e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "Usage:\n"); 746e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, 756e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root " %s a[dd] [ OPTIONS ] FILENAME\n" 766e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root " Adds an OBB signature to the file.\n\n", gProgName); 776e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, 783b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root " Options:\n" 793b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root " -n <package name> sets the OBB package name (required)\n" 803b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root " -v <OBB version> sets the OBB version (required)\n" 813b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root " -o sets the OBB overlay flag\n" 823b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root " -s <8 byte hex salt> sets the crypto key salt (if encrypted)\n" 833b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root "\n"); 843b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root fprintf(stderr, 856e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root " %s r[emove] FILENAME\n" 866e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root " Removes the OBB signature from the file.\n\n", gProgName); 876e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, 886e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root " %s i[nfo] FILENAME\n" 896e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root " Prints the OBB signature information of a file.\n\n", gProgName); 906e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root} 916e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 923b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Rootvoid doAdd(const char* filename, struct PackageInfo* info) { 936e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root ObbFile *obb = new ObbFile(); 946e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (obb->readFrom(filename)) { 956e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "ERROR: %s: OBB signature already present\n", filename); 966e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return; 976e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 986e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 996e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root obb->setPackageName(String8(info->packageName)); 1006e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root obb->setVersion(info->packageVersion); 10102ca31fbae9f35dd30f79de6927fae11b549391aKenny Root obb->setOverlay(info->overlay); 1023b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root if (info->salted) { 1033b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root obb->setSalt(info->salt, SALT_LEN); 1043b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } 1056e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1066e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (!obb->writeTo(filename)) { 1076e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "ERROR: %s: couldn't write OBB signature: %s\n", 1086e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root filename, strerror(errno)); 1096e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return; 1106e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 1116e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1126e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "OBB signature successfully written\n"); 1136e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root} 1146e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1156e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootvoid doRemove(const char* filename) { 1166e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root ObbFile *obb = new ObbFile(); 1176e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (!obb->readFrom(filename)) { 1186e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "ERROR: %s: no OBB signature present\n", filename); 1196e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return; 1206e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 1216e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1226e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (!obb->removeFrom(filename)) { 1236e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "ERROR: %s: couldn't remove OBB signature\n", filename); 1246e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return; 1256e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 1266e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1276e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "OBB signature successfully removed\n"); 1286e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root} 1296e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1306e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootvoid doInfo(const char* filename) { 1316e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root ObbFile *obb = new ObbFile(); 1326e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (!obb->readFrom(filename)) { 1336e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "ERROR: %s: couldn't read OBB signature\n", filename); 1346e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return; 1356e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 1366e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1376e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root printf("OBB info for '%s':\n", filename); 1386e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root printf("Package name: %s\n", obb->getPackageName().string()); 1396e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root printf(" Version: %d\n", obb->getVersion()); 14002ca31fbae9f35dd30f79de6927fae11b549391aKenny Root printf(" Flags: 0x%08x\n", obb->getFlags()); 14102ca31fbae9f35dd30f79de6927fae11b549391aKenny Root printf(" Overlay: %s\n", obb->isOverlay() ? "true" : "false"); 1423b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root printf(" Salt: "); 1433b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root 1443b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root size_t saltLen; 1453b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root const unsigned char* salt = obb->getSalt(&saltLen); 1463b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root if (salt != NULL) { 1473b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root for (int i = 0; i < SALT_LEN; i++) { 1483b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root printf("%02x", salt[i]); 1493b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } 1503b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root printf("\n"); 1513b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } else { 1523b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root printf("<empty>\n"); 1533b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } 1543b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root} 1553b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root 1563b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Rootbool fromHex(char h, unsigned char *b) { 1573b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root if (h >= '0' && h <= '9') { 1583b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root *b = h - '0'; 1593b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root return true; 1603b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } else if (h >= 'a' && h <= 'f') { 1613b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root *b = h - 'a' + 10; 1623b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root return true; 1633b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } else if (h >= 'A' && h <= 'F') { 1643b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root *b = h - 'A' + 10; 1653b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root return true; 1663b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } 1673b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root return false; 1683b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root} 1693b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root 1703b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Rootbool hexToByte(char h1, char h2, unsigned char* b) { 1713b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root unsigned char first, second; 1723b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root if (!fromHex(h1, &first)) return false; 1733b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root if (!fromHex(h2, &second)) return false; 1743b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root *b = (first << 4) | second; 1753b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root return true; 1766e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root} 1776e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1786e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root/* 1796e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root * Parse args. 1806e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root */ 1816e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootint main(int argc, char* const argv[]) 1826e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root{ 1836e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root int opt; 1846e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root int option_index = 0; 1853b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root struct PackageInfo package_info; 1866e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1876e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root int result = 1; // pessimistically assume an error. 1886e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1896e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (argc < 2) { 1906e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root wantUsage = 1; 1916e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto bail; 1926e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 1936e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 1946e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root while ((opt = getopt_long(argc, argv, ADD_OPTS, longopts, &option_index)) != -1) { 1956e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root switch (opt) { 1966e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root case 0: 1976e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (longopts[option_index].flag) 1986e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root break; 1996e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "'%s' requires an argument\n", longopts[option_index].name); 2006e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root wantUsage = 1; 2016e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto bail; 2026e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root case 'n': 2036e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root package_info.packageName = optarg; 2046e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root break; 20502ca31fbae9f35dd30f79de6927fae11b549391aKenny Root case 'v': { 2063b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root char* end; 2076e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root package_info.packageVersion = strtol(optarg, &end, 10); 2086e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (*optarg == '\0' || *end != '\0') { 2096e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "ERROR: invalid version; should be integer!\n\n"); 2106e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root wantUsage = 1; 2116e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto bail; 2126e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2136e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root break; 21402ca31fbae9f35dd30f79de6927fae11b549391aKenny Root } 21502ca31fbae9f35dd30f79de6927fae11b549391aKenny Root case 'o': 21602ca31fbae9f35dd30f79de6927fae11b549391aKenny Root package_info.overlay = true; 2176e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root break; 2183b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root case 's': 2193b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root if (strlen(optarg) != SALT_LEN * 2) { 2203b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root fprintf(stderr, "ERROR: salt must be 8 bytes in hex (e.g., ABCD65031337D00D)\n\n"); 2213b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root wantUsage = 1; 2223b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root goto bail; 2233b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } 2243b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root 2253b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root package_info.salted = true; 2263b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root 2273b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root unsigned char b; 2283b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root for (int i = 0, j = 0; i < SALT_LEN; i++, j+=2) { 2293b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root if (!hexToByte(optarg[j], optarg[j+1], &b)) { 2303b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root fprintf(stderr, "ERROR: salt must be in hex (e.g., ABCD65031337D00D)\n"); 2313b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root wantUsage = 1; 2323b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root goto bail; 2333b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } 2343b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root package_info.salt[i] = b; 2353b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root } 2363b1abba6bbc895d63da3e82e9b158c01bd12edddKenny Root break; 2376e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root case '?': 2386e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root wantUsage = 1; 2396e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto bail; 2406e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2416e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2426e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 2436e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (wantVersion) { 2446e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "%s %s\n", gProgName, gProgVersion); 2456e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2466e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 2476e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (wantUsage) { 2486e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto bail; 2496e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2506e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 2516e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root#define CHECK_OP(name) \ 2526e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (strncmp(op, name, opsize)) { \ 2536e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "ERROR: unknown function '%s'!\n\n", op); \ 2546e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root wantUsage = 1; \ 2556e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto bail; \ 2566e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2576e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 2586e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (optind < argc) { 2596e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root const char* op = argv[optind++]; 2606e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root const int opsize = strlen(op); 2616e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 2626e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (optind >= argc) { 2636e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "ERROR: filename required!\n\n"); 2646e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root wantUsage = 1; 2656e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto bail; 2666e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2676e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 2686e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root const char* filename = argv[optind++]; 2696e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 2706e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root switch (op[0]) { 2716e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root case 'a': 2726e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root CHECK_OP("add"); 2736e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (package_info.packageName == NULL) { 2746e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "ERROR: arguments required 'packageName' and 'version'\n"); 2756e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto bail; 2766e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2776e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root doAdd(filename, &package_info); 2786e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root break; 2796e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root case 'r': 2806e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root CHECK_OP("remove"); 2816e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root doRemove(filename); 2826e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root break; 2836e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root case 'i': 2846e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root CHECK_OP("info"); 2856e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root doInfo(filename); 2866e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root break; 2876e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root default: 2886e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root fprintf(stderr, "ERROR: unknown command '%s'!\n\n", op); 2896e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root wantUsage = 1; 2906e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root goto bail; 2916e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2926e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2936e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 2946e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Rootbail: 2956e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root if (wantUsage) { 2966e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root usage(); 2976e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root result = 2; 2986e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root } 2996e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root 3006e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root return result; 3016e7ac5f0bceddf51947fbf3b376e278df0735603Kenny Root} 302