189 lines
5.8 KiB
C
189 lines
5.8 KiB
C
/**
|
|
* @file main.c
|
|
* @brief Converts files to a C file that can be used by llfs (linked list file system).
|
|
* @version 0.2.1
|
|
* @author Lorenz C.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "tinydir.h"
|
|
|
|
#define VERSION "0.2.1"
|
|
#define LLFS_VERSION "0.1.1"
|
|
#define MAX_PATH_LEN 256
|
|
|
|
static void file_name_to_llfs_name(char* llfs_name, const char* file_name);
|
|
static void print_help(void);
|
|
static void print_version(void);
|
|
|
|
int main(int argc, char** argv) {
|
|
char src_path[MAX_PATH_LEN];
|
|
char llfs_name[MAX_PATH_LEN];
|
|
char prev_llfs_name[MAX_PATH_LEN] = "NULL";
|
|
FILE* out_file;
|
|
FILE* src_file;
|
|
tinydir_dir dir;
|
|
int file_count = 0;
|
|
|
|
// Check if the help or version flag is set
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
|
|
print_help();
|
|
return 0;
|
|
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
|
|
print_version();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Check if at least 2 arguments are given (directory and output file)
|
|
if (argc < 3) {
|
|
fprintf(stderr, "Error: Not enough arguments.\r\n");
|
|
print_help();
|
|
goto fail_init;
|
|
}
|
|
|
|
// Open the output file
|
|
out_file = fopen(argv[argc - 1], "w");
|
|
if (out_file == NULL) {
|
|
fprintf(stderr, "Error: Could not open output file\r\n");
|
|
goto fail_init;
|
|
}
|
|
|
|
// Open the source directory
|
|
strcpy(src_path, argv[argc - 2]);
|
|
if (tinydir_open(&dir, src_path) == -1) {
|
|
fprintf(stderr, "Error: Could not open directory\r\n");
|
|
goto fail_open_dir;
|
|
}
|
|
|
|
// Write the header of the output file
|
|
fprintf(out_file, "/**\n"
|
|
" * @file %s\n"
|
|
" * @brief Linked list file system (llfs) data file.\n"
|
|
" * This file was generated by mkllfs %s.\n"
|
|
" * @date %s\n */\n\n",
|
|
argv[argc - 1], VERSION, __DATE__);
|
|
|
|
// Write the headers of the output file
|
|
fprintf(out_file, "#include <stddef.h>\n");
|
|
fprintf(out_file, "#include \"llfs.h\"\n");
|
|
fprintf(out_file, "\n");
|
|
|
|
// Iterate over all files in the directory
|
|
while (dir.has_next) {
|
|
tinydir_file file;
|
|
size_t file_size = 0;
|
|
|
|
// Get file info
|
|
if (tinydir_readfile(&dir, &file) == -1) {
|
|
fprintf(stderr, "Error: Could not read file\r\n");
|
|
continue;
|
|
}
|
|
if (file.is_dir) {
|
|
tinydir_next(&dir);
|
|
continue;
|
|
}
|
|
|
|
// Open the source file
|
|
src_file = fopen(file.path, "rb");
|
|
if (src_file == NULL) {
|
|
printf("Error: Could not open source file: %s\r\n", file.path);
|
|
continue;
|
|
}
|
|
|
|
// Convert the file name to a valid llfs name
|
|
file_name_to_llfs_name(llfs_name, file.name);
|
|
|
|
// Write the file data to the output file
|
|
fprintf(out_file, "// File: %s\n", file.name);
|
|
fprintf(out_file, "__attribute__((section(\".ext_qspi_flash\")))\n");
|
|
fprintf(out_file, "const uint8_t %s_data[] = {\n", llfs_name);
|
|
for (int i = 0, c; (c = fgetc(src_file)) != EOF; i++) {
|
|
file_size++;
|
|
fprintf(out_file, "0x%02X, ", c);
|
|
if (i % 16 == 15) {
|
|
fprintf(out_file, "\n");
|
|
}
|
|
}
|
|
fprintf(out_file, "\n};\n");
|
|
|
|
// Write the file info to the output file
|
|
fprintf(out_file,
|
|
"const struct llfs_data_file %s = {\n .data = %s_data,\n .name = \"%s\",\n .len = %zu,\n "
|
|
".next =%s%s\n};\n\n",
|
|
llfs_name, llfs_name, file.name, file_size, strcmp(prev_llfs_name, "NULL") == 0 ? " " : " &",
|
|
prev_llfs_name);
|
|
|
|
file_count++;
|
|
tinydir_next(&dir);
|
|
strcpy(prev_llfs_name, llfs_name);
|
|
fclose(src_file);
|
|
}
|
|
|
|
// Make the last file the root file of the llfs
|
|
fprintf(out_file, "\n");
|
|
fprintf(out_file, "const struct llfs_data_file *llfs_root =%s%s;\n", (strcmp(prev_llfs_name, "NULL") == 0 ? " " : " &"), prev_llfs_name);
|
|
|
|
// Print the number of files
|
|
printf("Successfully converted %d files.\r\n", file_count);
|
|
|
|
fail:
|
|
tinydir_close(&dir);
|
|
fail_open_dir:
|
|
fclose(out_file);
|
|
fail_init:
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Converts a file name to a valid llfs name, so that it can be used as a variable name in the generated C file.
|
|
* The length of the generated llfs name is the same as the length of the original file name.
|
|
*
|
|
* @param[out] llfs_name The output llfs name. Must be at least as long as the file name.
|
|
* @param[in] file_name The input file name as a null terminated string.
|
|
*/
|
|
static void file_name_to_llfs_name(char* llfs_name, const char* file_name) {
|
|
size_t len = strlen(file_name);
|
|
|
|
// Replace all invalid characters with '_'
|
|
for (int i = 0; i < len; i++) {
|
|
if (file_name[i] == '.' || file_name[i] == '-' || file_name[i] == ' ') {
|
|
llfs_name[i] = '_';
|
|
} else {
|
|
llfs_name[i] = file_name[i];
|
|
}
|
|
}
|
|
|
|
// Replace the first character if it is a number
|
|
if (llfs_name[0] >= '0' && llfs_name[0] <= '9') {
|
|
llfs_name[0] = '_';
|
|
}
|
|
|
|
llfs_name[len] = '\0';
|
|
}
|
|
|
|
/**
|
|
* @brief Prints the help message.
|
|
*/
|
|
static void print_help(void) {
|
|
printf("Make Linked list file system (mkllfs)\r\n");
|
|
printf("Converts files into a linked list file system.\r\n");
|
|
printf("By Lorenz C.\r\n");
|
|
printf("\r\n");
|
|
printf("Usage: mkllfs [options] <directory> <output file>\r\n");
|
|
printf("Options:\r\n");
|
|
printf(" -h, --help: Print this help message\r\n");
|
|
printf(" -v, --version: Print the version\r\n");
|
|
}
|
|
|
|
/**
|
|
* @brief Prints the version.
|
|
*/
|
|
static void print_version(void) {
|
|
printf("mkllfs version %s\r\n", VERSION);
|
|
printf("llfs version %s\r\n", LLFS_VERSION);
|
|
}
|