blob: 2a9bf04201024d0ef922596aed02e53988889f25 [file] [log] [blame]
Kenny Root6e7ac5f2010-07-19 10:31:34 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <utils/ObbFile.h>
18#include <utils/String8.h>
19
20#include <getopt.h>
21#include <stdio.h>
22#include <stdlib.h>
23
24using namespace android;
25
26static const char* gProgName = "obbtool";
27static const char* gProgVersion = "1.0";
28
29static int wantUsage = 0;
30static int wantVersion = 0;
31
32#define ADD_OPTS "n:v:f:c:"
33static const struct option longopts[] = {
34 {"help", no_argument, &wantUsage, 1},
35 {"version", no_argument, &wantVersion, 1},
36
37 /* Args for "add" */
38 {"name", required_argument, NULL, 'n'},
39 {"version", required_argument, NULL, 'v'},
40 {"filesystem", required_argument, NULL, 'f'},
41 {"crypto", required_argument, NULL, 'c'},
42
43 {NULL, 0, NULL, '\0'}
44};
45
46struct package_info_t {
47 char* packageName;
48 int packageVersion;
49 char* filesystem;
50 char* crypto;
51};
52
53/*
54 * Print usage info.
55 */
56void usage(void)
57{
58 fprintf(stderr, "Opaque Binary Blob (OBB) Tool\n\n");
59 fprintf(stderr, "Usage:\n");
60 fprintf(stderr,
61 " %s a[dd] [ OPTIONS ] FILENAME\n"
62 " Adds an OBB signature to the file.\n\n", gProgName);
63 fprintf(stderr,
64 " %s r[emove] FILENAME\n"
65 " Removes the OBB signature from the file.\n\n", gProgName);
66 fprintf(stderr,
67 " %s i[nfo] FILENAME\n"
68 " Prints the OBB signature information of a file.\n\n", gProgName);
69}
70
71void doAdd(const char* filename, struct package_info_t* info) {
72 ObbFile *obb = new ObbFile();
73 if (obb->readFrom(filename)) {
74 fprintf(stderr, "ERROR: %s: OBB signature already present\n", filename);
75 return;
76 }
77
78 obb->setPackageName(String8(info->packageName));
79 obb->setVersion(info->packageVersion);
80
81 if (!obb->writeTo(filename)) {
82 fprintf(stderr, "ERROR: %s: couldn't write OBB signature: %s\n",
83 filename, strerror(errno));
84 return;
85 }
86
87 fprintf(stderr, "OBB signature successfully written\n");
88}
89
90void doRemove(const char* filename) {
91 ObbFile *obb = new ObbFile();
92 if (!obb->readFrom(filename)) {
93 fprintf(stderr, "ERROR: %s: no OBB signature present\n", filename);
94 return;
95 }
96
97 if (!obb->removeFrom(filename)) {
98 fprintf(stderr, "ERROR: %s: couldn't remove OBB signature\n", filename);
99 return;
100 }
101
102 fprintf(stderr, "OBB signature successfully removed\n");
103}
104
105void doInfo(const char* filename) {
106 ObbFile *obb = new ObbFile();
107 if (!obb->readFrom(filename)) {
108 fprintf(stderr, "ERROR: %s: couldn't read OBB signature\n", filename);
109 return;
110 }
111
112 printf("OBB info for '%s':\n", filename);
113 printf("Package name: %s\n", obb->getPackageName().string());
114 printf(" Version: %d\n", obb->getVersion());
115}
116
117/*
118 * Parse args.
119 */
120int main(int argc, char* const argv[])
121{
122 const char *prog = argv[0];
123 struct options *options;
124 int opt;
125 int option_index = 0;
126 struct package_info_t package_info;
127
128 int result = 1; // pessimistically assume an error.
129
130 if (argc < 2) {
131 wantUsage = 1;
132 goto bail;
133 }
134
135 while ((opt = getopt_long(argc, argv, ADD_OPTS, longopts, &option_index)) != -1) {
136 switch (opt) {
137 case 0:
138 if (longopts[option_index].flag)
139 break;
140 fprintf(stderr, "'%s' requires an argument\n", longopts[option_index].name);
141 wantUsage = 1;
142 goto bail;
143 case 'n':
144 package_info.packageName = optarg;
145 break;
146 case 'v':
147 char *end;
148 package_info.packageVersion = strtol(optarg, &end, 10);
149 if (*optarg == '\0' || *end != '\0') {
150 fprintf(stderr, "ERROR: invalid version; should be integer!\n\n");
151 wantUsage = 1;
152 goto bail;
153 }
154 break;
155 case 'f':
156 package_info.filesystem = optarg;
157 break;
158 case 'c':
159 package_info.crypto = optarg;
160 break;
161 case '?':
162 wantUsage = 1;
163 goto bail;
164 }
165 }
166
167 if (wantVersion) {
168 fprintf(stderr, "%s %s\n", gProgName, gProgVersion);
169 }
170
171 if (wantUsage) {
172 goto bail;
173 }
174
175#define CHECK_OP(name) \
176 if (strncmp(op, name, opsize)) { \
177 fprintf(stderr, "ERROR: unknown function '%s'!\n\n", op); \
178 wantUsage = 1; \
179 goto bail; \
180 }
181
182 if (optind < argc) {
183 const char* op = argv[optind++];
184 const int opsize = strlen(op);
185
186 if (optind >= argc) {
187 fprintf(stderr, "ERROR: filename required!\n\n");
188 wantUsage = 1;
189 goto bail;
190 }
191
192 const char* filename = argv[optind++];
193
194 switch (op[0]) {
195 case 'a':
196 CHECK_OP("add");
197 if (package_info.packageName == NULL) {
198 fprintf(stderr, "ERROR: arguments required 'packageName' and 'version'\n");
199 goto bail;
200 }
201 doAdd(filename, &package_info);
202 break;
203 case 'r':
204 CHECK_OP("remove");
205 doRemove(filename);
206 break;
207 case 'i':
208 CHECK_OP("info");
209 doInfo(filename);
210 break;
211 default:
212 fprintf(stderr, "ERROR: unknown command '%s'!\n\n", op);
213 wantUsage = 1;
214 goto bail;
215 }
216 }
217
218bail:
219 if (wantUsage) {
220 usage();
221 result = 2;
222 }
223
224 return result;
225}