1 #include "filesys/file.h"
4 #include "filesys/directory.h"
5 #include "filesys/inode.h"
6 #include "filesys/filesys.h"
7 #include "threads/malloc.h"
12 struct inode *inode; /* File's inode. */
13 uint8_t *bounce; /* Bounce buffer for reads and writes. */
14 off_t pos; /* Current position. */
17 /* Opens and returns the file whose inode is in sector
18 INODE_SECTOR. Returns a null pointer if unsuccessful. */
20 file_open (disk_sector_t inode_sector)
22 struct file *file = calloc (1, sizeof *file);
26 file->inode = inode_open (inode_sector);
27 file->bounce = malloc (DISK_SECTOR_SIZE);
29 if (file->inode == NULL || file->bounce == NULL)
31 inode_close (file->inode);
41 file_close (struct file *file)
46 inode_close (file->inode);
50 /* Reads SIZE bytes from FILE into BUFFER,
51 starting at the file's current position,
52 and advances the current position.
53 Returns the number of bytes actually read,
54 which may be less than SIZE if end of file is reached. */
56 file_read (struct file *file, void *buffer, off_t size)
58 off_t bytes_read = file_read_at (file, buffer, size, file->pos);
59 file->pos += bytes_read;
63 /* Reads SIZE bytes from FILE into BUFFER,
64 starting at offset FILE_OFS in the file.
65 The file's current position is unaffected
66 Returns the number of bytes actually read,
67 which may be less than SIZE if end of file is reached. */
69 file_read_at (struct file *file, void *buffer_, off_t size,
72 uint8_t *buffer = buffer_;
77 /* Disk sector to read, starting byte offset within sector. */
78 off_t sector_idx = inode_byte_to_sector (file->inode, file_ofs);
79 int sector_ofs = file_ofs % DISK_SECTOR_SIZE;
81 /* Bytes left in file, bytes left in sector, lesser of the two. */
82 off_t file_left = inode_length (file->inode) - file_ofs;
83 int sector_left = DISK_SECTOR_SIZE - sector_ofs;
84 int min_left = file_left < sector_left ? file_left : sector_left;
86 /* Number of bytes to actually copy out of this sector. */
87 int chunk_size = size < min_left ? size : min_left;
91 /* Read sector into bounce buffer, then copy into caller's
93 disk_read (filesys_disk, sector_idx, file->bounce);
94 memcpy (buffer + bytes_read, file->bounce + sector_ofs, chunk_size);
98 file_ofs += chunk_size;
99 bytes_read += chunk_size;
105 /* Writes SIZE bytes from BUFFER into FILE,
106 starting at the file's current position,
107 and advances the current position.
108 Returns the number of bytes actually written,
109 which may be less than SIZE if end of file is reached.
110 (Normally we'd grow the file in that case, but file growth is
111 not yet implemented.) */
113 file_write (struct file *file, const void *buffer, off_t size)
115 off_t bytes_written = file_write_at (file, buffer, size, file->pos);
116 file->pos += bytes_written;
117 return bytes_written;
120 /* Writes SIZE bytes from BUFFER into FILE,
121 starting at offset FILE_OFS in the file.
122 The file's current position is unaffected
123 Returns the number of bytes actually written,
124 which may be less than SIZE if end of file is reached.
125 (Normally we'd grow the file in that case, but file growth is
126 not yet implemented.) */
128 file_write_at (struct file *file, const void *buffer_, off_t size,
131 const uint8_t *buffer = buffer_;
132 off_t bytes_written = 0;
136 /* Starting byte offset within sector to read. */
137 off_t sector_idx = inode_byte_to_sector (file->inode, file_ofs);
138 int sector_ofs = file_ofs % DISK_SECTOR_SIZE;
140 /* Bytes left in file, bytes left in sector, lesser of the two. */
141 off_t file_left = inode_length (file->inode) - file_ofs;
142 int sector_left = DISK_SECTOR_SIZE - sector_ofs;
143 int min_left = file_left < sector_left ? file_left : sector_left;
145 /* Number of bytes to actually writen into this sector. */
146 int chunk_size = size < min_left ? size : min_left;
150 /* If the sector contains data before or after the chunk
151 we're writing, then we need to read in the sector
152 first. Otherwise we start with a sector of all zeros. */
153 if (sector_ofs > 0 || chunk_size < sector_ofs)
154 disk_read (filesys_disk, sector_idx, file->bounce);
156 memset (file->bounce, 0, DISK_SECTOR_SIZE);
157 memcpy (file->bounce + sector_ofs, buffer + bytes_written, chunk_size);
158 disk_write (filesys_disk, sector_idx, file->bounce);
162 file_ofs += chunk_size;
163 bytes_written += chunk_size;
166 return bytes_written;
169 /* Returns the size of FILE in bytes. */
171 file_length (struct file *file)
173 ASSERT (file != NULL);
174 return inode_length (file->inode);
177 /* Sets the current position in FILE to an offset of FILE_OFS
178 bytes from the start of the file. */
180 file_seek (struct file *file, off_t file_ofs)
182 ASSERT (file != NULL);
183 ASSERT (file_ofs >= 0);
184 file->pos = file_ofs;
187 /* Returns the current position in FILE as a byte offset from the
188 start of the file. */
190 file_tell (struct file *file)
192 ASSERT (file != NULL);