[wip] initial commit
This commit is contained in:
commit
3f605489ac
|
@ -0,0 +1,17 @@
|
||||||
|
CFLAGS = -g3 -O0 -I. -Iinc
|
||||||
|
|
||||||
|
build: main
|
||||||
|
|
||||||
|
main: out/main.o out/cli.o out/fs.o out/ctrl.o config.h
|
||||||
|
gcc out/*.o -o main
|
||||||
|
|
||||||
|
out/%.o : src/%.c out/ config.h
|
||||||
|
gcc -c $(CFLAGS) -o "$@" "$<"
|
||||||
|
|
||||||
|
out/:
|
||||||
|
mkdir -p out/
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -r out/ main
|
||||||
|
|
||||||
|
.PHONY : build clean
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef CONFIG_FILE
|
||||||
|
#define CONFIG_FILE
|
||||||
|
|
||||||
|
/* Global config options */
|
||||||
|
#define DEBUG 1
|
||||||
|
#define LOG_LEVEL 4
|
||||||
|
#define ENABLE_FILE_LINE_IN_OTHER_PR 1
|
||||||
|
|
||||||
|
|
||||||
|
/* Output color config section */
|
||||||
|
#define COLOR_ENABLE 1
|
||||||
|
|
||||||
|
|
||||||
|
/* CLI config section */
|
||||||
|
#define CLI_MAX_LINE_LENGTH 256
|
||||||
|
#define CLI_MAX_ACCEPTED_ARGS 4
|
||||||
|
#define CLI_MAX_TOKEN_LENGTH 64
|
||||||
|
|
||||||
|
|
||||||
|
/* FS config section */
|
||||||
|
#define FS_MAX_DEVICE_FILE_NAME_LEN 512
|
||||||
|
#define FS_BLOCK_SIZE 4096
|
||||||
|
#define FS_MAX_BITMAP_SIZE 256
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef INC_CLI_H
|
||||||
|
#define INC_CLI_H
|
||||||
|
|
||||||
|
|
||||||
|
enum CliArgType {
|
||||||
|
INT,
|
||||||
|
STR,
|
||||||
|
WRONG_TYPE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CliCommandEntry {
|
||||||
|
char *cmd;
|
||||||
|
unsigned int arg_count;
|
||||||
|
enum CliArgType *args;
|
||||||
|
int (*process)(void *);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int cli_poll_process_next(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef INC_COLOR_H
|
||||||
|
#define INC_COLOR_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#if COLOR_ENABLE == 1
|
||||||
|
#define COLOR_RESET "\e[0m"
|
||||||
|
#define COLOR_RED "\e[0;31m"
|
||||||
|
#define COLOR_YELLOW "\e[0;33m"
|
||||||
|
#else
|
||||||
|
#define COLOR_RESET ""
|
||||||
|
#define COLOR_RED ""
|
||||||
|
#define COLOR_YELLOW ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef INC_CTRL_H
|
||||||
|
#define INC_CTRL_H
|
||||||
|
|
||||||
|
|
||||||
|
int ctrl_exit(void *d);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
enum fs_filetype {
|
||||||
|
REGULAR,
|
||||||
|
DIRECTORY
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((packed))
|
||||||
|
struct fs_header {
|
||||||
|
unsigned char version;
|
||||||
|
unsigned int max_inode_count:24;
|
||||||
|
unsigned int block_count;
|
||||||
|
unsigned int next_extension;
|
||||||
|
unsigned int inode_ptrs[(FS_BLOCK_SIZE-sizeof(int)*3) / sizeof(int)];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fs_header_extension {
|
||||||
|
unsigned int next_extension;
|
||||||
|
unsigned int inode_ptrs[(FS_BLOCK_SIZE-sizeof(int)) / sizeof(int)];
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((packed))
|
||||||
|
struct fs_inode {
|
||||||
|
unsigned int ftype:8;
|
||||||
|
unsigned int ref_count:24;
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int next_extension;
|
||||||
|
unsigned int blocks[(FS_BLOCK_SIZE-sizeof(int)*3) / sizeof(int)];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fs_inode_extension {
|
||||||
|
unsigned int next_extension;
|
||||||
|
unsigned int blocks[(FS_BLOCK_SIZE-sizeof(int)) / sizeof(int)];
|
||||||
|
};
|
||||||
|
|
||||||
|
int fs_create(void *d);
|
||||||
|
int fs_use(void *d);
|
||||||
|
int fs_mkfs(void *d);
|
||||||
|
int fs_allow_write(void *d);
|
||||||
|
int fs_prohibit_write(void *d);
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef INC_MACRO_H
|
||||||
|
#define INC_MACRO_H
|
||||||
|
|
||||||
|
|
||||||
|
#define LEN(x) ( sizeof(x) / sizeof((x)[0]) )
|
||||||
|
|
||||||
|
#define FOR(i, max) for (unsigned int (i) = 0; (i) < (max); (i)++)
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef INC_PRINT_H
|
||||||
|
#define INC_PRINT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "color.h"
|
||||||
|
|
||||||
|
#if DEBUG == 1
|
||||||
|
#define pr(...) { printf("[%s:%d] ", __FILE__, __LINE__); printf(__VA_ARGS__); }
|
||||||
|
#else
|
||||||
|
#define pr(...) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if LOG_LEVEL >= 2
|
||||||
|
#if ENABLE_FILE_LINE_IN_OTHER_PR == 1
|
||||||
|
#define pr_err(...) { \
|
||||||
|
printf(COLOR_RED "[%s:%d] Error: ", __FILE__, __LINE__); \
|
||||||
|
printf(__VA_ARGS__); \
|
||||||
|
printf(COLOR_RESET); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define pr_err(...) { \
|
||||||
|
printf(COLOR_RED "Error: "); \
|
||||||
|
printf(__VA_ARGS__); \
|
||||||
|
printf(COLOR_RESET);\
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define pr_err(...) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LOG_LEVEL >= 3
|
||||||
|
#if ENABLE_FILE_LINE_IN_OTHER_PR == 1
|
||||||
|
#define pr_warn(...) { \
|
||||||
|
printf(COLOR_YELLOW "[%s:%d] Warning: ", __FILE__, __LINE__); \
|
||||||
|
printf(__VA_ARGS__); \
|
||||||
|
printf(COLOR_RESET); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define pr_warn(...) { \
|
||||||
|
printf(COLOR_YELLOW "Warning: "); \
|
||||||
|
printf(__VA_ARGS__); \
|
||||||
|
printf(COLOR_RESET); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define pr_warn(...) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LOG_LEVEL >= 4
|
||||||
|
#if ENABLE_FILE_LINE_IN_OTHER_PR == 1
|
||||||
|
#define pr_info(...) { \
|
||||||
|
printf("[%s:%d] Info: ", __FILE__, __LINE__); \
|
||||||
|
printf(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define pr_info(...) { printf("Info: "); printf(__VA_ARGS__); }
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define pr_info(...) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,250 @@
|
||||||
|
#include "macro.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "cli.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
#include "fs.h"
|
||||||
|
#include "ctrl.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const struct CliCommandEntry cmd[] = {
|
||||||
|
// mandatory commands
|
||||||
|
{"mkfs", 1, (enum CliArgType[]) {INT}, fs_mkfs},
|
||||||
|
{"create", 1, (enum CliArgType[]) {STR}, fs_create},
|
||||||
|
|
||||||
|
// custom commands
|
||||||
|
{"use", 1, (enum CliArgType[]) {STR}, fs_use},
|
||||||
|
{"prohibit-write", 0, NULL, fs_prohibit_write},
|
||||||
|
{"allow-write", 0, NULL, fs_allow_write},
|
||||||
|
{"exit", 0, NULL, ctrl_exit}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void destroy_tokenized_line(char **tokenized_line)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < CLI_MAX_ACCEPTED_ARGS; j++)
|
||||||
|
if (tokenized_line[j])
|
||||||
|
free(tokenized_line[j]);
|
||||||
|
|
||||||
|
free(tokenized_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tokenized_line_len(char **t)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < CLI_MAX_ACCEPTED_ARGS; i++)
|
||||||
|
if (!t[i])
|
||||||
|
break;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char **tokenize_line(char *line, ssize_t result)
|
||||||
|
{
|
||||||
|
if (result > CLI_MAX_LINE_LENGTH) {
|
||||||
|
pr_err("command too long (%d > %d)\n", result+1, CLI_MAX_LINE_LENGTH);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char **tokenized_line = malloc(sizeof(char *) * CLI_MAX_ACCEPTED_ARGS);
|
||||||
|
memset(tokenized_line, 0, sizeof(char *) * CLI_MAX_ACCEPTED_ARGS);
|
||||||
|
|
||||||
|
unsigned int i, t, l;
|
||||||
|
for (
|
||||||
|
i = 0, t = 0, l = 0;
|
||||||
|
i < CLI_MAX_LINE_LENGTH,
|
||||||
|
t <= CLI_MAX_ACCEPTED_ARGS,
|
||||||
|
l < CLI_MAX_TOKEN_LENGTH;
|
||||||
|
i++
|
||||||
|
) {
|
||||||
|
if (line[i] == '\n') {
|
||||||
|
if (l) {
|
||||||
|
if (t == CLI_MAX_ACCEPTED_ARGS) {
|
||||||
|
t++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenized_line[t] = malloc(sizeof(char) * (l+1));
|
||||||
|
memcpy(tokenized_line[t], &(line[i-l]), l);
|
||||||
|
tokenized_line[t][l] = '\0';
|
||||||
|
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else if (line[i] == ' ') {
|
||||||
|
if (l) {
|
||||||
|
if (t == CLI_MAX_ACCEPTED_ARGS) {
|
||||||
|
t++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenized_line[t] = malloc(sizeof(char) * (l+1));
|
||||||
|
memcpy(tokenized_line[t], &(line[i-l]), l);
|
||||||
|
tokenized_line[t][l] = '\0';
|
||||||
|
|
||||||
|
l = 0;
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
i >= CLI_MAX_LINE_LENGTH ||
|
||||||
|
t > CLI_MAX_ACCEPTED_ARGS ||
|
||||||
|
l >= CLI_MAX_TOKEN_LENGTH ||
|
||||||
|
t == 0
|
||||||
|
) goto cli_process_error;
|
||||||
|
|
||||||
|
return tokenized_line;
|
||||||
|
|
||||||
|
|
||||||
|
cli_process_error:
|
||||||
|
// print error
|
||||||
|
if (i >= CLI_MAX_LINE_LENGTH)
|
||||||
|
pr_err("command too long (> %d)\n", CLI_MAX_LINE_LENGTH);
|
||||||
|
|
||||||
|
if (t > CLI_MAX_ACCEPTED_ARGS)
|
||||||
|
pr_err("too many arguments (> %d)\n", CLI_MAX_ACCEPTED_ARGS);
|
||||||
|
|
||||||
|
if (l >= CLI_MAX_TOKEN_LENGTH)
|
||||||
|
pr_err("argument %d too long (> %d)\n", t, CLI_MAX_TOKEN_LENGTH);
|
||||||
|
|
||||||
|
// clean up
|
||||||
|
destroy_tokenized_line(tokenized_line);
|
||||||
|
|
||||||
|
// return
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *format_args(char **tokenized_line, unsigned int arg_count, enum CliArgType *arg_types)
|
||||||
|
{
|
||||||
|
char *new_struct;
|
||||||
|
|
||||||
|
{
|
||||||
|
// prepare struct space
|
||||||
|
unsigned int struct_size = 0;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < arg_count; i++)
|
||||||
|
switch (arg_types[i]) {
|
||||||
|
case INT:
|
||||||
|
struct_size += sizeof(int);
|
||||||
|
break;
|
||||||
|
case STR:
|
||||||
|
struct_size += sizeof(char *);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_struct = malloc(struct_size);
|
||||||
|
memset(new_struct, 0, struct_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int struct_offset = 0;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < arg_count; i++)
|
||||||
|
{
|
||||||
|
if (arg_types[i] == INT) {
|
||||||
|
if (!tokenized_line[i+1]) {
|
||||||
|
pr_err("missing argument %d of type 'integer'\n", i+1);
|
||||||
|
goto abandon_struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
int value;
|
||||||
|
int result = sscanf(tokenized_line[i+1], "%d", &value);
|
||||||
|
|
||||||
|
if (result != 1) {
|
||||||
|
pr_err("argument %d must be of type 'integer'\n", i+1);
|
||||||
|
goto abandon_struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
*((int*) &(new_struct[struct_offset])) = value;
|
||||||
|
struct_offset += sizeof(int);
|
||||||
|
}
|
||||||
|
else if (arg_types[i] == STR) {
|
||||||
|
if (!tokenized_line[i+1]) {
|
||||||
|
pr_err("missing argument %d of type 'string'\n", i+1);
|
||||||
|
goto abandon_struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
*((char**) &(new_struct[struct_offset])) = tokenized_line[i+1];
|
||||||
|
struct_offset += sizeof(char *);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_struct;
|
||||||
|
|
||||||
|
abandon_struct:
|
||||||
|
free(new_struct);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int cli_poll_process_next(void)
|
||||||
|
{
|
||||||
|
for ( ;; ) {
|
||||||
|
fputs("$ ", stdout);
|
||||||
|
|
||||||
|
size_t buf_size = 0;
|
||||||
|
char *line = NULL;
|
||||||
|
|
||||||
|
ssize_t result = getline(&line, &buf_size, stdin);
|
||||||
|
if (result == -1)
|
||||||
|
return 0x1;
|
||||||
|
|
||||||
|
char **tokenized_line = tokenize_line(line, result);
|
||||||
|
free(line);
|
||||||
|
|
||||||
|
if (tokenized_line == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; (i < LEN(cmd)) && strcmp(tokenized_line[0], cmd[i].cmd); i++);
|
||||||
|
if (i == LEN(cmd)) {
|
||||||
|
pr_err("command '%s' not found\n", tokenized_line[0]);
|
||||||
|
destroy_tokenized_line(tokenized_line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int tll = tokenized_line_len(tokenized_line);
|
||||||
|
|
||||||
|
if ((cmd[i].arg_count + 1) != tll) {
|
||||||
|
pr_err("wrong amount of arguments for '%s' (%d required, %d got)\n", tokenized_line[0], cmd[i].arg_count, tll-1);
|
||||||
|
destroy_tokenized_line(tokenized_line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int (*executor)(void *) = cmd[i].process;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
if (cmd[i].arg_count) {
|
||||||
|
data = format_args(tokenized_line, cmd[i].arg_count, cmd[i].args);
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
destroy_tokenized_line(tokenized_line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int execution_result_code = executor(data);
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
destroy_tokenized_line(tokenized_line);
|
||||||
|
|
||||||
|
if (0x1 == execution_result_code)
|
||||||
|
return 0x1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
int ctrl_exit(void *d)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "print.h"
|
||||||
|
#include "fs.h"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
const static int BLOCK_ADDRESSES_PER_INODE = (FS_BLOCK_SIZE-sizeof(int)*4) / sizeof(int);
|
||||||
|
const static int BLOCK_ADDRESSES_PER_INODE_EXTENSION = (FS_BLOCK_SIZE-sizeof(int)) / sizeof(int);
|
||||||
|
|
||||||
|
|
||||||
|
static char used_file_path[FS_MAX_DEVICE_FILE_NAME_LEN+1];
|
||||||
|
static int used_file_fd;
|
||||||
|
static int write_permitted;
|
||||||
|
|
||||||
|
|
||||||
|
static int read_block(unsigned int block_no, void *data)
|
||||||
|
{
|
||||||
|
if (lseek(used_file_fd, block_no * FS_BLOCK_SIZE, SEEK_SET) < 0) {
|
||||||
|
pr_err("failed to seek to block %d (bs=%d) on device '%s'\n", block_no, FS_BLOCK_SIZE, used_file_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return read(used_file_fd, data, FS_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_block(unsigned int block_no, void *data)
|
||||||
|
{
|
||||||
|
if (lseek(used_file_fd, block_no * FS_BLOCK_SIZE, SEEK_SET) < 0) {
|
||||||
|
pr_err("failed to seek to block %d (bs=%d) on device '%s'\n", block_no, FS_BLOCK_SIZE, used_file_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return write(used_file_fd, data, FS_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int identify_fs(void)
|
||||||
|
{
|
||||||
|
if (lseek(used_file_fd, 0, SEEK_SET) < 0) {
|
||||||
|
pr_err("failed to seek '%s' to 0\n", used_file_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char read_buf[FS_BLOCK_SIZE];
|
||||||
|
{
|
||||||
|
int read_amount = read(used_file_fd, read_buf, FS_BLOCK_SIZE);
|
||||||
|
|
||||||
|
if (read_amount < 0) {
|
||||||
|
pr_err("failed to read from storage device\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_amount < FS_BLOCK_SIZE)
|
||||||
|
pr_warn("failed to read full first block of %d bytes\n", FS_BLOCK_SIZE);
|
||||||
|
|
||||||
|
if (read_amount == 0) {
|
||||||
|
pr_err("storage device size is 0\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return read_buf[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_allow_write(void *d)
|
||||||
|
{
|
||||||
|
if (used_file_fd <= 0) {
|
||||||
|
pr_err("no device present\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info("Allowing write operations on device '%s'\n", used_file_path);
|
||||||
|
write_permitted = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_prohibit_write(void *d)
|
||||||
|
{
|
||||||
|
if (used_file_fd <= 0) {
|
||||||
|
pr_err("no device present\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info("Prohibiting write operations on device '%s'\n", used_file_path);
|
||||||
|
write_permitted = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_create(void *d)
|
||||||
|
{
|
||||||
|
pr("[mock] Regular file '%s' created\n", *((char **) d));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_use(void *d)
|
||||||
|
{
|
||||||
|
char *fname = *((char **) d);
|
||||||
|
int name_len = strlen(fname);
|
||||||
|
|
||||||
|
if (name_len > FS_MAX_DEVICE_FILE_NAME_LEN) {
|
||||||
|
pr_err("device filename too long (> %d)\n", FS_MAX_DEVICE_FILE_NAME_LEN);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr("Using file '%s' as storage device\n", fname);
|
||||||
|
|
||||||
|
strcpy(used_file_path, fname);
|
||||||
|
|
||||||
|
if (used_file_fd > 0)
|
||||||
|
close(used_file_fd);
|
||||||
|
|
||||||
|
used_file_fd = open(fname, O_RDWR);
|
||||||
|
|
||||||
|
if (used_file_fd < 0) {
|
||||||
|
pr_err("failed to open filename '%s'\n", fname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_version = identify_fs();
|
||||||
|
if (!fs_version) {
|
||||||
|
pr_info("filesystem could not be identified on device '%s'\n", fname);
|
||||||
|
write_permitted = 0;
|
||||||
|
} else if (fs_version != 1) {
|
||||||
|
pr_warn("filesystem is corrupted or has unsupported version (0x%hhx)\n", fs_version);
|
||||||
|
write_permitted = 0;
|
||||||
|
} else if (fs_version == 1) {
|
||||||
|
pr_info("filesystem v1 has been identified on device '%s'\n", fname);
|
||||||
|
write_permitted = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_mkfs(void *d)
|
||||||
|
{
|
||||||
|
if (!write_permitted) {
|
||||||
|
pr_err("device '%s' is write-protected\n", used_file_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (used_file_fd <= 0) {
|
||||||
|
pr_err("storage device not present\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int max_inode_count = *((int *)d);
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (fstat(used_file_fd, &st) < 0) {
|
||||||
|
pr_err("could not stat device '%s'\n", used_file_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int block_count = st.st_size / FS_BLOCK_SIZE;
|
||||||
|
int blocks_used_for_bitmap = block_count / (FS_BLOCK_SIZE * 8);
|
||||||
|
if (block_count % (FS_BLOCK_SIZE * 8))
|
||||||
|
blocks_used_for_bitmap++;
|
||||||
|
|
||||||
|
if (blocks_used_for_bitmap > FS_MAX_BITMAP_SIZE) {
|
||||||
|
pr_err("memory bitmap is too large (%d blocks > %d)\n", blocks_used_for_bitmap, FS_MAX_BITMAP_SIZE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr("Formatting storage device '%s' of size %d (total_block_count = %d, bitmap_blocks = %d) with %d allowed inode pointers\n", used_file_path, st.st_size, block_count, blocks_used_for_bitmap, max_inode_count);
|
||||||
|
|
||||||
|
struct fs_header fsh = {};
|
||||||
|
fsh.version = 0x1;
|
||||||
|
fsh.max_inode_count = max_inode_count;
|
||||||
|
fsh.block_count = block_count;
|
||||||
|
|
||||||
|
pr("header size is %d bytes, writing it to the first block\n", sizeof(fsh));
|
||||||
|
|
||||||
|
int result = write_block(0, (void *) &fsh);
|
||||||
|
if (FS_BLOCK_SIZE != result) {
|
||||||
|
if (result < 0) {
|
||||||
|
pr_err("failed to write fs header to device '%s'\n", used_file_path);
|
||||||
|
} else {
|
||||||
|
pr_err("failed to write full block to device, written %d/%d bytes\n", result, FS_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char bitmap[blocks_used_for_bitmap * FS_BLOCK_SIZE];
|
||||||
|
memset(bitmap, 0, blocks_used_for_bitmap * FS_BLOCK_SIZE);
|
||||||
|
|
||||||
|
int blocks_used = 1 + blocks_used_for_bitmap;
|
||||||
|
|
||||||
|
//for (int i = 0; i < FS_MAX_BITMAP_SIZE; i++)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "print.h"
|
||||||
|
#include "cli.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
if (0x1 == cli_poll_process_next())
|
||||||
|
break;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue