summaryrefslogtreecommitdiff
path: root/futility/file_type.c
diff options
context:
space:
mode:
Diffstat (limited to 'futility/file_type.c')
-rw-r--r--futility/file_type.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/futility/file_type.c b/futility/file_type.c
new file mode 100644
index 00000000..0c915865
--- /dev/null
+++ b/futility/file_type.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "file_type.h"
+#include "futility.h"
+#include "gbb_header.h"
+
+/* Human-readable strings */
+static const char * const type_strings[] = {
+ "unknown",
+ "VbPublicKey",
+ "VbKeyBlock",
+ "VbFirmwarePreamble",
+ "GBB",
+ "Chrome OS BIOS image",
+ "Cr-48 Chrome OS BIOS image",
+ "VbKernelPreamble",
+ "raw firmware",
+ "raw kernel",
+ "chromiumos disk image",
+};
+BUILD_ASSERT(ARRAY_SIZE(type_strings) == NUM_FILE_TYPES);
+
+const char * const futil_file_type_str(enum futil_file_type type)
+{
+ if (type < 0 || type >= NUM_FILE_TYPES)
+ type = FILE_TYPE_UNKNOWN;
+
+ return type_strings[type];
+}
+
+/* Try these in order so we recognize the larger objects first */
+enum futil_file_type (*recognizers[])(uint8_t *buf, uint32_t len) = {
+ &recognize_gpt,
+ &recognize_bios_image,
+ &recognize_gbb,
+ &recognize_vblock1,
+};
+
+/* Try to figure out what we're looking at */
+enum futil_file_type futil_file_type_buf(uint8_t *buf, uint32_t len)
+{
+ enum futil_file_type type;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(recognizers); i++) {
+ type = recognizers[i](buf, len);
+ if (type != FILE_TYPE_UNKNOWN)
+ return type;
+ }
+
+ return FILE_TYPE_UNKNOWN;
+}
+
+enum futil_file_err futil_file_type(const char *filename,
+ enum futil_file_type *type)
+{
+ int ifd;
+ uint8_t *buf;
+ uint32_t buf_len;
+ struct stat sb;
+ enum futil_file_err err = FILE_ERR_NONE;
+
+ *type = FILE_TYPE_UNKNOWN;
+
+ ifd = open(filename, O_RDONLY);
+ if (ifd < 0) {
+ fprintf(stderr, "Can't open %s: %s\n",
+ filename, strerror(errno));
+ return FILE_ERR_OPEN;
+ }
+
+ if (0 != fstat(ifd, &sb)) {
+ fprintf(stderr, "Can't stat input file: %s\n",
+ strerror(errno));
+ return FILE_ERR_STAT;
+ }
+
+ if (S_ISREG(sb.st_mode) || S_ISBLK(sb.st_mode)) {
+ err = futil_map_file(ifd, MAP_RO, &buf, &buf_len);
+ if (err) {
+ close(ifd);
+ return err;
+ }
+
+ *type = futil_file_type_buf(buf, buf_len);
+
+ err = futil_unmap_file(ifd, MAP_RO, buf, buf_len);
+ if (err) {
+ close(ifd);
+ return err;
+ }
+ } else if (S_ISDIR(sb.st_mode)) {
+ err = FILE_ERR_DIR;
+ } else if (S_ISCHR(sb.st_mode)) {
+ err = FILE_ERR_CHR;
+ } else if (S_ISFIFO(sb.st_mode)) {
+ err = FILE_ERR_FIFO;
+ } else if (S_ISSOCK(sb.st_mode)) {
+ err = FILE_ERR_SOCK;
+ }
+
+ if (close(ifd)) {
+ fprintf(stderr, "Error when closing %s: %s\n",
+ filename, strerror(errno));
+ return FILE_ERR_CLOSE;
+ }
+
+ return err;
+}