From 2cf38a4ba2dd965c892767b0d8ee97e67f33b274 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 30 Aug 2004 04:50:13 +0000 Subject: [PATCH] Start work on filesystem code. --- src/filesys/file.c | 131 ++++++++++++++++++++++++------- src/filesys/file.h | 14 +++- src/filesys/filesys.c | 179 ++++++++++++++++++++++++++++++++---------- src/filesys/filesys.h | 12 ++- 4 files changed, 262 insertions(+), 74 deletions(-) diff --git a/src/filesys/file.c b/src/filesys/file.c index 0c18ab0..e6f282f 100644 --- a/src/filesys/file.c +++ b/src/filesys/file.c @@ -6,53 +6,126 @@ #include "lib.h" #include "malloc.h" +bool +file_open (struct file *file, const char *name) +{ + struct dir dir; + disk_sector_no hdr_sector; + bool success = false; + + dir_init (&dir, NUM_DIR_ENTRIES); + dir_read (&dir, &root_dir_file); + if (dir_lookup (&dir, name, &hdr_sector)) + success = file_open_sector (file, hdr_sector); + + dir_destroy (&dir); + return success; +} + +bool +file_open_sector (struct file *file, disk_sector_no hdr_sector) +{ + file->pos = 0; + return filehdr_read (&file->hdr, hdr_sector); +} + void file_close (struct file *file) { - filesys_stub_lock (); - filesys_stub_put_string ("close"); - filesys_stub_put_file (file); - filesys_stub_match_string ("close"); - filesys_stub_unlock (); + filehdr_destroy (file); } off_t file_read (struct file *file, void *buffer, off_t size) { - int32_t retval; + off_t retval = file_read_at (file, buffer, size, file->pos); + file->pos += retval; + return retval; +} - filesys_stub_lock (); - filesys_stub_put_string ("read"); - filesys_stub_put_file (file); - filesys_stub_put_uint32 (size); - filesys_stub_match_string ("read"); - retval = filesys_stub_get_int32 (); - if (retval > 0) +off_t +file_read_at (struct file *file, void *buffer_, off_t size, off_t start) +{ + uint8_t *buffer = buffer_; + off_t bytes_read = 0; + uint8_t *bounce; + + bounce = malloc (DISK_SECTOR_SIZE); + while (size > 0) { - ASSERT (retval <= size); - filesys_stub_get_bytes (buffer, retval); + /* Disk sector to read, starting byte offset within sector. */ + off_t sector_idx = filehdr_byte_to_sector (file->hdr); + int sector_ofs = start % DISK_SECTOR_SIZE; + + /* Bytes left in file, bytes left in sector. */ + off_t file_left = filehdr_size (file->hdr) - start; + off_t sector_left = DISK_SECTOR_SIZE - sector_ofs; + + /* Number of bytes to actually copy out of this sector. */ + int chunk_size = file_left < sector_left ? file_left : sector_left; + if (chunk_size == 0) + break; + + /* Read sector into bounce buffer, then copy into caller's + buffer. */ + disk_read (disk, sector_idx, bounce); + memcpy (buffer + bytes_read, bounce + sector_ofs, chunk_size); + + /* Advance. */ + size -= chunk_size; + start += chunk_size; + bytes_read += chunk_size; } - filesys_stub_unlock (); - - return retval; + free (bounce); + + return bytes_read; } off_t file_write (struct file *file, const void *buffer, off_t size) { - int32_t retval; + off_t retval = file_write_at (file, buffer, size, file->pos); + file->pos += retval; + return retval; +} - filesys_stub_lock (); - filesys_stub_put_string ("write"); - filesys_stub_put_file (file); - filesys_stub_put_uint32 (size); - filesys_stub_put_bytes (buffer, size); - filesys_stub_match_string ("write"); - retval = filesys_stub_get_int32 (); - ASSERT (retval <= size); - filesys_stub_unlock (); +off_t +file_write_at (struct file *file, const void *buffer_, off_t size, + off_t start) +{ + uint8_t *buffer = buffer_; + off_t bytes_read = 0; + uint8_t *bounce; - return retval; + bounce = malloc (DISK_SECTOR_SIZE); + while (size > 0) + { + /* Disk sector to read, starting byte offset within sector. */ + off_t sector_idx = filehdr_byte_to_sector (file->hdr); + int sector_ofs = start % DISK_SECTOR_SIZE; + + /* Bytes left in file, bytes left in sector. */ + off_t file_left = filehdr_size (file->hdr) - start; + off_t sector_left = DISK_SECTOR_SIZE - sector_ofs; + + /* Number of bytes to actually copy out of this sector. */ + int chunk_size = file_left < sector_left ? file_left : sector_left; + if (chunk_size == 0) + break; + + /* Read sector into bounce buffer, then copy into caller's + buffer. */ + disk_read (disk, sector_idx, bounce); + memcpy (buffer + bytes_read, bounce + sector_ofs, chunk_size); + + /* Advance. */ + size -= chunk_size; + start += chunk_size; + bytes_read += chunk_size; + } + free (bounce); + + return bytes_read; } off_t diff --git a/src/filesys/file.h b/src/filesys/file.h index 8f2fbc9..d165e80 100644 --- a/src/filesys/file.h +++ b/src/filesys/file.h @@ -4,12 +4,24 @@ #include #include +#ifndef OFF_T +#define OFF_T typedef int32_t off_t; +#endif -struct file; +struct file + { + struct filehdr *hdr; + off_t pos; + }; + +bool file_open (struct file *, const char *name); +bool file_open_sector (struct file *, disk_sector_no); void file_close (struct file *); off_t file_read (struct file *, void *, off_t); +off_t file_read_at (struct file *, void *, off_t size, off_t start); off_t file_write (struct file *, const void *, off_t); +off_t file_write_at (struct file *, const void *, off_t size, off_t start); off_t file_length (struct file *); void file_seek (struct file *, off_t); off_t file_tell (struct file *); diff --git a/src/filesys/filesys.c b/src/filesys/filesys.c index f8348ed..0b96c27 100644 --- a/src/filesys/filesys.c +++ b/src/filesys/filesys.c @@ -1,65 +1,162 @@ #include "filesys.h" +#include "disk.h" +#include "directory.h" +static struct disk *disk; -#ifdef FILESYS_STUB -#include -#include "debug.h" -#include "filesys-stub.h" -#include "lib.h" +static struct file free_map_file, root_dir_file; -void -filesys_init (bool reformat) +#define FREE_MAP_SECTOR 0 +#define ROOT_DIR_SECTOR 1 + +#define NUM_DIR_ENTRIES 10 +#define ROOT_DIR_FILE_SIZE (sizeof (struct dir_entry) * NUM_DIR_ENTRIES) + +static void +do_format (void) { - if (reformat) - printk ("filesystem stubs don't support formatting\n"); - filesys_stub_init (); + struct bitmap free_map; + struct filehdr map_hdr, dir_hdr; + struct dir dir; + + /* Create the initial bitmap and reserve sectors for the + free map and root directory file headers. */ + bitmap_init (&free_map, disk_size (disk)); + bitmap_mark (&free_map, FREE_MAP_SECTOR); + bitmap_mark (&free_map, ROOT_DIR_SECTOR); + + /* Allocate data sector(s) for the free map file + and write its file header to disk. */ + if (!filehdr_allocate (&map_hdr, bitmap_storage_size (&free_map))) + panic ("free map creation failed"); + filehdr_write (&map_hdr, FREE_MAP_SECTOR); + filehdr_destroy (&map_hdr); + + /* Allocate data sector(s) for the root directory file + and write its file header to disk. */ + if (!filehdr_allocate (&dir_hdr, ROOT_DIR_FILE_SIZE)) + panic ("root directory creation failed"); + filehdr_write (&dir_hdr, FREE_MAP_SECTOR); + filehdr_destroy (&dir_hdr); + + /* Write out the free map now that we have space reserved + for it. */ + file_open (&free_map_file, FREE_MAP_SECTOR); + bitmapio_write (&free_map, free_map_file); + bitmap_destroy (&free_map); + file_close (&free_map_file); + + /* Write out the root directory in the same way. */ + file_open (&root_dir_file, ROOT_DIR_SECTOR); + if (!dir_init (&dir, NUM_DIR_ENTRIES)) + panic ("can't initialize root directory"); + dir_write (root_dir_file); + dir_destroy (&dir); + file_close (&free_map_file); } -bool -filesys_create (const char *name) +void +filesys_init (bool format) { - bool success; - - filesys_stub_lock (); - filesys_stub_put_string ("create"); - filesys_stub_put_string (name); - filesys_stub_match_string ("create"); - success = filesys_stub_get_bool (); - filesys_stub_unlock (); + disk = disk_get (1); + if (disk == NULL) + panic ("ide1:1 not present, filesystem initialization failed"); - return success; + if (format) + do_format (); + + file_open (&free_map_file, FREE_MAP_SECTOR); + file_open (&root_dir_file, ROOT_DIR_SECTOR); } -struct file * -filesys_open (const char *name) +bool +filesys_create (const char *name, off_t initial_size) { - struct file *file; + struct dir dir; + struct bitmap free_map; + disk_sector_no hdr_sector; + struct filehdr filehdr; + bool success = false; + + /* Read the root directory. */ + dir_init (&dir, NUM_DIR_ENTRIES); + dir_read (&dir, &root_dir_file); + if (dir_lookup (&dir, name, NULL)) + goto exit1; + + /* Allocate a block for the file header. */ + bitmap_init (&free_map, disk_size (disk)); + bitmapio_read (&free_map, &free_map_file); + hdr_sector = bitmap_find_and_set (&free_map); + if (hdr_sector == BITMAP_ERROR) + goto exit2; + + /* Add the file to the directory. */ + if (!dir_add (&dir, name, hdr_sector)) + goto exit2; + + /* Allocate space for the file. */ + if (!filehdr_allocate (&filehdr, initial_size)) + goto exit2; + + /* Write everything back. */ + filehdr_write (&filehdr, hdr_sector); + dir_write (&dir, &root_dir_file); + bitmapio_write (&free_map, &free_map_file); + + success = true; + + /* Clean up. */ + filehdr_destroy (&filehdr); + exit2: + bitmap_destroy (&free_map); + exit1: + dir_destroy (&dir); - filesys_stub_lock (); - filesys_stub_put_string ("open"); - filesys_stub_put_string (name); - filesys_stub_match_string ("open"); - file = filesys_stub_get_file (); - filesys_stub_unlock (); - - return file; + return success; } bool filesys_remove (const char *name) { - bool success; - - filesys_stub_lock (); - filesys_stub_put_string ("remove"); - filesys_stub_put_string (name); - filesys_stub_match_string ("remove"); - success = filesys_stub_get_bool (); - filesys_stub_unlock (); + struct dir dir; + disk_sector_no hdr_sector; + struct filehdr filehdr; + struct bitmap free_map; + bool success = false; + + /* Read the root directory. */ + dir_init (&dir, NUM_DIR_ENTRIES); + dir_read (&dir, &root_dir_file); + if (!dir_lookup (&dir, name, &hdr_sector)) + goto exit; + + /* Read the file header. */ + filehdr_read (&filehdr, hdr_sector); + + /* Allocate a block for the file header. */ + bitmap_init (&free_map, disk_size (disk)); + bitmapio_read (&free_map, &free_map_file); + + /* Deallocate. */ + filehdr_deallocate (&filehdr, &free_map); + bitmap_reset (&free_map, hdr_sector); + dir_remove (&dir, name); + + /* Write everything back. */ + bitmapio_write (&free_map, &free_map_file); + dir_write (&dir, &root_dir_file); + + success = true; + + /* Clean up. */ + filehdr_destroy (&filehdr); + bitmap_destroy (&free_map); + exit: + dir_destroy (&dir); return success; } -#endif /* FILESYS_STUB */ #undef NDEBUG #include "debug.h" diff --git a/src/filesys/filesys.h b/src/filesys/filesys.h index bbde398..4f31b7c 100644 --- a/src/filesys/filesys.h +++ b/src/filesys/filesys.h @@ -3,10 +3,16 @@ #include -void filesys_init (bool reformat); -bool filesys_create (const char *name); -struct file *filesys_open (const char *name); +#ifndef OFF_T +#define OFF_T +typedef int32_t off_t; +#endif + +struct file; +void filesys_init (bool format); +bool filesys_create (const char *name, off_t initial_size); bool filesys_remove (const char *name); +void filesys_list (void); void filesys_self_test (void); -- 2.30.2