blob: 6696bb48308cd1f95ab1d2131926492d9c393318 [file] [log] [blame]
Bill Richardson25593382015-01-30 12:22:28 -08001/*
2 * Copyright 2015 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7#include <errno.h>
8#include <fcntl.h>
9#include <stdint.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/stat.h>
14#include <sys/types.h>
15#include <unistd.h>
16
17#include "file_type.h"
18#include "futility.h"
19#include "gbb_header.h"
20
21/* Human-readable strings */
22static const char * const type_strings[] = {
23 "unknown",
24 "VbPublicKey",
25 "VbKeyBlock",
26 "VbFirmwarePreamble",
27 "GBB",
28 "Chrome OS BIOS image",
29 "Cr-48 Chrome OS BIOS image",
30 "VbKernelPreamble",
31 "raw firmware",
32 "raw kernel",
33 "chromiumos disk image",
Bill Richardson4805f182015-01-30 22:21:10 -080034 "VbPrivateKey",
Bill Richardson25593382015-01-30 12:22:28 -080035};
36BUILD_ASSERT(ARRAY_SIZE(type_strings) == NUM_FILE_TYPES);
37
38const char * const futil_file_type_str(enum futil_file_type type)
39{
David Riley05987b12015-02-05 19:22:49 -080040 if ((int) type < 0 || type >= NUM_FILE_TYPES)
Bill Richardson25593382015-01-30 12:22:28 -080041 type = FILE_TYPE_UNKNOWN;
42
43 return type_strings[type];
44}
45
46/* Try these in order so we recognize the larger objects first */
47enum futil_file_type (*recognizers[])(uint8_t *buf, uint32_t len) = {
48 &recognize_gpt,
49 &recognize_bios_image,
50 &recognize_gbb,
51 &recognize_vblock1,
Bill Richardson4805f182015-01-30 22:21:10 -080052 &recognize_privkey,
Bill Richardson25593382015-01-30 12:22:28 -080053};
54
55/* Try to figure out what we're looking at */
56enum futil_file_type futil_file_type_buf(uint8_t *buf, uint32_t len)
57{
58 enum futil_file_type type;
59 int i;
60
61 for (i = 0; i < ARRAY_SIZE(recognizers); i++) {
62 type = recognizers[i](buf, len);
63 if (type != FILE_TYPE_UNKNOWN)
64 return type;
65 }
66
67 return FILE_TYPE_UNKNOWN;
68}
69
70enum futil_file_err futil_file_type(const char *filename,
71 enum futil_file_type *type)
72{
73 int ifd;
74 uint8_t *buf;
75 uint32_t buf_len;
76 struct stat sb;
77 enum futil_file_err err = FILE_ERR_NONE;
78
79 *type = FILE_TYPE_UNKNOWN;
80
81 ifd = open(filename, O_RDONLY);
82 if (ifd < 0) {
83 fprintf(stderr, "Can't open %s: %s\n",
84 filename, strerror(errno));
85 return FILE_ERR_OPEN;
86 }
87
88 if (0 != fstat(ifd, &sb)) {
89 fprintf(stderr, "Can't stat input file: %s\n",
90 strerror(errno));
91 return FILE_ERR_STAT;
92 }
93
94 if (S_ISREG(sb.st_mode) || S_ISBLK(sb.st_mode)) {
95 err = futil_map_file(ifd, MAP_RO, &buf, &buf_len);
96 if (err) {
97 close(ifd);
98 return err;
99 }
100
101 *type = futil_file_type_buf(buf, buf_len);
102
103 err = futil_unmap_file(ifd, MAP_RO, buf, buf_len);
104 if (err) {
105 close(ifd);
106 return err;
107 }
108 } else if (S_ISDIR(sb.st_mode)) {
109 err = FILE_ERR_DIR;
110 } else if (S_ISCHR(sb.st_mode)) {
111 err = FILE_ERR_CHR;
112 } else if (S_ISFIFO(sb.st_mode)) {
113 err = FILE_ERR_FIFO;
114 } else if (S_ISSOCK(sb.st_mode)) {
115 err = FILE_ERR_SOCK;
116 }
117
118 if (close(ifd)) {
119 fprintf(stderr, "Error when closing %s: %s\n",
120 filename, strerror(errno));
121 return FILE_ERR_CLOSE;
122 }
123
124 return err;
125}