X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffilesys%2Ffile.c;h=d5fc10de15004e98d4f8490aa8a7ec8a4c7efcff;hb=fd2a5afa946474ba0839de0e9da238dbaecbd6a5;hp=0c18ab093dab78aea95471da9f4bd14a1f3b3c92;hpb=3fc16f6e9abc98a3bd5427eb210669860609a224;p=pintos-anon diff --git a/src/filesys/file.c b/src/filesys/file.c index 0c18ab0..d5fc10d 100644 --- a/src/filesys/file.c +++ b/src/filesys/file.c @@ -1,98 +1,168 @@ -#include "file.h" +#include "filesys/file.h" +#include +#include "filesys/inode.h" +#include "threads/malloc.h" -#ifdef FILESYS_STUB -#include "debug.h" -#include "filesys-stub.h" -#include "lib.h" -#include "malloc.h" +/* An open file. */ +struct file + { + struct inode *inode; /* File's inode. */ + off_t pos; /* Current position. */ + bool deny_write; /* Has file_deny_write() been called? */ + }; +/* Opens a file for the given INODE, of which it takes ownership, + and returns the new file. Returns a null pointer if an + allocation fails or if INODE is null. */ +struct file * +file_open (struct inode *inode) +{ + struct file *file = calloc (1, sizeof *file); + if (inode != NULL && file != NULL) + { + file->inode = inode; + file->pos = 0; + file->deny_write = false; + return file; + } + else + { + inode_close (inode); + free (file); + return NULL; + } +} + +/* Opens and returns a new file for the same inode as FILE. + Returns a null pointer if unsuccessful. */ +struct file * +file_reopen (struct file *file) +{ + return file_open (inode_reopen (file->inode)); +} + +/* Closes FILE. */ 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 (); + if (file != NULL) + { + file_allow_write (file); + inode_close (file->inode); + free (file); + } +} + +/* Returns the inode encapsulated by FILE. */ +struct inode * +file_get_inode (struct file *file) +{ + return file->inode; } +/* Reads SIZE bytes from FILE into BUFFER, + starting at the file's current position. + Returns the number of bytes actually read, + which may be less than SIZE if end of file is reached. + Advances FILE's position by the number of bytes read. */ off_t file_read (struct file *file, void *buffer, off_t size) { - int32_t retval; + off_t bytes_read = inode_read_at (file->inode, buffer, size, file->pos); + file->pos += bytes_read; + return bytes_read; +} - 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) - { - ASSERT (retval <= size); - filesys_stub_get_bytes (buffer, retval); - } - filesys_stub_unlock (); - - return retval; +/* Reads SIZE bytes from FILE into BUFFER, + starting at offset FILE_OFS in the file. + Returns the number of bytes actually read, + which may be less than SIZE if end of file is reached. + The file's current position is unaffected. */ +off_t +file_read_at (struct file *file, void *buffer, off_t size, off_t file_ofs) +{ + return inode_read_at (file->inode, buffer, size, file_ofs); } +/* Writes SIZE bytes from BUFFER into FILE, + starting at the file's current position. + Returns the number of bytes actually written, + which may be less than SIZE if end of file is reached. + (Normally we'd grow the file in that case, but file growth is + not yet implemented.) + Advances FILE's position by the number of bytes read. */ off_t file_write (struct file *file, const void *buffer, off_t size) { - int32_t retval; + off_t bytes_written = inode_write_at (file->inode, buffer, size, file->pos); + file->pos += bytes_written; + return bytes_written; +} - 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 (); +/* Writes SIZE bytes from BUFFER into FILE, + starting at offset FILE_OFS in the file. + Returns the number of bytes actually written, + which may be less than SIZE if end of file is reached. + (Normally we'd grow the file in that case, but file growth is + not yet implemented.) + The file's current position is unaffected. */ +off_t +file_write_at (struct file *file, const void *buffer, off_t size, + off_t file_ofs) +{ + return inode_write_at (file->inode, buffer, size, file_ofs); +} - return retval; +/* Prevents write operations on FILE's underlying inode + until file_allow_write() is called or FILE is closed. */ +void +file_deny_write (struct file *file) +{ + ASSERT (file != NULL); + if (!file->deny_write) + { + file->deny_write = true; + inode_deny_write (file->inode); + } } +/* Re-enables write operations on FILE's underlying inode. + (Writes might still be denied by some other file that has the + same inode open.) */ +void +file_allow_write (struct file *file) +{ + ASSERT (file != NULL); + if (file->deny_write) + { + file->deny_write = false; + inode_allow_write (file->inode); + } +} + +/* Returns the size of FILE in bytes. */ off_t file_length (struct file *file) { - int32_t length; - - filesys_stub_lock (); - filesys_stub_put_string ("length"); - filesys_stub_put_file (file); - filesys_stub_match_string ("length"); - length = filesys_stub_get_int32 (); - filesys_stub_unlock (); - - return length; + ASSERT (file != NULL); + return inode_length (file->inode); } +/* Sets the current position in FILE to NEW_POS bytes from the + start of the file. */ void -file_seek (struct file *file, off_t pos) +file_seek (struct file *file, off_t new_pos) { - filesys_stub_lock (); - filesys_stub_put_string ("seek"); - filesys_stub_put_file (file); - filesys_stub_put_uint32 (pos); - filesys_stub_match_string ("seek"); - filesys_stub_unlock (); + ASSERT (file != NULL); + ASSERT (new_pos >= 0); + file->pos = new_pos; } +/* Returns the current position in FILE as a byte offset from the + start of the file. */ off_t file_tell (struct file *file) { - int32_t pos; - - filesys_stub_lock (); - filesys_stub_put_string ("tell"); - filesys_stub_put_file (file); - filesys_stub_match_string ("tell"); - pos = filesys_stub_get_int32 (); - filesys_stub_unlock (); - - return pos; + ASSERT (file != NULL); + return file->pos; } -#endif /* FILESYS_STUB */