323470efdd568a5dcea711366c8bd1bd263ff80d
[pintos-anon] / src / filesys / file.c
1 #include "file.h"
2 #include "debug.h"
3 #include "lib.h"
4 #include "malloc.h"
5 #include "directory.h"
6 #include "filehdr.h"
7 #include "filesys.h"
8
9 bool
10 file_open (struct file *file, disk_sector_t hdr_sector) 
11 {
12   file->hdr = filehdr_read (hdr_sector);
13   file->bounce = malloc (DISK_SECTOR_SIZE);
14   file->pos = 0;
15   if (file->hdr != NULL && file->bounce != NULL)
16     return true;
17   else
18     {
19       filehdr_destroy (file->hdr);
20       free (file->bounce);
21       return false;
22     }
23 }
24
25 void
26 file_close (struct file *file) 
27 {
28   filehdr_destroy (file->hdr);
29 }
30
31 off_t
32 file_read (struct file *file, void *buffer, off_t size) 
33 {
34   off_t bytes_read = file_read_at (file, buffer, size, file->pos);
35   file->pos += bytes_read;
36   return bytes_read;
37 }
38
39 off_t
40 file_read_at (struct file *file, void *buffer_, off_t size,
41               off_t file_ofs) 
42 {
43   uint8_t *buffer = buffer_;
44   off_t bytes_read = 0;
45
46   while (size > 0) 
47     {
48       /* Disk sector to read, starting byte offset within sector. */
49       off_t sector_idx = filehdr_byte_to_sector (file->hdr, file_ofs);
50       int sector_ofs = file_ofs % DISK_SECTOR_SIZE;
51
52       /* Bytes left in file, bytes left in sector, lesser of the two. */
53       off_t file_left = filehdr_length (file->hdr) - file_ofs;
54       int sector_left = DISK_SECTOR_SIZE - sector_ofs;
55       int min_left = file_left < sector_left ? file_left : sector_left;
56
57       /* Number of bytes to actually copy out of this sector. */
58       int chunk_size = size < min_left ? size : min_left;
59       if (chunk_size == 0)
60         break;
61
62       /* Read sector into bounce buffer, then copy into caller's
63          buffer. */
64       disk_read (filesys_disk, sector_idx, file->bounce);
65       memcpy (buffer + bytes_read, file->bounce + sector_ofs, chunk_size);
66
67       /* Advance. */
68       size -= chunk_size;
69       file_ofs += chunk_size;
70       bytes_read += chunk_size;
71     }
72
73   return bytes_read;
74 }
75
76 off_t
77 file_write (struct file *file, const void *buffer, off_t size) 
78 {
79   off_t bytes_written = file_write_at (file, buffer, size, file->pos);
80   file->pos += bytes_written;
81   return bytes_written;
82 }
83
84 off_t
85 file_write_at (struct file *file, const void *buffer_, off_t size,
86                off_t file_ofs) 
87 {
88   const uint8_t *buffer = buffer_;
89   off_t bytes_written = 0;
90
91   while (size > 0) 
92     {
93       /* Starting byte offset within sector to read. */
94       off_t sector_idx = filehdr_byte_to_sector (file->hdr, file_ofs);
95       int sector_ofs = file_ofs % DISK_SECTOR_SIZE;
96
97       /* Bytes left in file, bytes left in sector, lesser of the two. */
98       off_t file_left = filehdr_length (file->hdr) - file_ofs;
99       int sector_left = DISK_SECTOR_SIZE - sector_ofs;
100       int min_left = file_left < sector_left ? file_left : sector_left;
101
102       /* Number of bytes to actually writen into this sector. */
103       int chunk_size = size < min_left ? size : min_left;
104       if (chunk_size == 0)
105         break;
106
107       /* If the sector contains data before or after the chunk
108          we're writing, then we need to read in the sector
109          first.  Otherwise we start with a sector of all zeros. */
110       if (sector_ofs > 0 || chunk_size < sector_ofs)
111         disk_read (filesys_disk, sector_idx, file->bounce);
112       else
113         memset (file->bounce, 0, DISK_SECTOR_SIZE);
114       memcpy (file->bounce + sector_ofs, buffer + bytes_written, chunk_size);
115       disk_write (filesys_disk, sector_idx, file->bounce);
116
117       /* Advance. */
118       size -= chunk_size;
119       file_ofs += chunk_size;
120       bytes_written += chunk_size;
121     }
122
123   return bytes_written;
124 }
125
126 off_t
127 file_length (struct file *file) 
128 {
129   ASSERT (file != NULL);
130   return filehdr_length (file->hdr);
131 }
132
133 void
134 file_seek (struct file *file, off_t file_ofs) 
135 {
136   ASSERT (file != NULL);
137   ASSERT (file_ofs >= 0);
138   file->pos = file_ofs;
139 }
140
141 off_t
142 file_tell (struct file *file) 
143 {
144   ASSERT (file != NULL);
145   return file->pos;
146 }