file_type.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. #include <errno.h>
  7. #include <fcntl.h>
  8. #include <stdint.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <sys/stat.h>
  13. #include <sys/types.h>
  14. #include <unistd.h>
  15. #include "file_type.h"
  16. #include "futility.h"
  17. #include "gbb_header.h"
  18. /* Description and functions to handle each file type */
  19. struct futil_file_type_s {
  20. /* Short name for this type */
  21. const char *name;
  22. /* Human-readable description */
  23. const char *desc;
  24. /* Functions to identify, display, and sign this type of file. */
  25. enum futil_file_type (*recognize)(uint8_t *buf, uint32_t len);
  26. int (*show)(const char *name, uint8_t *buf, uint32_t len, void *data);
  27. int (*sign)(const char *name, uint8_t *buf, uint32_t len, void *data);
  28. };
  29. /* Populate a list of file types and operator functions. */
  30. static const struct futil_file_type_s futil_file_types[] = {
  31. {"unknown", "not something we know about", 0, 0, 0},
  32. #define R_(x) x
  33. #define S_(x) x
  34. #define NONE 0
  35. #define FILE_TYPE(A, B, C, D, E, F) {B, C, D, E, F},
  36. #include "file_type.inc"
  37. #undef FILE_TYPE
  38. #undef NONE
  39. #undef S_
  40. #undef R_
  41. };
  42. const char * const futil_file_type_name(enum futil_file_type type)
  43. {
  44. return futil_file_types[type].name;
  45. }
  46. const char * const futil_file_type_desc(enum futil_file_type type)
  47. {
  48. return futil_file_types[type].desc;
  49. }
  50. /* Name to enum. Returns true on success. */
  51. int futil_str_to_file_type(const char *str, enum futil_file_type *type)
  52. {
  53. int i;
  54. for (i = 0; i < NUM_FILE_TYPES; i++)
  55. if (!strcasecmp(str, futil_file_types[i].name)) {
  56. *type = i;
  57. return 1;
  58. }
  59. *type = FILE_TYPE_UNKNOWN;
  60. return 0;
  61. }
  62. /* Print the list of type names and exit with the given value. */
  63. void print_file_types_and_exit(int retval)
  64. {
  65. int i;
  66. printf("\nValid file types are:\n\n");
  67. for (i = 0; i < NUM_FILE_TYPES; i++)
  68. printf(" %-20s%s\n", futil_file_types[i].name,
  69. futil_file_types[i].desc);
  70. printf("\n");
  71. exit(retval);
  72. }
  73. /* Try to figure out what we're looking at */
  74. enum futil_file_type futil_file_type_buf(uint8_t *buf, uint32_t len)
  75. {
  76. enum futil_file_type type;
  77. int i;
  78. for (i = 0; i < NUM_FILE_TYPES; i++) {
  79. if (futil_file_types[i].recognize) {
  80. type = futil_file_types[i].recognize(buf, len);
  81. if (type != FILE_TYPE_UNKNOWN)
  82. return type;
  83. }
  84. }
  85. return FILE_TYPE_UNKNOWN;
  86. }
  87. enum futil_file_err futil_file_type(const char *filename,
  88. enum futil_file_type *type)
  89. {
  90. int ifd;
  91. uint8_t *buf;
  92. uint32_t buf_len;
  93. struct stat sb;
  94. enum futil_file_err err = FILE_ERR_NONE;
  95. *type = FILE_TYPE_UNKNOWN;
  96. ifd = open(filename, O_RDONLY);
  97. if (ifd < 0) {
  98. fprintf(stderr, "Can't open %s: %s\n",
  99. filename, strerror(errno));
  100. return FILE_ERR_OPEN;
  101. }
  102. if (0 != fstat(ifd, &sb)) {
  103. fprintf(stderr, "Can't stat input file: %s\n",
  104. strerror(errno));
  105. close(ifd);
  106. return FILE_ERR_STAT;
  107. }
  108. if (S_ISREG(sb.st_mode) || S_ISBLK(sb.st_mode)) {
  109. err = futil_map_file(ifd, MAP_RO, &buf, &buf_len);
  110. if (err) {
  111. close(ifd);
  112. return err;
  113. }
  114. *type = futil_file_type_buf(buf, buf_len);
  115. err = futil_unmap_file(ifd, MAP_RO, buf, buf_len);
  116. if (err) {
  117. close(ifd);
  118. return err;
  119. }
  120. } else if (S_ISDIR(sb.st_mode)) {
  121. err = FILE_ERR_DIR;
  122. } else if (S_ISCHR(sb.st_mode)) {
  123. err = FILE_ERR_CHR;
  124. } else if (S_ISFIFO(sb.st_mode)) {
  125. err = FILE_ERR_FIFO;
  126. } else if (S_ISSOCK(sb.st_mode)) {
  127. err = FILE_ERR_SOCK;
  128. }
  129. if (close(ifd)) {
  130. fprintf(stderr, "Error when closing %s: %s\n",
  131. filename, strerror(errno));
  132. return FILE_ERR_CLOSE;
  133. }
  134. return err;
  135. }
  136. int futil_file_type_show(enum futil_file_type type,
  137. const char *filename,
  138. uint8_t *buf, uint32_t len)
  139. {
  140. if (futil_file_types[type].show)
  141. return futil_file_types[type].show(filename, buf, len, 0);
  142. fprintf(stderr, "Don't know how to show %s (type %s)\n",
  143. filename, futil_file_type_name(type));
  144. return 1;
  145. }
  146. int futil_file_type_sign(enum futil_file_type type,
  147. const char *filename,
  148. uint8_t *buf, uint32_t len)
  149. {
  150. if (futil_file_types[type].sign)
  151. return futil_file_types[type].sign(filename, buf, len, 0);
  152. fprintf(stderr, "Don't know how to sign %s (type %s)\n",
  153. filename, futil_file_type_name(type));
  154. return 1;
  155. }