Parcourir la source

Added ls program and check for file and dirname length

bart il y a 7 mois
Parent
commit
93dfd54dbb
3 fichiers modifiés avec 161 ajouts et 95 suppressions
  1. 14 46
      BCC/BDOS/lib/brfs.c
  2. 0 49
      BCC/BDOS/lib/shell.c
  3. 147 0
      BCC/userBDOS/ls.c

+ 14 - 46
BCC/BDOS/lib/brfs.c

@@ -380,6 +380,13 @@ void brfs_format(word blocks, word words_per_block, char* label, word full_forma
 */
 word brfs_create_directory(char* parent_dir_path, char* dirname)
 {
+  // Check length of dirname
+  if (strlen(dirname) >= 16)
+  {
+    uprintln("Directory name too long!");
+    return 0;
+  }
+  
   struct brfs_superblock* superblock = (struct brfs_superblock*) brfs_ram_storage;
 
   word* brfs_data_block_addr = brfs_ram_storage + SUPERBLOCK_SIZE + superblock->total_blocks;
@@ -467,6 +474,13 @@ word brfs_create_directory(char* parent_dir_path, char* dirname)
 */
 word brfs_create_file(char* parent_dir_path, char* filename)
 {
+  // Check length of filename
+  if (strlen(filename) >= 16)
+  {
+    uprintln("Filename too long!");
+    return 0;
+  }
+
   struct brfs_superblock* superblock = (struct brfs_superblock*) brfs_ram_storage;
 
   word* brfs_data_block_addr = brfs_ram_storage + SUPERBLOCK_SIZE + superblock->total_blocks;
@@ -547,52 +561,6 @@ word brfs_create_file(char* parent_dir_path, char* filename)
   return 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->words_per_block);
-  word dir_entries_max = superblock->words_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[17];
-      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("");
-}
-
 /**
  * Reads all directory entries of a directory into a buffer
  * dir_path: full path of the directory

+ 0 - 49
BCC/BDOS/lib/shell.c

@@ -215,44 +215,6 @@ word shell_run_program(word run_from_path)
   return 1;
 }
 
-/**
- * List the contents of a directory (TMP function until separate ls program is implemented)
- * dir_path: full path of the directory
-*/
-void shell_list_directory(char* dir_path)
-{
-  // 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)
-  {
-    GFX_PrintConsole("Directory not found\n");
-    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->words_per_block);
-  word dir_entries_max = superblock->words_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[17];
-      strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
-      GFX_PrintConsole(decompressed_filename);
-      GFX_PrintConsole(" FAT: ");
-      GFX_PrintDecConsole((dir_entry->fat_idx));
-      GFX_PrintConsole(" Flg: ");
-      GFX_PrintDecConsole((dir_entry->flags));
-      GFX_PrintConsole(" Size: ");
-      GFX_PrintDecConsole((dir_entry->filesize));
-      GFX_PrintConsole("\n");
-    }
-  }
-}
-
 /**
  * Process dots in path so that ".." goes up one directory and "." is skipped
 */
@@ -414,17 +376,6 @@ void shell_handle_command()
     GFX_clearWindowpaletteTable();
     GFX_cursor = 0;
   }
-  else if (strcmp(shell_tokens[0], "ls") == 0)
-  {
-    if (shell_num_tokens > 1)
-    {
-      shell_list_directory(shell_tokens[1]);
-    }
-    else
-    {
-      shell_list_directory(shell_path);
-    }
-  }
   else if (strcmp(shell_tokens[0], "help") == 0)
   {
     shell_print_help();

+ 147 - 0
BCC/userBDOS/ls.c

@@ -0,0 +1,147 @@
+#define word char
+
+#include "lib/math.c"
+#include "lib/stdlib.c"
+#include "lib/sys.c"
+#include "lib/brfs.c"
+
+/**
+ * List the contents of a directory
+ * Sort by filename
+*/
+void list_dir(char* path)
+{
+  struct brfs_dir_entry entries[MAX_DIR_ENTRIES];
+  word num_entries = fs_readdir(path, entries);
+
+  // Keep track of the longest filename for formatting
+  word max_filename_length = 0;
+
+  // Sort entries by filename
+  word i, j;
+  for (i = 0; i < num_entries - 1; i++)
+  {
+    for (j = 0; j < num_entries - i - 1; j++)
+    {
+      char decompressed_filename1[17];
+      strdecompress(decompressed_filename1, entries[j].filename);
+
+      char decompressed_filename2[17];
+      strdecompress(decompressed_filename2, entries[j + 1].filename);
+
+      // Update max_filename_length
+      // This works because . is always the first entry (skipped by this check)
+      if (strlen(decompressed_filename2) > max_filename_length)
+      {
+        max_filename_length = strlen(decompressed_filename2);
+      }
+
+      // Sort by filename
+      if (strcmp(decompressed_filename1, decompressed_filename2) > 0)
+      {
+        // Swap filenames
+        struct brfs_dir_entry temp = entries[j];
+        entries[j] = entries[j + 1];
+        entries[j + 1] = temp;
+      }
+    }
+  }
+
+  for (i = 0; i < num_entries; i++)
+  {
+    // Create entire line with blank spaces
+    char output_line[40];
+    memset(output_line, ' ', 40);
+    output_line[40] = 0;
+
+    // Add filename
+    struct brfs_dir_entry entry = entries[i];
+    strdecompress(output_line, entry.filename);
+    output_line[strlen(output_line)] = ' ';
+
+    // Add filesize if file
+    if ((entry.flags & 0x01) == 0)
+    {
+      char buffer[11];
+      itoa(entry.filesize, buffer);
+      memcpy(output_line + max_filename_length + 1, buffer, strlen(buffer));
+    }
+    
+    bdos_print(output_line);
+  }
+}
+
+int main() 
+{
+  // Read number of arguments
+  word argc = shell_argc();
+  char** args = shell_argv();
+
+  // Read file/dir name if provided
+  char* fname;
+  if (argc < 2)
+  {
+    fname = fs_getcwd();
+  }
+  else
+  {
+    fname = args[1];
+  } 
+
+  // Create absolute path
+  char absolute_path[MAX_PATH_LENGTH];
+  if (fname[0] != '/')
+  {
+    char* cwd = fs_getcwd();
+    strcpy(absolute_path, cwd);
+    if (absolute_path[strlen(absolute_path) - 1] != '/')
+    {
+      strcat(absolute_path, "/");
+    }
+    strcat(absolute_path, fname);
+  }
+  else
+  {
+    strcpy(absolute_path, fname);
+  }
+
+  // If path is root, list root directory
+  if (strcmp(absolute_path, "/") == 0)
+  {
+    list_dir("/");
+    return 'q';
+  }
+
+  // Check if fname is a file or directory
+  struct brfs_dir_entry* entry = (struct brfs_dir_entry*)fs_stat(absolute_path);
+  if ((word)entry == -1)
+  {
+    bdos_println("Dir not found");
+    return 'q';
+  }
+
+  if ((entry->flags & 0x01) == 0)
+  {
+    // File
+    bdos_println("Not a directory");
+  }
+  else
+  {
+    // Directory
+    list_dir(absolute_path);
+  }
+
+  return 'q';
+}
+
+void interrupt()
+{
+  // Handle all interrupts
+  word i = get_int_id();
+  switch(i)
+  {
+    case INTID_TIMER1:
+      timer1Value = 1;  // Notify ending of timer1
+      break;
+  }
+}