X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffilesys%2Ffile.c;h=029d8ce847a26d7b02f4606bd48f750a4476f3bd;hb=615bf3b3d2a8573ed6fb9ddc0055745e163ac999;hp=323470efdd568a5dcea711366c8bd1bd263ff80d;hpb=762a09bb7b3dc24de325e74273d7575251f0d419;p=pintos-anon diff --git a/src/filesys/file.c b/src/filesys/file.c index 323470e..029d8ce 100644 --- a/src/filesys/file.c +++ b/src/filesys/file.c @@ -1,143 +1,158 @@ -#include "file.h" -#include "debug.h" -#include "lib.h" -#include "malloc.h" -#include "directory.h" -#include "filehdr.h" -#include "filesys.h" - -bool -file_open (struct file *file, disk_sector_t hdr_sector) +#include "filesys/file.h" +#include +#include "filesys/inode.h" +#include "threads/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) { - file->hdr = filehdr_read (hdr_sector); - file->bounce = malloc (DISK_SECTOR_SIZE); - file->pos = 0; - if (file->hdr != NULL && file->bounce != NULL) - return true; + 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 { - filehdr_destroy (file->hdr); - free (file->bounce); - return false; + 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) { - filehdr_destroy (file->hdr); + if (file != NULL) + { + file_allow_write (file); + inode_close (file->inode); + free (file); + } } +/* 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) { - off_t bytes_read = file_read_at (file, buffer, size, file->pos); + off_t bytes_read = inode_read_at (file->inode, buffer, size, file->pos); file->pos += bytes_read; return bytes_read; } +/* 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) +file_read_at (struct file *file, void *buffer, off_t size, off_t file_ofs) { - uint8_t *buffer = buffer_; - off_t bytes_read = 0; - - while (size > 0) - { - /* Disk sector to read, starting byte offset within sector. */ - off_t sector_idx = filehdr_byte_to_sector (file->hdr, file_ofs); - int sector_ofs = file_ofs % DISK_SECTOR_SIZE; - - /* Bytes left in file, bytes left in sector, lesser of the two. */ - off_t file_left = filehdr_length (file->hdr) - file_ofs; - int sector_left = DISK_SECTOR_SIZE - sector_ofs; - int min_left = file_left < sector_left ? file_left : sector_left; - - /* Number of bytes to actually copy out of this sector. */ - int chunk_size = size < min_left ? size : min_left; - if (chunk_size == 0) - break; - - /* Read sector into bounce buffer, then copy into caller's - buffer. */ - disk_read (filesys_disk, sector_idx, file->bounce); - memcpy (buffer + bytes_read, file->bounce + sector_ofs, chunk_size); - - /* Advance. */ - size -= chunk_size; - file_ofs += chunk_size; - bytes_read += chunk_size; - } - - return bytes_read; + 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) { - off_t bytes_written = file_write_at (file, buffer, size, file->pos); + off_t bytes_written = inode_write_at (file->inode, buffer, size, file->pos); file->pos += bytes_written; return bytes_written; } +/* 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, +file_write_at (struct file *file, const void *buffer, off_t size, off_t file_ofs) { - const uint8_t *buffer = buffer_; - off_t bytes_written = 0; + return inode_write_at (file->inode, buffer, size, file_ofs); +} - while (size > 0) +/* 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) { - /* Starting byte offset within sector to read. */ - off_t sector_idx = filehdr_byte_to_sector (file->hdr, file_ofs); - int sector_ofs = file_ofs % DISK_SECTOR_SIZE; - - /* Bytes left in file, bytes left in sector, lesser of the two. */ - off_t file_left = filehdr_length (file->hdr) - file_ofs; - int sector_left = DISK_SECTOR_SIZE - sector_ofs; - int min_left = file_left < sector_left ? file_left : sector_left; - - /* Number of bytes to actually writen into this sector. */ - int chunk_size = size < min_left ? size : min_left; - if (chunk_size == 0) - break; - - /* If the sector contains data before or after the chunk - we're writing, then we need to read in the sector - first. Otherwise we start with a sector of all zeros. */ - if (sector_ofs > 0 || chunk_size < sector_ofs) - disk_read (filesys_disk, sector_idx, file->bounce); - else - memset (file->bounce, 0, DISK_SECTOR_SIZE); - memcpy (file->bounce + sector_ofs, buffer + bytes_written, chunk_size); - disk_write (filesys_disk, sector_idx, file->bounce); - - /* Advance. */ - size -= chunk_size; - file_ofs += chunk_size; - bytes_written += chunk_size; + file->deny_write = true; + inode_deny_write (file->inode); } +} - return bytes_written; +/* 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) { ASSERT (file != NULL); - return filehdr_length (file->hdr); + 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 file_ofs) +file_seek (struct file *file, off_t new_pos) { ASSERT (file != NULL); - ASSERT (file_ofs >= 0); - file->pos = file_ofs; + 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) {