mongoose/test/pack.c

116 lines
3.7 KiB
C
Raw Permalink Normal View History

2021-07-25 17:22:56 +08:00
// Copyright (c) Cesanta Software Limited
// All rights reserved.
// This program is used to pack arbitrary data into a C binary. It takes
// a list of files as an input, and produces a .c data file that contains
// contents of all these files as a collection of byte arrays.
//
// Usage:
// 1. Compile this file:
// cc -o pack pack.c
//
// 2. Convert list of files into single .c:
// ./pack file1.data file2.data > fs.c
//
// 3. In your application code, you can access files using this function:
2021-07-26 16:15:17 +08:00
// const char *mg_unpack(const char *file_name, size_t *size);
2021-07-25 17:22:56 +08:00
//
// 4. Build your app with fs.c:
// cc -o my_app my_app.c fs.c
2022-02-12 22:28:02 +08:00
#include <errno.h>
2021-07-25 17:22:56 +08:00
#include <stdio.h>
#include <stdlib.h>
2022-02-12 22:28:02 +08:00
#include <string.h>
2021-07-30 20:19:20 +08:00
#include <sys/stat.h>
2021-07-25 17:22:56 +08:00
static const char *code =
2022-07-12 22:09:33 +08:00
"static int scmp(const char *a, const char *b) {\n"
" while (*a && (*a == *b)) a++, b++;\n"
" return *(const unsigned char *) a - *(const unsigned char *) b;\n"
"}\n"
2021-07-30 20:19:20 +08:00
"const char *mg_unlist(size_t no) {\n"
" return packed_files[no].name;\n"
"}\n"
"const char *mg_unpack(const char *name, size_t *size, time_t *mtime) {\n"
2021-07-25 17:22:56 +08:00
" const struct packed_file *p;\n"
2021-07-26 16:15:17 +08:00
" for (p = packed_files; p->name != NULL; p++) {\n"
2022-07-12 22:09:33 +08:00
" if (scmp(p->name, name) != 0) continue;\n"
2021-07-25 17:22:56 +08:00
" if (size != NULL) *size = p->size - 1;\n"
2021-07-30 20:19:20 +08:00
" if (mtime != NULL) *mtime = p->mtime;\n"
2021-07-25 17:22:56 +08:00
" return (const char *) p->data;\n"
" }\n"
" return NULL;\n"
"}\n";
int main(int argc, char *argv[]) {
int i, j, ch;
2022-05-01 20:47:33 +08:00
const char *strip_prefix = "";
2021-07-25 17:22:56 +08:00
printf("%s", "#include <stddef.h>\n");
printf("%s", "#include <string.h>\n");
2021-07-30 20:19:20 +08:00
printf("%s", "#include <time.h>\n");
2021-07-25 17:22:56 +08:00
printf("%s", "\n");
printf("%s", "#if defined(__cplusplus)\nextern \"C\" {\n#endif\n");
printf("%s", "const char *mg_unlist(size_t no);\n");
printf("%s", "const char *mg_unpack(const char *, size_t *, time_t *);\n");
printf("%s", "#if defined(__cplusplus)\n}\n#endif\n\n");
2021-07-25 17:22:56 +08:00
for (i = 1; i < argc; i++) {
2022-05-01 20:47:33 +08:00
if (strcmp(argv[i], "-s") == 0) {
2022-02-15 01:44:43 +08:00
strip_prefix = argv[++i];
} else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
2022-05-01 20:47:33 +08:00
fprintf(stderr, "Usage: %s[-s STRIP_PREFIX] files...\n", argv[0]);
2022-02-15 01:44:43 +08:00
exit(EXIT_FAILURE);
2022-02-12 22:28:02 +08:00
} else {
2022-05-01 20:47:33 +08:00
char ascii[12];
FILE *fp = fopen(argv[i], "rb");
2022-02-12 22:28:02 +08:00
if (fp == NULL) {
2022-05-01 20:47:33 +08:00
fprintf(stderr, "Cannot open [%s]: %s\n", argv[i], strerror(errno));
2022-02-12 22:28:02 +08:00
exit(EXIT_FAILURE);
}
printf("static const unsigned char v%d[] = {\n", i);
for (j = 0; (ch = fgetc(fp)) != EOF; j++) {
if (j == (int) sizeof(ascii)) {
printf(" // %.*s\n", j, ascii);
j = 0;
}
ascii[j] = (char) ((ch >= ' ' && ch <= '~' && ch != '\\') ? ch : '.');
printf(" %3u,", ch);
}
// Append zero byte at the end, to make text files appear in memory
// as nul-terminated strings.
// printf(" 0 // %.*s\n", (int) sizeof(ascii), ascii);
printf(" 0 // %.*s\n};\n", j, ascii);
2022-05-01 20:47:33 +08:00
fclose(fp);
2021-07-25 17:22:56 +08:00
}
}
2021-07-26 16:15:17 +08:00
printf("%s", "\nstatic const struct packed_file {\n");
2021-07-25 17:22:56 +08:00
printf("%s", " const char *name;\n");
printf("%s", " const unsigned char *data;\n");
printf("%s", " size_t size;\n");
2021-07-30 20:19:20 +08:00
printf("%s", " time_t mtime;\n");
2021-07-26 16:15:17 +08:00
printf("%s", "} packed_files[] = {\n");
2021-07-25 17:22:56 +08:00
for (i = 1; i < argc; i++) {
2021-07-30 20:19:20 +08:00
struct stat st;
2022-02-15 01:44:43 +08:00
const char *name = argv[i];
size_t n = strlen(strip_prefix);
2022-05-13 23:47:10 +08:00
if (strcmp(argv[i], "-s") == 0) {
2022-02-15 01:44:43 +08:00
i++;
continue;
}
2021-07-30 20:19:20 +08:00
stat(argv[i], &st);
2022-02-15 01:44:43 +08:00
if (strncmp(name, strip_prefix, n) == 0) name += n;
2022-10-31 18:40:34 +08:00
printf(" {\"/%s\", v%d, sizeof(v%d), %lu},\n", name, i, i,
(unsigned long) st.st_mtime);
2021-07-25 17:22:56 +08:00
}
2022-05-01 20:47:33 +08:00
printf("%s", " {NULL, NULL, 0, 0}\n");
2021-07-25 17:22:56 +08:00
printf("%s", "};\n\n");
printf("%s", code);
return EXIT_SUCCESS;
}