Home | History | Annotate | Download | only in futility
      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