File: | 3rdparty/vboot/futility/futility.c |
Warning: | line 230, column 14 Value stored to 'vstr' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Copyright 2013 The ChromiumOS Authors |
2 | * Use of this source code is governed by a BSD-style license that can be |
3 | * found in the LICENSE file. |
4 | */ |
5 | |
6 | #include <errno(*__errno_location ()).h> |
7 | #include <fcntl.h> |
8 | #include <getopt.h> |
9 | #include <limits.h> |
10 | #include <stdint.h> |
11 | #include <stdio.h> |
12 | #include <stdlib.h> |
13 | #include <string.h> |
14 | #include <sys/stat.h> |
15 | #include <unistd.h> |
16 | |
17 | #include "futility.h" |
18 | |
19 | /******************************************************************************/ |
20 | /* Logging stuff */ |
21 | |
22 | /* File to use for logging, if present */ |
23 | #define LOGFILE"/tmp/futility.log" "/tmp/futility.log" |
24 | |
25 | /* Normally logging will only happen if the logfile already exists. Uncomment |
26 | * this to force log file creation (and thus logging) always. */ |
27 | |
28 | /* #define FORCE_LOGGING_ON */ |
29 | |
30 | static int log_fd = -1; |
31 | const char *ft_print_header = NULL((void*)0); |
32 | const char *ft_print_header2 = NULL((void*)0); |
33 | |
34 | /* Write the string and a newline. Silently give up on errors */ |
35 | static void log_str(const char *prefix, const char *str) |
36 | { |
37 | int len, done, n; |
38 | |
39 | if (log_fd < 0) |
40 | return; |
41 | |
42 | if (!str) |
43 | str = "(NULL)"; |
44 | |
45 | if (prefix && *prefix) { |
46 | len = strlen(prefix); |
47 | for (done = 0; done < len; done += n) { |
48 | n = write(log_fd, prefix + done, len - done); |
49 | if (n < 0) |
50 | return; |
51 | } |
52 | } |
53 | |
54 | len = strlen(str); |
55 | if (len == 0) { |
56 | str = "(EMPTY)"; |
57 | len = strlen(str); |
58 | } |
59 | |
60 | for (done = 0; done < len; done += n) { |
61 | n = write(log_fd, str + done, len - done); |
62 | if (n < 0) |
63 | return; |
64 | } |
65 | |
66 | if (write(log_fd, "\n", 1) < 0) |
67 | return; |
68 | } |
69 | |
70 | static void log_close(void) |
71 | { |
72 | struct flock lock; |
73 | |
74 | if (log_fd >= 0) { |
75 | memset(&lock, 0, sizeof(lock)); |
76 | lock.l_type = F_UNLCK2; |
77 | lock.l_whence = SEEK_SET0; |
78 | if (fcntl(log_fd, F_SETLKW7, &lock)) |
79 | perror("Unable to unlock log file"); |
80 | |
81 | close(log_fd); |
82 | log_fd = -1; |
83 | } |
84 | } |
85 | |
86 | static void log_open(void) |
87 | { |
88 | struct flock lock; |
89 | int ret; |
90 | |
91 | #ifdef FORCE_LOGGING_ON |
92 | log_fd = open(LOGFILE"/tmp/futility.log", O_WRONLY01 | O_APPEND02000 | O_CREAT0100, 0666); |
93 | #else |
94 | log_fd = open(LOGFILE"/tmp/futility.log", O_WRONLY01 | O_APPEND02000); |
95 | #endif |
96 | if (log_fd < 0) { |
97 | |
98 | if (errno(*__errno_location ()) != EACCES13) |
99 | return; |
100 | |
101 | /* Permission problems should improve shortly ... */ |
102 | sleep(1); |
103 | log_fd = open(LOGFILE"/tmp/futility.log", O_WRONLY01 | O_APPEND02000 | O_CREAT0100, 0666); |
104 | if (log_fd < 0) /* Nope, they didn't */ |
105 | return; |
106 | } |
107 | |
108 | /* Let anyone have a turn */ |
109 | fchmod(log_fd, 0666); |
110 | |
111 | /* But only one at a time */ |
112 | memset(&lock, 0, sizeof(lock)); |
113 | lock.l_type = F_WRLCK1; |
114 | lock.l_whence = SEEK_END2; |
115 | |
116 | ret = fcntl(log_fd, F_SETLKW7, &lock); /* this blocks */ |
117 | if (ret < 0) |
118 | log_close(); |
119 | } |
120 | |
121 | static void log_args(int argc, char *argv[]) |
122 | { |
123 | int i; |
124 | ssize_t r; |
125 | pid_t parent; |
126 | char buf[80]; |
127 | FILE *fp; |
128 | char caller_buf[PATH_MAX4096]; |
129 | |
130 | log_open(); |
131 | |
132 | /* delimiter */ |
133 | log_str(NULL((void*)0), "##### LOG #####"); |
134 | |
135 | /* Can we tell who called us? */ |
136 | parent = getppid(); |
137 | snprintf(buf, sizeof(buf), "/proc/%d/exe", parent); |
138 | r = readlink(buf, caller_buf, sizeof(caller_buf) - 1); |
139 | if (r >= 0) { |
140 | caller_buf[r] = '\0'; |
141 | log_str("CALLER:", caller_buf); |
142 | } |
143 | |
144 | /* From where? */ |
145 | snprintf(buf, sizeof(buf), "/proc/%d/cwd", parent); |
146 | r = readlink(buf, caller_buf, sizeof(caller_buf) - 1); |
147 | if (r >= 0) { |
148 | caller_buf[r] = '\0'; |
149 | log_str("DIR:", caller_buf); |
150 | } |
151 | |
152 | /* And maybe the args? */ |
153 | snprintf(buf, sizeof(buf), "/proc/%d/cmdline", parent); |
154 | fp = fopen(buf, "r"); |
155 | if (fp) { |
156 | memset(caller_buf, 0, sizeof(caller_buf)); |
157 | r = fread(caller_buf, 1, sizeof(caller_buf) - 1, fp); |
158 | if (r > 0) { |
159 | char *s = caller_buf; |
160 | for (i = 0; i < r && *s; ) { |
161 | log_str("CMDLINE:", s); |
162 | while (i < r && *s) |
163 | i++, s++; |
164 | i++, s++; |
165 | } |
166 | } |
167 | fclose(fp); |
168 | } |
169 | |
170 | /* Now log the stuff about ourselves */ |
171 | for (i = 0; i < argc; i++) |
172 | log_str(NULL((void*)0), argv[i]); |
173 | |
174 | log_close(); |
175 | } |
176 | |
177 | /******************************************************************************/ |
178 | |
179 | static const char *const usage = "\n" |
180 | "Usage: " MYNAME"futility" " [options] COMMAND [args...]\n" |
181 | "\n" |
182 | "This is the unified firmware utility, which contains various of distinct\n" |
183 | "verified boot tools as subcommands.\n" |
184 | "\n" |
185 | "See the README file for more information about the available commands\n"; |
186 | |
187 | static const char *const options = |
188 | "Global options:\n" |
189 | "\n" |
190 | " --vb1 Use only vboot v1.0 binary formats\n" |
191 | " --vb21 Use only vboot v2.1 binary formats\n" |
192 | " --debug Be noisy about what's going on\n" |
193 | "\n"; |
194 | |
195 | static const struct futil_cmd_t *find_command(const char *name) |
196 | { |
197 | const struct futil_cmd_t *const *cmd; |
198 | |
199 | for (cmd = futil_cmds; *cmd; cmd++) |
200 | if (((*cmd)->version & vboot_version) && |
201 | !strcmp((*cmd)->name, name)) |
202 | return *cmd; |
203 | |
204 | return NULL((void*)0); |
205 | } |
206 | |
207 | static void list_commands(void) |
208 | { |
209 | const struct futil_cmd_t *const *cmd; |
210 | |
211 | for (cmd = futil_cmds; *cmd; cmd++) |
212 | if (vboot_version & (*cmd)->version) |
213 | printf(" %-20s %s\n", |
214 | (*cmd)->name, (*cmd)->shorthelp); |
215 | } |
216 | |
217 | static int run_command(const struct futil_cmd_t *cmd, int argc, char *argv[]) |
218 | { |
219 | int i; |
220 | VB2_DEBUG("\"%s\" ...\n", cmd->name)vb2ex_printf(__func__, "\"%s\" ...\n", cmd->name); |
221 | for (i = 0; i < argc; i++) |
222 | VB2_DEBUG(" argv[%d] = \"%s\"\n", i, argv[i])vb2ex_printf(__func__, " argv[%d] = \"%s\"\n", i, argv[i]); |
223 | |
224 | return cmd->handler(argc, argv); |
225 | } |
226 | |
227 | static int do_help(int argc, char *argv[]) |
228 | { |
229 | const struct futil_cmd_t *cmd; |
230 | const char *vstr = ""; |
Value stored to 'vstr' during its initialization is never read | |
231 | |
232 | /* Help about a known command? */ |
233 | if (argc > 1) { |
234 | cmd = find_command(argv[1]); |
235 | if (cmd) { |
236 | /* Let the command provide its own help */ |
237 | argv[0] = argv[1]; |
238 | argv[1] = (char *)"--help"; |
239 | return run_command(cmd, argc, argv); |
240 | } |
241 | } |
242 | |
243 | fputs(usage, stdoutstdout); |
244 | |
245 | if (vboot_version == VBOOT_VERSION_ALL) |
246 | fputs(options, stdoutstdout); |
247 | |
248 | switch (vboot_version) { |
249 | case VBOOT_VERSION_1_0: |
250 | vstr = "version 1.0 "; |
251 | break; |
252 | case VBOOT_VERSION_2_1: |
253 | vstr = "version 2.1 "; |
254 | break; |
255 | case VBOOT_VERSION_ALL: |
256 | vstr = ""; |
257 | break; |
258 | } |
259 | printf("The following %scommands are built-in:\n\n", vstr); |
260 | list_commands(); |
261 | printf("\nUse \"" MYNAME"futility" " help COMMAND\" for more information.\n\n"); |
262 | |
263 | return 0; |
264 | } |
265 | |
266 | DECLARE_FUTIL_COMMAND(help, do_help, VBOOT_VERSION_ALL,const struct futil_cmd_t __cmd_help = { .name = "help", .handler = do_help, .version = VBOOT_VERSION_ALL, .shorthelp = "Show a bit of help (you're looking at it)" , } |
267 | "Show a bit of help (you're looking at it)")const struct futil_cmd_t __cmd_help = { .name = "help", .handler = do_help, .version = VBOOT_VERSION_ALL, .shorthelp = "Show a bit of help (you're looking at it)" , }; |
268 | |
269 | static const char ver_help[] = |
270 | "Show the futility source revision and build date"; |
271 | static int do_version(int argc, char *argv[]) |
272 | { |
273 | if (argc > 1) |
274 | printf("%s - %s\n", argv[0], ver_help); |
275 | else |
276 | printf("%s\n", futility_version); |
277 | return 0; |
278 | } |
279 | |
280 | DECLARE_FUTIL_COMMAND(version, do_version, VBOOT_VERSION_ALL,const struct futil_cmd_t __cmd_version = { .name = "version", .handler = do_version, .version = VBOOT_VERSION_ALL, .shorthelp = ver_help, } |
281 | ver_help)const struct futil_cmd_t __cmd_version = { .name = "version", .handler = do_version, .version = VBOOT_VERSION_ALL, .shorthelp = ver_help, }; |
282 | |
283 | static char *simple_basename(char *str) |
284 | { |
285 | char *s = strrchr(str, '/'); |
286 | if (s) |
287 | s++; |
288 | else |
289 | s = str; |
290 | return s; |
291 | } |
292 | |
293 | /* Here we go */ |
294 | #define OPT_HELP1000 1000 |
295 | test_mockable__attribute__((weak)) |
296 | int main(int argc, char *argv[], char *envp[]) |
297 | { |
298 | char *progname; |
299 | const struct futil_cmd_t *cmd; |
300 | int i, errorcnt = 0; |
301 | int vb_ver = VBOOT_VERSION_ALL; |
302 | int helpind = 0; |
303 | struct option long_opts[] = { |
304 | {"debug", 0, &debugging_enabled, 1}, |
305 | {"vb1" , 0, &vb_ver, VBOOT_VERSION_1_0}, |
306 | {"vb21", 0, &vb_ver, VBOOT_VERSION_2_1}, |
307 | {"help", 0, 0, OPT_HELP1000}, |
308 | { 0, 0, 0, 0}, |
309 | }; |
310 | |
311 | log_args(argc, argv); |
312 | |
313 | /* How were we invoked? */ |
314 | progname = simple_basename(argv[0]); |
315 | |
316 | /* See if the program name is a command we recognize */ |
317 | cmd = find_command(progname); |
318 | if (cmd) { |
319 | /* Yep, just do that */ |
320 | return !!run_command(cmd, argc, argv); |
321 | } |
322 | |
323 | /* Parse the global options, stopping at the first non-option. */ |
324 | opterr = 0; /* quiet, you. */ |
325 | while ((i = getopt_long(argc, argv, "+:", long_opts, NULL((void*)0))) != -1) { |
326 | switch (i) { |
327 | case OPT_HELP1000: |
328 | /* Remember where we found this option */ |
329 | /* Note: this might be GNU-specific */ |
330 | helpind = optind - 1; |
331 | break; |
332 | case '?': |
333 | if (optopt) |
334 | fprintf(stderrstderr, "Unrecognized option: -%c\n", |
335 | optopt); |
336 | else |
337 | fprintf(stderrstderr, "Unrecognized option: %s\n", |
338 | argv[optind - 1]); |
339 | errorcnt++; |
340 | break; |
341 | case ':': |
342 | fprintf(stderrstderr, "Missing argument to -%c\n", optopt); |
343 | errorcnt++; |
344 | break; |
345 | case 0: /* handled option */ |
346 | break; |
347 | default: |
348 | FATAL("Unrecognized getopt output: %d\n", i)do { fprintf(stderr, "FATAL: %s: " "Unrecognized getopt output: %d\n" , __func__, i ); exit(1); } while (0); |
349 | } |
350 | } |
351 | vboot_version = vb_ver; |
352 | |
353 | /* |
354 | * Translate "--help" in the args to "help" as the first parameter, |
355 | * by rearranging argv[]. |
356 | */ |
357 | if (helpind) { |
358 | int j; |
359 | optind--; |
360 | for (j = helpind; j < optind; j++) |
361 | argv[j] = argv[j + 1]; |
362 | argv[j] = (char *)"help"; |
363 | } |
364 | |
365 | /* We require a command name. */ |
366 | if (errorcnt || argc == optind) { |
367 | do_help(1, argv); |
368 | return 1; |
369 | } |
370 | |
371 | /* For reasons I've forgotten, treat /blah/blah/CMD the same as CMD */ |
372 | argv[optind] = simple_basename(argv[optind]); |
373 | |
374 | /* Do we recognize the command? */ |
375 | cmd = find_command(argv[optind]); |
376 | if (cmd) { |
377 | /* Reset so commands can parse their own options */ |
378 | argc -= optind; |
379 | argv += optind; |
380 | optind = 0; |
381 | return !!run_command(cmd, argc, argv); |
382 | } |
383 | |
384 | /* Nope. We've no clue what we're being asked to do. */ |
385 | do_help(1, argv); |
386 | return 1; |
387 | } |