pack.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // Copyright (c) Cesanta Software Limited
  2. // All rights reserved.
  3. // This program is used to pack arbitrary data into a C binary. It takes
  4. // a list of files as an input, and produces a .c data file that contains
  5. // contents of all these files as a collection of byte arrays.
  6. //
  7. // Usage:
  8. // 1. Compile this file:
  9. // cc -o pack pack.c
  10. //
  11. // 2. Convert list of files into single .c:
  12. // ./pack file1.data file2.data > fs.c
  13. //
  14. // 3. In your application code, you can access files using this function:
  15. // const char *mg_unpack(const char *file_name, size_t *size);
  16. //
  17. // 4. Build your app with fs.c:
  18. // cc -o my_app my_app.c fs.c
  19. #include <errno.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <sys/stat.h>
  24. static const char *code =
  25. "static int scmp(const char *a, const char *b) {\n"
  26. " while (*a && (*a == *b)) a++, b++;\n"
  27. " return *(const unsigned char *) a - *(const unsigned char *) b;\n"
  28. "}\n"
  29. "const char *mg_unlist(size_t no) {\n"
  30. " return packed_files[no].name;\n"
  31. "}\n"
  32. "const char *mg_unpack(const char *name, size_t *size, time_t *mtime) {\n"
  33. " const struct packed_file *p;\n"
  34. " for (p = packed_files; p->name != NULL; p++) {\n"
  35. " if (scmp(p->name, name) != 0) continue;\n"
  36. " if (size != NULL) *size = p->size - 1;\n"
  37. " if (mtime != NULL) *mtime = p->mtime;\n"
  38. " return (const char *) p->data;\n"
  39. " }\n"
  40. " return NULL;\n"
  41. "}\n";
  42. int main(int argc, char *argv[]) {
  43. int i, j, ch;
  44. const char *strip_prefix = "";
  45. printf("%s", "#include <stddef.h>\n");
  46. printf("%s", "#include <string.h>\n");
  47. printf("%s", "#include <time.h>\n");
  48. printf("%s", "\n");
  49. printf("%s", "#if defined(__cplusplus)\nextern \"C\" {\n#endif\n");
  50. printf("%s", "const char *mg_unlist(size_t no);\n");
  51. printf("%s", "const char *mg_unpack(const char *, size_t *, time_t *);\n");
  52. printf("%s", "#if defined(__cplusplus)\n}\n#endif\n\n");
  53. for (i = 1; i < argc; i++) {
  54. if (strcmp(argv[i], "-s") == 0) {
  55. strip_prefix = argv[++i];
  56. } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
  57. fprintf(stderr, "Usage: %s[-s STRIP_PREFIX] files...\n", argv[0]);
  58. exit(EXIT_FAILURE);
  59. } else {
  60. char ascii[12];
  61. FILE *fp = fopen(argv[i], "rb");
  62. if (fp == NULL) {
  63. fprintf(stderr, "Cannot open [%s]: %s\n", argv[i], strerror(errno));
  64. exit(EXIT_FAILURE);
  65. }
  66. printf("static const unsigned char v%d[] = {\n", i);
  67. for (j = 0; (ch = fgetc(fp)) != EOF; j++) {
  68. if (j == (int) sizeof(ascii)) {
  69. printf(" // %.*s\n", j, ascii);
  70. j = 0;
  71. }
  72. ascii[j] = (char) ((ch >= ' ' && ch <= '~' && ch != '\\') ? ch : '.');
  73. printf(" %3u,", ch);
  74. }
  75. // Append zero byte at the end, to make text files appear in memory
  76. // as nul-terminated strings.
  77. // printf(" 0 // %.*s\n", (int) sizeof(ascii), ascii);
  78. printf(" 0 // %.*s\n};\n", j, ascii);
  79. fclose(fp);
  80. }
  81. }
  82. printf("%s", "\nstatic const struct packed_file {\n");
  83. printf("%s", " const char *name;\n");
  84. printf("%s", " const unsigned char *data;\n");
  85. printf("%s", " size_t size;\n");
  86. printf("%s", " time_t mtime;\n");
  87. printf("%s", "} packed_files[] = {\n");
  88. for (i = 1; i < argc; i++) {
  89. struct stat st;
  90. const char *name = argv[i];
  91. size_t n = strlen(strip_prefix);
  92. if (strcmp(argv[i], "-s") == 0) {
  93. i++;
  94. continue;
  95. }
  96. stat(argv[i], &st);
  97. if (strncmp(name, strip_prefix, n) == 0) name += n;
  98. printf(" {\"/%s\", v%d, sizeof(v%d), %lu},\n", name, i, i,
  99. (unsigned long) st.st_mtime);
  100. }
  101. printf("%s", " {NULL, NULL, 0, 0}\n");
  102. printf("%s", "};\n\n");
  103. printf("%s", code);
  104. return EXIT_SUCCESS;
  105. }