create-image.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <fcntl.h>
  16. #include <unistd.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <getopt.h>
  20. #include <sys/stat.h>
  21. #include <sys/mman.h>
  22. #include <sys/param.h>
  23. #include <inttypes.h>
  24. /*
  25. * The "new" ASCII format uses 8-byte hexadecimal fields for all numbers and
  26. * separates device numbers into separate fields for major and minor numbers.
  27. *
  28. * struct cpio_newc_header {
  29. * char c_magic[6];
  30. * char c_ino[8];
  31. * char c_mode[8];
  32. * char c_uid[8];
  33. * char c_gid[8];
  34. * char c_nlink[8];
  35. * char c_mtime[8];
  36. * char c_filesize[8];
  37. * char c_devmajor[8];
  38. * char c_devminor[8];
  39. * char c_rdevmajor[8];
  40. * char c_rdevminor[8];
  41. * char c_namesize[8];
  42. * char c_check[8];
  43. * };
  44. *
  45. */
  46. #define HDR_FMT "%s%08X%08X%08X%08X%08X%08X%08jX%08X%08X%08X%08X%08X%08X%s"
  47. #define HDR_MAGIC "070701"
  48. static unsigned int ino_cnt = 721;
  49. #define REG_EXE S_IFREG | 0555
  50. static const struct {
  51. const char *source;
  52. const char *target;
  53. mode_t mode;
  54. } file_list[] = {
  55. { "tools/test-runner", "init", REG_EXE },
  56. { }
  57. };
  58. static void write_block(FILE *fp, const char *pathname, unsigned int ino,
  59. mode_t mode, const char *name)
  60. {
  61. int i, pad, namelen = strlen(name);
  62. struct stat st;
  63. void *map;
  64. int fd;
  65. if (!pathname) {
  66. fd = -1;
  67. map = NULL;
  68. st.st_size = 0;
  69. goto done;
  70. }
  71. fd = open(pathname, O_RDONLY | O_CLOEXEC);
  72. if (fd < 0) {
  73. fd = -1;
  74. map = NULL;
  75. st.st_size = 0;
  76. goto done;
  77. }
  78. if (fstat(fd, &st) < 0) {
  79. close(fd);
  80. fd = -1;
  81. map = NULL;
  82. st.st_size = 0;
  83. goto done;
  84. }
  85. map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
  86. if (!map || map == MAP_FAILED) {
  87. close(fd);
  88. fd = -1;
  89. map = NULL;
  90. st.st_size = 0;
  91. }
  92. done:
  93. fprintf(fp, HDR_FMT, HDR_MAGIC, ino, mode, 0, 0, 1, 0,
  94. (uintmax_t) st.st_size, 0, 0, 0, 0, namelen + 1, 0, name);
  95. pad = 4 - ((110 + namelen) % 4);
  96. for (i = 0; i < pad; i++)
  97. fputc(0, fp);
  98. if (st.st_size > 0) {
  99. fwrite(map, st.st_size, 1, fp);
  100. pad = 3 - ((st.st_size + 3) % 4);
  101. for (i = 0; i < pad; i++)
  102. fputc(0, fp);
  103. munmap(map, st.st_size);
  104. close(fd);
  105. }
  106. }
  107. static void usage(void)
  108. {
  109. printf("create-image - CPIO image creation utility\n"
  110. "Usage:\n");
  111. printf("\tcreate-image [options]\n");
  112. printf("Options:\n"
  113. "\t-o, --output <image> Output CPIO image\n"
  114. "\t-h, --help Show help options\n");
  115. }
  116. static const struct option main_options[] = {
  117. { "output", required_argument, NULL, 'o' },
  118. { "version", no_argument, NULL, 'v' },
  119. { "help", no_argument, NULL, 'h' },
  120. { }
  121. };
  122. int main(int argc, char *argv[])
  123. {
  124. const char *output_pathname = NULL;
  125. FILE *fp;
  126. int i;
  127. for (;;) {
  128. int opt;
  129. opt = getopt_long(argc, argv, "o:vh", main_options, NULL);
  130. if (opt < 0)
  131. break;
  132. switch (opt) {
  133. case 'o':
  134. output_pathname = optarg;
  135. break;
  136. case 'v':
  137. printf("%s\n", VERSION);
  138. return EXIT_SUCCESS;
  139. case 'h':
  140. usage();
  141. return EXIT_SUCCESS;
  142. default:
  143. return EXIT_FAILURE;
  144. }
  145. }
  146. if (argc - optind > 0) {
  147. fprintf(stderr, "Invalid command line parameters\n");
  148. return EXIT_FAILURE;
  149. }
  150. if (!output_pathname) {
  151. fprintf(stderr, "Failed to specify output file\n");
  152. return EXIT_FAILURE;
  153. }
  154. fp = fopen(output_pathname, "we");
  155. for (i = 0; file_list[i].source; i++)
  156. write_block(fp, file_list[i].source, ino_cnt++,
  157. file_list[i].mode, file_list[i].target);
  158. write_block(fp, NULL, ino_cnt++, 0, "TRAILER!!!");
  159. fclose(fp);
  160. return EXIT_SUCCESS;
  161. }