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);
51 /* Reads SIZE bytes from FILE into BUFFER,
52 starting at the file's current position,
53 and advances the current position.
54 Returns the number of bytes actually read,
55 which may be less than SIZE if end of file is reached. */
57 file_read (struct file *file, void *buffer, off_t size)
59 off_t bytes_read = file_read_at (file, buffer, size, file->pos);
60 file->pos += bytes_read;
64 /* Reads SIZE bytes from FILE into BUFFER,
65 starting at offset FILE_OFS in the file.
66 The file's current position is unaffected
67 Returns the number of bytes actually read,
68 which may be less than SIZE if end of file is reached. */
70 file_read_at (struct file *file, void *buffer_, off_t size,
73 uint8_t *buffer = buffer_;
78 /* Disk sector to read, starting byte offset within sector. */
79 disk_sector_t sector_idx;
80 int sector_ofs = file_ofs % DISK_SECTOR_SIZE;
82 /* Bytes left in file, bytes left in sector, lesser of the two. */
83 off_t file_left = inode_length (file->inode) - file_ofs;
84 int sector_left = DISK_SECTOR_SIZE - sector_ofs;
85 int min_left = file_left < sector_left ? file_left : sector_left;
87 /* Number of bytes to actually copy out of this sector. */
88 int chunk_size = size < min_left ? size : min_left;
92 /* Read sector into bounce buffer, then copy into caller's
94 sector_idx = inode_byte_to_sector (file->inode, file_ofs);
95 disk_read (filesys_disk, sector_idx, file->bounce);
96 memcpy (buffer + bytes_read, file->bounce + sector_ofs, chunk_size);
100 file_ofs += chunk_size;
101 bytes_read += chunk_size;
107 /* Writes SIZE bytes from BUFFER into FILE,
108 starting at the file's current position,
109 and advances the current position.
110 Returns the number of bytes actually written,
111 which may be less than SIZE if end of file is reached.
112 (Normally we'd grow the file in that case, but file growth is
113 not yet implemented.) */
115 file_write (struct file *file, const void *buffer, off_t size)
117 off_t bytes_written = file_write_at (file, buffer, size, file->pos);
118 file->pos += bytes_written;
119 return bytes_written;
122 /* Writes SIZE bytes from BUFFER into FILE,
123 starting at offset FILE_OFS in the file.
124 The file's current position is unaffected
125 Returns the number of bytes actually written,
126 which may be less than SIZE if end of file is reached.
127 (Normally we'd grow the file in that case, but file growth is
128 not yet implemented.) */
130 file_write_at (struct file *file, const void *buffer_, off_t size,
133 const uint8_t *buffer = buffer_;
134 off_t bytes_written = 0;
138 /* Sector to write, starting byte offset within sector. */
140 int sector_ofs = file_ofs % DISK_SECTOR_SIZE;
142 /* Bytes left in file, bytes left in sector, lesser of the two. */
143 off_t file_left = inode_length (file->inode) - file_ofs;
144 int sector_left = DISK_SECTOR_SIZE - sector_ofs;
145 int min_left = file_left < sector_left ? file_left : sector_left;
147 /* Number of bytes to actually write into this sector. */
148 int chunk_size = size < min_left ? size : min_left;
152 /* If the sector contains data before or after the chunk
153 we're writing, then we need to read in the sector
154 first. Otherwise we start with a sector of all zeros. */
155 sector_idx = inode_byte_to_sector (file->inode, file_ofs);
156 if (sector_ofs > 0 || chunk_size < sector_left)
157 disk_read (filesys_disk, sector_idx, file->bounce);
159 memset (file->bounce, 0, DISK_SECTOR_SIZE);
160 memcpy (file->bounce + sector_ofs, buffer + bytes_written, chunk_size);
161 disk_write (filesys_disk, sector_idx, file->bounce);
165 file_ofs += chunk_size;
166 bytes_written += chunk_size;
169 return bytes_written;
172 /* Returns the size of FILE in bytes. */
174 file_length (struct file *file)
176 ASSERT (file != NULL);
177 return inode_length (file->inode);
180 /* Sets the current position in FILE to an offset of FILE_OFS
181 bytes from the start of the file. */
183 file_seek (struct file *file, off_t file_ofs)
185 ASSERT (file != NULL);
186 ASSERT (file_ofs >= 0);
187 file->pos = file_ofs;
190 /* Returns the current position in FILE as a byte offset from the
191 start of the file. */
193 file_tell (struct file *file)
195 ASSERT (file != NULL);