diff --git a/kernel/core/fs/ext2_disk.c b/kernel/core/fs/ext2_disk.c index 10d09d43..662680dd 100644 --- a/kernel/core/fs/ext2_disk.c +++ b/kernel/core/fs/ext2_disk.c @@ -2,7 +2,7 @@ #include #include -#define EXT2_DEBUG_BLOCK_DESCRIPTORS 1 +#define EXT2_DEBUG_BLOCK_DESCRIPTORS 0 #define BLOCKSIZE 1024 #define SECTORSIZE 512 @@ -31,7 +31,9 @@ uint32_t ext2_disk_bg_descriptors = 0; #define RN ext2_root_fsnode #define DC ext2_disk_cache -#define BLOCKBIT(n) (bg_buffer[(n / 8)] & (1 << ((n % 8)))) +#define BLOCKBIT(n) (bg_buffer[((n) / 8)] & (1 << (((n) % 8)))) +#define BLOCKBYTE(n) (bg_buffer[((n) / 8)]) +#define SETBIT(n) (1 << (((n) % 8))) static uint32_t btos(uint32_t block) { return block * (BLOCKSIZE / SECTORSIZE); @@ -62,7 +64,9 @@ void ext2_disk_read_block(uint32_t block_no, uint8_t * buf) { void ext2_disk_write_block(uint32_t block_no, uint8_t * buf) { if (!block_no) return; ide_write_sector(DISK_PORT, 0, btos(block_no) + 0, (uint8_t *)((uint32_t)buf + 0)); - ide_write_sector(DISK_PORT, 0, btos(block_no) + 0, (uint8_t *)((uint32_t)buf + SECTORSIZE)); + timer_wait(10); + ide_write_sector(DISK_PORT, 0, btos(block_no) + 1, (uint8_t *)((uint32_t)buf + SECTORSIZE)); + timer_wait(10); int oldest = -1; uint32_t oldest_age = UINT32_MAX; for (uint32_t i = 0; i < CACHEENTRIES; ++i) { @@ -110,6 +114,56 @@ uint32_t ext2_disk_inode_block(ext2_inodetable_t * inode, uint32_t block, uint8_ return 0; } +ext2_inodetable_t * ext2_disk_alloc_inode(ext2_inodetable_t * parent, char * name) { +#if 0 + /* Allocate a new inode with parent as the parent directory node and name as the filename + * within that parent directory. Returns a pointer to a memory-copy of the node which + * the client can (and should) free. */ + ext2_inodetable_t * inode = (ext2_inodetable_t * )malloc(BLOCKSIZE); + uint32_t node_no = 0, node_offset = 0, group = 0; + char bg_buffer[BLOCKSIZE]; + /* Locate a block with an available inode. Will probably be the first block group. */ + for (uint32_t i = 0; i < BGDS; ++i) { + if (BGD[i].free_inodes_count > 0) { + kprintf("Group %d has %d free inodes!\n", i, BGD[i].free_inodes_count); + ext2_disk_read_block(BGD[i].inode_bitmap, (uint8_t *)bg_buffer); + node_offset = 0; + while (BLOCKBIT(node_offset)) ++node_offset; + node_no = node_offset + ext2_disk_inodes_per_group * i + 1; + group = i; + break; + } + } + if (!node_no) { + free(inode); + return NULL; + } + /* Alright, we found an inode (node_no), we need to mark it as in-use... */ + uint8_t b = BLOCKBYTE(node_offset); + kprintf("Located an inode at #%d (%d), the byte for this block is currently set to %x\n", node_no, node_offset, (uint32_t)b); + b |= SETBIT(node_offset); + kprintf("We would want to set it to %x\n", (uint32_t)b); + kprintf("Setting it in our temporary buffer...\n"); + BLOCKBYTE(node_offset) = b; + for (uint32_t i = 0; i < BLOCKSIZE / 4; ++i) { + kprintf("%x", ((uint32_t *)bg_buffer)[i]); + } + kprintf("\nWriting back out.\n"); + ext2_disk_write_block(BGD[group].inode_bitmap, (uint8_t * )bg_buffer); + kprintf("Okay, now we need to update the available inodes count...\n"); + kprintf("it is %d, it should be %d\n", BGD[group].free_inodes_count, BGD[group].free_inodes_count - 1); + BGD[group].free_inodes_count -= 1; + for (uint32_t i = 0; i < BLOCKSIZE / 4; ++i) { + kprintf("%x", ((uint32_t *)BGD)[i]); + } + kprintf("\nOkay, writing the block descriptors back to disk.\n"); + ext2_disk_write_block(2, (uint8_t *)BGD); + kprintf("Alright, we have an inode (%d), time to write it out to disk and make the file in the directory.\n", node_no); + free(inode); +#endif + return NULL; +} + ext2_dir_t * ext2_disk_direntry(ext2_inodetable_t * inode, uint32_t index) { uint8_t * block = malloc(BLOCKSIZE); ext2_disk_inode_block(inode,0,block); diff --git a/kernel/core/kprintf.c b/kernel/core/kprintf.c index 12d3a35e..d210c341 100644 --- a/kernel/core/kprintf.c +++ b/kernel/core/kprintf.c @@ -163,6 +163,7 @@ int kgets_want = 0; int kgets_newline = 0; int kgets_cancel = 0; kgets_redraw_t kgets_redraw_func = NULL; +kgets_tab_complete_t kgets_tab_complete_func = NULL; static void kwrite( @@ -196,7 +197,11 @@ kgets_handler( if (kgets_redraw_func) { kgets_redraw_func(); } - kprintf(kgets_buffer); + kgets_redraw_buffer(); + return; + } else if (ch == '\t' && kgets_tab_complete_func) { + kgets_tab_complete_func(kgets_buffer); + kgets_collected = strlen(kgets_buffer); return; } else if (ch == '\n') { /* Newline finishes off the kgets() */ @@ -211,6 +216,10 @@ kgets_handler( } } +void kgets_redraw_buffer() { + kprintf(kgets_buffer); +} + /** * Synchronously get a string from the keyboard. * @@ -239,6 +248,7 @@ kgets( /* Disable the buffer */ keyboard_buffer_handler = NULL; kgets_redraw_func = NULL; + kgets_tab_complete_func = NULL; /* Return the string */ return kgets_collected; } diff --git a/kernel/core/shell.c b/kernel/core/shell.c index 80a826e4..a624be4a 100644 --- a/kernel/core/shell.c +++ b/kernel/core/shell.c @@ -203,10 +203,13 @@ uint32_t shell_cmd_ls(int argc, char * argv[]) { struct dirent * entry = NULL; int i = 0; fs_node_t * ls_node; + char * dir_path; if (argc < 2) { ls_node = shell.node; + dir_path = shell.path; } else { ls_node = kopen(argv[1], 0); + dir_path = argv[1]; if (!ls_node) { kprintf("%s: Could not stat directory '%s'.\n", argv[0], argv[1]); return 1; @@ -215,12 +218,12 @@ uint32_t shell_cmd_ls(int argc, char * argv[]) { entry = readdir_fs(ls_node, i); while (entry != NULL) { char * filename = malloc(sizeof(char) * 1024); - memcpy(filename, shell.path, strlen(shell.path)); - if (!strcmp(shell.path,"/")) { - memcpy((void *)((uintptr_t)filename + strlen(shell.path)),entry->name,strlen(entry->name)+1); + memcpy(filename, dir_path, strlen(dir_path)); + if (!strcmp(dir_path,"/")) { + memcpy((void *)((uintptr_t)filename + strlen(dir_path)),entry->name,strlen(entry->name)+1); } else { - filename[strlen(shell.path)] = '/'; - memcpy((void *)((uintptr_t)filename + strlen(shell.path) + 1),entry->name,strlen(entry->name)+1); + filename[strlen(dir_path)] = '/'; + memcpy((void *)((uintptr_t)filename + strlen(dir_path) + 1),entry->name,strlen(entry->name)+1); } fs_node_t * chd = kopen(filename, 0); if (chd) { @@ -308,6 +311,14 @@ uint32_t shell_cmd_writedisk(int argc, char * argv[]) { return 0; } +#include +ext2_inodetable_t * ext2_disk_alloc_inode(ext2_inodetable_t * parent, char * name); + +uint32_t shell_cmd_testing(int argc, char * argv[]) { + ext2_inodetable_t * derp = ext2_disk_alloc_inode(NULL, "test"); + return 0; +} + void install_commands() { shell_install_command("cd", shell_cmd_cd); shell_install_command("ls", shell_cmd_ls); @@ -319,12 +330,124 @@ void install_commands() { shell_install_command("read-sb", shell_cmd_readsb); shell_install_command("read-disk", shell_cmd_readdisk); shell_install_command("write-disk", shell_cmd_writedisk); + shell_install_command("test-alloc-block", shell_cmd_testing); +} + +void add_path_contents() { + struct dirent * entry = NULL; + int i = 0; + fs_node_t * ls_node; + ls_node = kopen("/bin", 0); + char * dir_path = "/bin"; + if (!ls_node) { + kprintf("Failed to open /bin\n"); + return; + } + entry = readdir_fs(ls_node, i); + while (entry != NULL) { + char * filename = malloc(sizeof(char) * 1024); + memcpy(filename, dir_path, strlen(dir_path)); + filename[strlen(dir_path)] = '/'; + memcpy((void *)((uintptr_t)filename + strlen(dir_path) + 1),entry->name,strlen(entry->name)+1); + fs_node_t * chd = kopen(filename, 0); + if (chd) { + if (chd->flags & FS_DIRECTORY) { + } else if ((chd->mask & 0x001) || (chd->mask & 0x008) || (chd->mask & 0x040)) { + char * s = malloc(sizeof(char) * (strlen(entry->name) + 1)); + memcpy(s, entry->name, strlen(entry->name) + 1); + shell_install_command(s, NULL); + } + close_fs(chd); + } + free(filename); + free(entry); + i++; + entry = readdir_fs(ls_node, i); + } + if (ls_node != shell.node) { + close_fs(ls_node); + } +} + +void tab_complete_shell(char * buffer) { + char buf[1024]; + memcpy(buf, buffer, 1024); + char * pch; + char * cmd; + char * save; + pch = strtok_r(buf," ",&save); + cmd = pch; + char * argv[1024]; /* Command tokens (space-separated elements) */ + int argc = 0; + if (!cmd) { + argv[0] = ""; + argc = 1; + } else { + while (pch != NULL) { + argv[argc] = (char *)pch; + ++argc; + pch = strtok_r(NULL," ",&save); + } + } + argv[argc] = NULL; + if (argc < 2) { + if (buffer[strlen(buffer)-1] == ' ' || argc == 0) { + kprintf("\n"); + for (uint32_t i = 0; i < shell_commands_len; ++i) { + kprintf(shell_commands[i]); + if (i < shell_commands_len - 1) { + kprintf(", "); + } + } + kprintf("\n"); + redraw_shell(); + kgets_redraw_buffer(); + return; + } else { + uint32_t count = 0, j = 0; + for (uint32_t i = 0; i < shell_commands_len; ++i) { + if (strspn(shell_commands[i], argv[0]) == strlen(argv[0])) { + count++; + } + } + for (uint32_t i = 0; i < shell_commands_len; ++i) { + if (strspn(shell_commands[i], argv[0]) == strlen(argv[0])) { + if (count == 1) { + for (uint32_t j = 0; j < strlen(buffer); ++j) { + kprintf("\x08 \x08"); + } + kprintf(shell_commands[i]); + memcpy(buffer, shell_commands[i], strlen(shell_commands[i]) + 1); + return; + } + } + } + kprintf("\n"); + for (uint32_t i = 0; i < shell_commands_len; ++i) { + if (strspn(shell_commands[i], argv[0]) == strlen(argv[0])) { + kprintf(shell_commands[i]); + ++j; + if (j < count) { + kprintf(", "); + } + } + } + kprintf("\n"); + redraw_shell(); + kgets_redraw_buffer(); + return; + } + } else { + /* Complete path names */ + kprintf("%d\n", argc); + } } void start_shell() { init_shell(); install_commands(); + add_path_contents(); while (1) { /* Read buffer */ shell_update_time(); @@ -333,6 +456,7 @@ start_shell() { int size; /* Read commands */ kgets_redraw_func = redraw_shell; + kgets_tab_complete_func = tab_complete_shell; size = kgets((char *)&buffer, 1023); if (size < 1) { continue; diff --git a/kernel/include/system.h b/kernel/include/system.h index 389f7e3e..ca050beb 100644 --- a/kernel/include/system.h +++ b/kernel/include/system.h @@ -127,6 +127,9 @@ extern int sprintf(char *buf, const char *fmt, ...); extern int kgets(char *buf, int size); typedef void (*kgets_redraw_t)(); extern kgets_redraw_t kgets_redraw_func; +typedef void (*kgets_tab_complete_t)(char *); +extern kgets_tab_complete_t kgets_tab_complete_func; +extern void kgets_redraw_buffer(); /* Memory Management */ extern uintptr_t placement_pointer;