|
@@ -39,20 +39,28 @@ Implementation Details:
|
|
|
- (1) file size [in words, not bytes]
|
|
|
*/
|
|
|
|
|
|
+/*
|
|
|
+Implementation Notes:
|
|
|
+- Current directory is managed by the application/OS, not the FS. Directory (or file) can be checked to exist using stat()
|
|
|
+- Updating a file: might be better to delete and create a new one, but this is better be done by the application instead of the FS
|
|
|
+- Write should start writing at the cursor and jump to the next block (also create in FAT) if the end is reached
|
|
|
+- No delete/backspace, only delete entire file or overwrite data
|
|
|
+*/
|
|
|
+
|
|
|
/*
|
|
|
Required operations:
|
|
|
-- Format
|
|
|
-- Create directory
|
|
|
-- Create file
|
|
|
-- Open file (allow multiple files open at once)
|
|
|
-- Close file (update dir entry and check/update all FAT entries)
|
|
|
-- Set cursor
|
|
|
-- Get cursor
|
|
|
-- Read file
|
|
|
-- Write file
|
|
|
-- Delete entire file (deleting part of file is not a thing)
|
|
|
-- Change directory
|
|
|
-- List directory
|
|
|
+- [x] Format
|
|
|
+- [x] Create directory
|
|
|
+- [x] Create file
|
|
|
+- [] Open file (not a dir!) (allow multiple files open at once)
|
|
|
+- [] Close file (update dir entry and check/update all FAT entries)
|
|
|
+- [] Stat (returns dir entry)
|
|
|
+- [] Set cursor
|
|
|
+- [] Get cursor
|
|
|
+- [] Read file
|
|
|
+- [] Write file
|
|
|
+- [] Delete entire file (deleting part of file is not a thing)
|
|
|
+- [x] List directory
|
|
|
*/
|
|
|
|
|
|
#define word char
|
|
@@ -63,12 +71,14 @@ Required operations:
|
|
|
|
|
|
#define BRFS_RAM_STORAGE_ADDR 0x600000
|
|
|
|
|
|
+#define MAX_PATH_LENGTH 127
|
|
|
+
|
|
|
+// Length of structs, should not be changed
|
|
|
#define SUPERBLOCK_SIZE 16
|
|
|
+#define DIR_ENTRY_SIZE 8
|
|
|
|
|
|
word *brfs_ram_storage = (word*) BRFS_RAM_STORAGE_ADDR; // RAM storage of file system
|
|
|
|
|
|
-word brfs_current_dir = 0; // Current directory index, points to block in data section
|
|
|
-
|
|
|
// 16 words long
|
|
|
struct brfs_superblock
|
|
|
{
|
|
@@ -89,6 +99,144 @@ struct brfs_dir_entry
|
|
|
word filesize; // file size in words, not bytes
|
|
|
};
|
|
|
|
|
|
+/**
|
|
|
+ * Create a hexdump like dump of a section of memory
|
|
|
+ * addr: address of the section
|
|
|
+ * len: length of the section in words
|
|
|
+ * linesize: number of words per line to print
|
|
|
+*/
|
|
|
+void brfs_dump_section(word* addr, word len, word linesize)
|
|
|
+{
|
|
|
+ char buf[16];
|
|
|
+ word i;
|
|
|
+ for (i = 0; i < len; i++)
|
|
|
+ {
|
|
|
+ itoah(addr[i], buf);
|
|
|
+ if (strlen(buf+2) == 1)
|
|
|
+ uprintc('0');
|
|
|
+ uprint(buf+2);
|
|
|
+
|
|
|
+ uprintc(' ');
|
|
|
+
|
|
|
+ // newline every linesize words
|
|
|
+ // also print last linesize words as chars if alphanum
|
|
|
+ if (i != 0 && MATH_modU(i+1, linesize) == 0)
|
|
|
+ {
|
|
|
+ uprint(" ");
|
|
|
+ word j;
|
|
|
+ for (j = i - (linesize-1); j < i+1; j++)
|
|
|
+ {
|
|
|
+ if (isalnum(addr[j]) || addr[j] == ' ')
|
|
|
+ uprintc(addr[j]);
|
|
|
+ else
|
|
|
+ uprintc('.');
|
|
|
+ }
|
|
|
+ uprintc('\n');
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Create a raw filesystem dump over UART
|
|
|
+ * fatsize: size of the FAT table in words
|
|
|
+ * datasize: size of the data section in words
|
|
|
+*/
|
|
|
+void brfs_dump(word fatsize, word datasize)
|
|
|
+{
|
|
|
+ // Superblock dump
|
|
|
+ uprintln("Superblock:");
|
|
|
+ brfs_dump_section(brfs_ram_storage, SUPERBLOCK_SIZE, 16);
|
|
|
+
|
|
|
+ // FAT dump
|
|
|
+ uprintln("\nFAT:");
|
|
|
+ brfs_dump_section(brfs_ram_storage+SUPERBLOCK_SIZE, fatsize, 8);
|
|
|
+
|
|
|
+ // Datablock dump
|
|
|
+ uprintln("\nData:");
|
|
|
+ brfs_dump_section(brfs_ram_storage+SUPERBLOCK_SIZE+fatsize, datasize, 32);
|
|
|
+
|
|
|
+ uprintc('\n');
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Return the FAT index of a directory, or -1 if not found
|
|
|
+ * dir_path: full path of the directory
|
|
|
+*/
|
|
|
+word brfs_get_fat_idx_of_dir(char* dir_path)
|
|
|
+{
|
|
|
+ // Check length of path
|
|
|
+ if (strlen(dir_path) > MAX_PATH_LENGTH)
|
|
|
+ {
|
|
|
+ uprintln("Path too long!");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Start with root directory
|
|
|
+ word current_dir_fat_idx = 0;
|
|
|
+
|
|
|
+ // Check if root directory is requested
|
|
|
+ if (strcmp(dir_path, "/") == 1)
|
|
|
+ {
|
|
|
+ return current_dir_fat_idx;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Copy dir_path, size + 1 for null terminator
|
|
|
+ // Since strtok modifies the string
|
|
|
+ char dir_path_copy[MAX_PATH_LENGTH+1];
|
|
|
+ strcpy(dir_path_copy, dir_path);
|
|
|
+
|
|
|
+ struct brfs_superblock* superblock = (struct brfs_superblock*) brfs_ram_storage;
|
|
|
+ word* brfs_data_block_addr = brfs_ram_storage + SUPERBLOCK_SIZE + superblock->total_blocks;
|
|
|
+ word dir_entries_max = superblock->bytes_per_block / sizeof(struct brfs_dir_entry);
|
|
|
+
|
|
|
+ // Split path by '/' and traverse directories
|
|
|
+ char* token = strtok(dir_path_copy, "/");
|
|
|
+ while (token != (word*)-1)
|
|
|
+ {
|
|
|
+ // Find token in current directory
|
|
|
+ word* dir_addr = brfs_data_block_addr + (current_dir_fat_idx * superblock->bytes_per_block);
|
|
|
+ word found_dir = 0; // Keep track if token is found in current directory
|
|
|
+ word i;
|
|
|
+ for (i = 0; i < dir_entries_max; i++)
|
|
|
+ {
|
|
|
+ struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (dir_addr + (i * sizeof(struct brfs_dir_entry)));
|
|
|
+ if (dir_entry->filename[0] != 0)
|
|
|
+ {
|
|
|
+ char decompressed_filename[16];
|
|
|
+ strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
|
|
|
+ if (strcmp(decompressed_filename, token) == 1)
|
|
|
+ {
|
|
|
+ // Found token in current directory
|
|
|
+ // Set current directory to token's FAT index
|
|
|
+ current_dir_fat_idx = dir_entry->fat_idx;
|
|
|
+ found_dir = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // If token not found in current directory, return -1
|
|
|
+ if (!found_dir)
|
|
|
+ {
|
|
|
+ uprint("Directory ");
|
|
|
+ uprint(dir_path);
|
|
|
+ uprintln(" not found!");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ token = strtok((word*)-1, "/");
|
|
|
+ }
|
|
|
+ return current_dir_fat_idx;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Given the address of the FAT table and the number of blocks, find the next free block
|
|
|
+ * Returns -1 if no free block is found
|
|
|
+ * fat_addr: address of the FAT table
|
|
|
+ * blocks: number of blocks in the FAT table
|
|
|
+*/
|
|
|
word brfs_find_next_free_block(word* fat_addr, word blocks)
|
|
|
{
|
|
|
word i = 0;
|
|
@@ -108,6 +256,12 @@ word brfs_find_next_free_block(word* fat_addr, word blocks)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Given the address of a directory data block and the maximum number of entries, find the next free directory entry
|
|
|
+ * Returns -1 if no free entry is found
|
|
|
+ * dir_addr: address of the directory data block (not the FAT idx)
|
|
|
+ * dir_entries_max: maximum number of entries in the directory
|
|
|
+*/
|
|
|
word brfs_find_next_free_dir_entry(word* dir_addr, word dir_entries_max)
|
|
|
{
|
|
|
word i = 0;
|
|
@@ -127,15 +281,23 @@ word brfs_find_next_free_dir_entry(word* dir_addr, word dir_entries_max)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Create a single directory entry
|
|
|
+ * dir_entry: pointer to the directory entry to be created
|
|
|
+ * filename: name of the file, max 16 chars and uncompressed
|
|
|
+ * fat_idx: index of the first FAT block of the file/directory
|
|
|
+ * filesize: size of the file in words
|
|
|
+ * flags: flags of the file/directory
|
|
|
+*/
|
|
|
void brfs_create_single_dir_entry(struct brfs_dir_entry* dir_entry, char* filename, word fat_idx, word filesize, word flags)
|
|
|
{
|
|
|
// Initialize to 0
|
|
|
- memset(dir_entry, 0, sizeof(*dir_entry));
|
|
|
+ memset((char*)dir_entry, 0, sizeof(*dir_entry));
|
|
|
|
|
|
// Set filename
|
|
|
char compressed_filename[4] = {0,0,0,0};
|
|
|
strcompress(compressed_filename, filename);
|
|
|
- memcpy(&(dir_entry->filename), compressed_filename, sizeof(compressed_filename));
|
|
|
+ memcpy((char*)&(dir_entry->filename), compressed_filename, sizeof(compressed_filename));
|
|
|
|
|
|
// Set other fields
|
|
|
dir_entry->fat_idx = fat_idx;
|
|
@@ -143,178 +305,101 @@ void brfs_create_single_dir_entry(struct brfs_dir_entry* dir_entry, char* filena
|
|
|
dir_entry->filesize = filesize;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Initialize a directory with . and .. entries
|
|
|
+ * dir_addr: address of the directory data block
|
|
|
+ * dir_entries_max: maximum number of entries in the directory
|
|
|
+ * dir_fat_idx: index of the FAT block of the directory
|
|
|
+ * parent_fat_idx: index of the FAT block of the parent directory
|
|
|
+*/
|
|
|
void brfs_init_directory(word* dir_addr, word dir_entries_max, word dir_fat_idx, word parent_fat_idx)
|
|
|
{
|
|
|
// Create . entry
|
|
|
struct brfs_dir_entry dir_entry;
|
|
|
brfs_create_single_dir_entry(&dir_entry, ".", dir_fat_idx, dir_entries_max*sizeof(struct brfs_dir_entry), 1);
|
|
|
// Copy to first data entry
|
|
|
- memcpy(dir_addr, &dir_entry, sizeof(dir_entry));
|
|
|
+ memcpy(dir_addr, (char*)&dir_entry, sizeof(dir_entry));
|
|
|
|
|
|
// Create .. entry
|
|
|
brfs_create_single_dir_entry(&dir_entry, "..", parent_fat_idx, dir_entries_max*sizeof(struct brfs_dir_entry), 1);
|
|
|
// Copy to second data entry
|
|
|
- memcpy(dir_addr+sizeof(dir_entry), &dir_entry, sizeof(dir_entry));
|
|
|
+ memcpy(dir_addr+sizeof(dir_entry), (char*)&dir_entry, sizeof(dir_entry));
|
|
|
|
|
|
// Set FAT table
|
|
|
brfs_ram_storage[SUPERBLOCK_SIZE + dir_fat_idx] = -1;
|
|
|
}
|
|
|
|
|
|
-// Creates hexdump like dump
|
|
|
-void brfs_dump_section(word* addr, word len, word linesize)
|
|
|
-{
|
|
|
- char buf[16];
|
|
|
- word i;
|
|
|
- for (i = 0; i < len; i++)
|
|
|
- {
|
|
|
- itoah(addr[i], buf);
|
|
|
- if (strlen(buf+2) == 1)
|
|
|
- uprintc('0');
|
|
|
- uprint(buf+2);
|
|
|
-
|
|
|
- uprintc(' ');
|
|
|
-
|
|
|
- // newline every linesize words
|
|
|
- // also print last linesize words as chars if alphanum
|
|
|
- if (i != 0 && MATH_modU(i+1, linesize) == 0)
|
|
|
- {
|
|
|
- uprint(" ");
|
|
|
- word j;
|
|
|
- for (j = i - (linesize-1); j < i+1; j++)
|
|
|
- {
|
|
|
- if (isalnum(addr[j]) || addr[j] == ' ')
|
|
|
- uprintc(addr[j]);
|
|
|
- else
|
|
|
- uprintc('.');
|
|
|
- }
|
|
|
- uprintc('\n');
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void brfs_dump(word* ram_addr, word fatsize, word datasize)
|
|
|
-{
|
|
|
- // Superblock dump
|
|
|
- uprintln("Superblock:");
|
|
|
- brfs_dump_section(ram_addr, SUPERBLOCK_SIZE, 16);
|
|
|
-
|
|
|
- // FAT dump
|
|
|
- uprintln("\nFAT:");
|
|
|
- brfs_dump_section(ram_addr+SUPERBLOCK_SIZE, fatsize, 8);
|
|
|
-
|
|
|
- // Datablock dump
|
|
|
- uprintln("\nData:");
|
|
|
- brfs_dump_section(ram_addr+SUPERBLOCK_SIZE+fatsize, datasize, 32);
|
|
|
-
|
|
|
- uprintc('\n');
|
|
|
-}
|
|
|
-
|
|
|
-void brfs_list_directory(word* ram_addr)
|
|
|
-{
|
|
|
- struct brfs_superblock* superblock = (struct brfs_superblock*) ram_addr;
|
|
|
- word* dir_addr = ram_addr + SUPERBLOCK_SIZE + superblock->total_blocks + (brfs_current_dir * superblock->bytes_per_block);
|
|
|
- word dir_entries_max = superblock->bytes_per_block / sizeof(struct brfs_dir_entry);
|
|
|
-
|
|
|
- uprintln("-------------------");
|
|
|
-
|
|
|
- word i;
|
|
|
- for (i = 0; i < dir_entries_max; i++)
|
|
|
- {
|
|
|
- struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (dir_addr + (i * sizeof(struct brfs_dir_entry)));
|
|
|
- if (dir_entry->filename[0] != 0)
|
|
|
- {
|
|
|
- uprint("Filename: ");
|
|
|
- char decompressed_filename[16];
|
|
|
- strdecompress(decompressed_filename, &(dir_entry->filename));
|
|
|
- uprintln(decompressed_filename);
|
|
|
- uprint("FAT idx: ");
|
|
|
- uprintDec((dir_entry->fat_idx));
|
|
|
- uprint("Flags: ");
|
|
|
- uprintDec((dir_entry->flags));
|
|
|
- uprint("Filesize: ");
|
|
|
- uprintDec((dir_entry->filesize));
|
|
|
- uprintc('\n');
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void brfs_change_directory(word* ram_addr, char* dirname)
|
|
|
-{
|
|
|
- struct brfs_superblock* superblock = (struct brfs_superblock*) ram_addr;
|
|
|
- word* dir_addr = ram_addr + SUPERBLOCK_SIZE + superblock->total_blocks + (brfs_current_dir * superblock->bytes_per_block);
|
|
|
- word dir_entries_max = superblock->bytes_per_block / sizeof(struct brfs_dir_entry);
|
|
|
-
|
|
|
- word i;
|
|
|
- for (i = 0; i < dir_entries_max; i++)
|
|
|
- {
|
|
|
- struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (dir_addr + (i * sizeof(struct brfs_dir_entry)));
|
|
|
- if (dir_entry->filename[0] != 0)
|
|
|
- {
|
|
|
- char decompressed_filename[16];
|
|
|
- strdecompress(decompressed_filename, &(dir_entry->filename));
|
|
|
- if (strcmp(decompressed_filename, dirname) == 1)
|
|
|
- {
|
|
|
- brfs_current_dir = dir_entry->fat_idx;
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- uprintln("Directory not found!");
|
|
|
-}
|
|
|
-
|
|
|
-void brfs_format(word* ram_addr, word blocks, word bytes_per_block, char* label, word full_format)
|
|
|
+/**
|
|
|
+ * Format the ram storage as a BRFS filesystem
|
|
|
+ * blocks: number of blocks in the filesystem
|
|
|
+ * bytes_per_block: number of bytes per block
|
|
|
+ * label: label of the filesystem
|
|
|
+ * full_format: if 1, initialize data section to 0
|
|
|
+*/
|
|
|
+void brfs_format(word blocks, word bytes_per_block, char* label, word full_format)
|
|
|
{
|
|
|
// Create a superblock
|
|
|
struct brfs_superblock superblock;
|
|
|
|
|
|
// Initialize to 0
|
|
|
- memset(&superblock, 0, sizeof(superblock));
|
|
|
+ memset((char*)&superblock, 0, sizeof(superblock));
|
|
|
|
|
|
// Set values of superblock
|
|
|
superblock.total_blocks = blocks;
|
|
|
superblock.bytes_per_block = bytes_per_block;
|
|
|
- strcpy(&(superblock.label), label);
|
|
|
+ strcpy((char*)&superblock.label, label);
|
|
|
superblock.brfs_version = 1;
|
|
|
|
|
|
// Copy superblock to head of ram addr
|
|
|
- memcpy(ram_addr, &superblock, sizeof(superblock));
|
|
|
+ memcpy(brfs_ram_storage, (char*)&superblock, sizeof(superblock));
|
|
|
|
|
|
|
|
|
// Create FAT
|
|
|
- memset(ram_addr + SUPERBLOCK_SIZE, 0, blocks);
|
|
|
+ memset(brfs_ram_storage + SUPERBLOCK_SIZE, 0, blocks);
|
|
|
|
|
|
// Create Data section
|
|
|
if (full_format)
|
|
|
{
|
|
|
- memset(ram_addr + SUPERBLOCK_SIZE + blocks, 0, blocks * bytes_per_block);
|
|
|
+ memset(brfs_ram_storage + SUPERBLOCK_SIZE + blocks, 0, blocks * bytes_per_block);
|
|
|
}
|
|
|
|
|
|
// Initialize root dir
|
|
|
word dir_entries_max = bytes_per_block / sizeof(struct brfs_dir_entry);
|
|
|
- brfs_init_directory(ram_addr + SUPERBLOCK_SIZE + blocks, dir_entries_max, 0, 0);
|
|
|
-
|
|
|
- brfs_current_dir = 0;
|
|
|
+ brfs_init_directory(brfs_ram_storage + SUPERBLOCK_SIZE + blocks, dir_entries_max, 0, 0);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
-* Creates directory in current directory
|
|
|
+/**
|
|
|
+ * Create a new directory in the directory of parent_dir_path
|
|
|
+ * parent_dir_path: full path of the parent directory
|
|
|
+ * dirname: name of the new directory
|
|
|
*/
|
|
|
-void brfs_create_directory(word* ram_addr, char* dirname)
|
|
|
+void brfs_create_directory(char* parent_dir_path, char* dirname)
|
|
|
{
|
|
|
- struct brfs_superblock* superblock = (struct brfs_superblock*) ram_addr;
|
|
|
+ struct brfs_superblock* superblock = (struct brfs_superblock*) brfs_ram_storage;
|
|
|
+
|
|
|
+ word* brfs_data_block_addr = brfs_ram_storage + SUPERBLOCK_SIZE + superblock->total_blocks;
|
|
|
|
|
|
// Find first free FAT block
|
|
|
- word next_free_block = brfs_find_next_free_block(ram_addr + SUPERBLOCK_SIZE, superblock->total_blocks);
|
|
|
+ word next_free_block = brfs_find_next_free_block(brfs_ram_storage + SUPERBLOCK_SIZE, superblock->total_blocks);
|
|
|
if (next_free_block == -1)
|
|
|
{
|
|
|
uprintln("No free blocks left!");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // Find data block address of parent directory path
|
|
|
+ word parent_dir_fat_idx = brfs_get_fat_idx_of_dir(parent_dir_path);
|
|
|
+ if (parent_dir_fat_idx == -1)
|
|
|
+ {
|
|
|
+ uprint("Parent directory ");
|
|
|
+ uprint(parent_dir_path);
|
|
|
+ uprintln(" not found!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
// Find first free dir entry
|
|
|
word next_free_dir_entry = brfs_find_next_free_dir_entry(
|
|
|
- ram_addr + SUPERBLOCK_SIZE + superblock->total_blocks + (brfs_current_dir * superblock->bytes_per_block),
|
|
|
+ brfs_data_block_addr + (parent_dir_fat_idx * superblock->bytes_per_block),
|
|
|
superblock->bytes_per_block / sizeof(struct brfs_dir_entry)
|
|
|
);
|
|
|
if (next_free_dir_entry == -1)
|
|
@@ -329,39 +414,53 @@ void brfs_create_directory(word* ram_addr, char* dirname)
|
|
|
|
|
|
// Copy dir entry to first free dir entry
|
|
|
memcpy(
|
|
|
- ram_addr + SUPERBLOCK_SIZE + superblock->total_blocks + (brfs_current_dir * superblock->bytes_per_block) + (next_free_dir_entry * sizeof(struct brfs_dir_entry)),
|
|
|
- &new_entry,
|
|
|
+ brfs_data_block_addr + (parent_dir_fat_idx * superblock->bytes_per_block) + (next_free_dir_entry * sizeof(struct brfs_dir_entry)),
|
|
|
+ (char*)&new_entry,
|
|
|
sizeof(new_entry)
|
|
|
);
|
|
|
|
|
|
// Initialize directory
|
|
|
word dir_entries_max = superblock->bytes_per_block / sizeof(struct brfs_dir_entry);
|
|
|
brfs_init_directory(
|
|
|
- ram_addr + SUPERBLOCK_SIZE + superblock->total_blocks + (next_free_block * superblock->bytes_per_block),
|
|
|
+ brfs_data_block_addr + (next_free_block * superblock->bytes_per_block),
|
|
|
dir_entries_max,
|
|
|
next_free_block,
|
|
|
- brfs_current_dir
|
|
|
+ parent_dir_fat_idx
|
|
|
);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
-* Creates an empty file in current directory
|
|
|
+/**
|
|
|
+ * Create a new file in the directory of parent_dir_path
|
|
|
+ * parent_dir_path: full path of the parent directory
|
|
|
+ * filename: name of the new file
|
|
|
*/
|
|
|
-void brfs_create_file(word* ram_addr, char* filename)
|
|
|
+void brfs_create_file(char* parent_dir_path, char* filename)
|
|
|
{
|
|
|
- struct brfs_superblock* superblock = (struct brfs_superblock*) ram_addr;
|
|
|
+ struct brfs_superblock* superblock = (struct brfs_superblock*) brfs_ram_storage;
|
|
|
+
|
|
|
+ word* brfs_data_block_addr = brfs_ram_storage + SUPERBLOCK_SIZE + superblock->total_blocks;
|
|
|
|
|
|
// Find first free FAT block
|
|
|
- word next_free_block = brfs_find_next_free_block(ram_addr + SUPERBLOCK_SIZE, superblock->total_blocks);
|
|
|
+ word next_free_block = brfs_find_next_free_block(brfs_ram_storage + SUPERBLOCK_SIZE, superblock->total_blocks);
|
|
|
if (next_free_block == -1)
|
|
|
{
|
|
|
uprintln("No free blocks left!");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // Find data block address of parent directory path
|
|
|
+ word parent_dir_fat_idx = brfs_get_fat_idx_of_dir(parent_dir_path);
|
|
|
+ if (parent_dir_fat_idx == -1)
|
|
|
+ {
|
|
|
+ uprint("Parent directory ");
|
|
|
+ uprint(parent_dir_path);
|
|
|
+ uprintln(" not found!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
// Find first free dir entry
|
|
|
word next_free_dir_entry = brfs_find_next_free_dir_entry(
|
|
|
- ram_addr + SUPERBLOCK_SIZE + superblock->total_blocks + (brfs_current_dir * superblock->bytes_per_block),
|
|
|
+ brfs_data_block_addr + (parent_dir_fat_idx * superblock->bytes_per_block),
|
|
|
superblock->bytes_per_block / sizeof(struct brfs_dir_entry)
|
|
|
);
|
|
|
if (next_free_dir_entry == -1)
|
|
@@ -376,20 +475,66 @@ void brfs_create_file(word* ram_addr, char* filename)
|
|
|
|
|
|
// Copy dir entry to first free dir entry
|
|
|
memcpy(
|
|
|
- ram_addr + SUPERBLOCK_SIZE + superblock->total_blocks + (brfs_current_dir * superblock->bytes_per_block) + (next_free_dir_entry * sizeof(struct brfs_dir_entry)),
|
|
|
- &new_entry,
|
|
|
+ brfs_data_block_addr + (parent_dir_fat_idx * superblock->bytes_per_block) + (next_free_dir_entry * sizeof(struct brfs_dir_entry)),
|
|
|
+ (char*)&new_entry,
|
|
|
sizeof(new_entry)
|
|
|
);
|
|
|
|
|
|
// Initialize file by setting data to 0
|
|
|
memset(
|
|
|
- ram_addr + SUPERBLOCK_SIZE + superblock->total_blocks + (next_free_block * superblock->bytes_per_block),
|
|
|
+ brfs_data_block_addr + (next_free_block * superblock->bytes_per_block),
|
|
|
0,
|
|
|
superblock->bytes_per_block
|
|
|
);
|
|
|
|
|
|
// Update FAT
|
|
|
- ram_addr[SUPERBLOCK_SIZE + next_free_block] = -1;
|
|
|
+ brfs_ram_storage[SUPERBLOCK_SIZE + next_free_block] = -1;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * List the contents of a directory over UART
|
|
|
+ * dir_path: full path of the directory
|
|
|
+*/
|
|
|
+void brfs_list_directory(char* dir_path)
|
|
|
+{
|
|
|
+ uprint("Listing directory ");
|
|
|
+ uprintln(dir_path);
|
|
|
+ uprintln("-------------------");
|
|
|
+
|
|
|
+ // Find data block address of parent directory path
|
|
|
+ word dir_fat_idx = brfs_get_fat_idx_of_dir(dir_path);
|
|
|
+ if (dir_fat_idx == -1)
|
|
|
+ {
|
|
|
+ uprint("Parent directory ");
|
|
|
+ uprint(dir_path);
|
|
|
+ uprintln(" not found!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ struct brfs_superblock* superblock = (struct brfs_superblock*) brfs_ram_storage;
|
|
|
+ word* dir_addr = brfs_ram_storage + SUPERBLOCK_SIZE + superblock->total_blocks + (dir_fat_idx * superblock->bytes_per_block);
|
|
|
+ word dir_entries_max = superblock->bytes_per_block / sizeof(struct brfs_dir_entry);
|
|
|
+
|
|
|
+ word i;
|
|
|
+ for (i = 0; i < dir_entries_max; i++)
|
|
|
+ {
|
|
|
+ struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (dir_addr + (i * sizeof(struct brfs_dir_entry)));
|
|
|
+ if (dir_entry->filename[0] != 0)
|
|
|
+ {
|
|
|
+ uprint("Filename: ");
|
|
|
+ char decompressed_filename[16];
|
|
|
+ strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
|
|
|
+ uprint(decompressed_filename);
|
|
|
+ uprint(" FAT idx: ");
|
|
|
+ uprintDec((dir_entry->fat_idx));
|
|
|
+ uprint(" Flags: ");
|
|
|
+ uprintDec((dir_entry->flags));
|
|
|
+ uprint(" Filesize: ");
|
|
|
+ uprintDec((dir_entry->filesize));
|
|
|
+ uprintc('\n');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ uprintln("");
|
|
|
}
|
|
|
|
|
|
|
|
@@ -408,25 +553,21 @@ int main()
|
|
|
word bytes_per_block = 32;
|
|
|
word full_format = 1;
|
|
|
|
|
|
- brfs_format(brfs_ram_storage, blocks, bytes_per_block, "Label", full_format);
|
|
|
-
|
|
|
- brfs_create_file(brfs_ram_storage, "file1");
|
|
|
-
|
|
|
- brfs_create_directory(brfs_ram_storage, "dir1");
|
|
|
+ brfs_format(blocks, bytes_per_block, "Label", full_format);
|
|
|
|
|
|
- brfs_list_directory(brfs_ram_storage);
|
|
|
+ brfs_dump(blocks, blocks*bytes_per_block);
|
|
|
|
|
|
- brfs_change_directory(brfs_ram_storage, "dir1");
|
|
|
+ brfs_list_directory("/");
|
|
|
|
|
|
- brfs_create_file(brfs_ram_storage, "file2");
|
|
|
+ brfs_create_file("/", "file1.txt");
|
|
|
|
|
|
- brfs_list_directory(brfs_ram_storage);
|
|
|
+ brfs_list_directory(".");
|
|
|
|
|
|
- brfs_change_directory(brfs_ram_storage, "..");
|
|
|
+ brfs_create_directory("..", "dir1");
|
|
|
+ brfs_create_file("dir1", "file2.txt");
|
|
|
|
|
|
- brfs_list_directory(brfs_ram_storage);
|
|
|
-
|
|
|
- brfs_dump(brfs_ram_storage, blocks, blocks*bytes_per_block);
|
|
|
+ brfs_list_directory(".");
|
|
|
+ brfs_list_directory("dir1");
|
|
|
|
|
|
return 'q';
|
|
|
}
|
|
@@ -441,25 +582,7 @@ void interrupt()
|
|
|
timer1Value = 1; // notify ending of timer1
|
|
|
break;
|
|
|
|
|
|
- case INTID_TIMER2:
|
|
|
- break;
|
|
|
-
|
|
|
- case INTID_UART0:
|
|
|
- break;
|
|
|
-
|
|
|
- case INTID_GPU:
|
|
|
- break;
|
|
|
-
|
|
|
- case INTID_TIMER3:
|
|
|
- break;
|
|
|
-
|
|
|
- case INTID_PS2:
|
|
|
- break;
|
|
|
-
|
|
|
- case INTID_UART1:
|
|
|
- break;
|
|
|
-
|
|
|
- case INTID_UART2:
|
|
|
+ default:
|
|
|
break;
|
|
|
}
|
|
|
}
|