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 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 */ 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 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