• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 */
22 static 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",
34 	"VbPrivateKey",
35 };
36 BUILD_ASSERT(ARRAY_SIZE(type_strings) == NUM_FILE_TYPES);
37 
futil_file_type_str(enum futil_file_type type)38 const char * const futil_file_type_str(enum futil_file_type type)
39 {
40 	if ((int) type < 0 || type >= NUM_FILE_TYPES)
41 		type = FILE_TYPE_UNKNOWN;
42 
43 	return type_strings[type];
44 }
45 
46 /* Try these in order so we recognize the larger objects first */
47 enum futil_file_type (*recognizers[])(uint8_t *buf, uint32_t len) = {
48 	&recognize_gpt,
49 	&recognize_bios_image,
50 	&recognize_gbb,
51 	&recognize_vblock1,
52 	&recognize_privkey,
53 };
54 
55 /* Try to figure out what we're looking at */
futil_file_type_buf(uint8_t * buf,uint32_t len)56 enum 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 
futil_file_type(const char * filename,enum futil_file_type * type)70 enum 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 }
126