87c20047418362ddb9ca22103afb2adce50298e6
[pintos-anon] / src / filesys / filesys.c
1 #include "filesys.h"
2 #include "bitmap.h"
3 #include "debug.h"
4 #include "directory.h"
5 #include "disk.h"
6 #include "file.h"
7 #include "filehdr.h"
8 #include "lib.h"
9
10 #define FREE_MAP_SECTOR 0
11 #define ROOT_DIR_SECTOR 1
12
13 #define NUM_DIR_ENTRIES 10
14 #define ROOT_DIR_FILE_SIZE (sizeof (struct dir_entry) * NUM_DIR_ENTRIES)
15
16 struct disk *filesys_disk;
17
18 static struct file free_map_file, root_dir_file;
19
20 static void
21 do_format (void)
22 {
23   struct bitmap free_map;
24   struct filehdr *map_hdr, *dir_hdr;
25   struct dir dir;
26
27   /* Create the initial bitmap and reserve sectors for the
28      free map and root directory file headers. */
29   if (!bitmap_init (&free_map, disk_size (filesys_disk)))
30     panic ("bitmap creation failed--disk is too large");
31   bitmap_mark (&free_map, FREE_MAP_SECTOR);
32   bitmap_mark (&free_map, ROOT_DIR_SECTOR);
33
34   /* Allocate data sector(s) for the free map file
35      and write its file header to disk. */
36   map_hdr = filehdr_allocate (&free_map, bitmap_storage_size (&free_map));
37   if (map_hdr == NULL)
38     panic ("free map creation failed--disk is too large");
39   filehdr_write (map_hdr, FREE_MAP_SECTOR);
40   filehdr_destroy (map_hdr);
41
42   /* Allocate data sector(s) for the root directory file
43      and write its file header to disk. */
44   dir_hdr = filehdr_allocate (&free_map, ROOT_DIR_FILE_SIZE);
45   if (dir_hdr == NULL)
46     panic ("root directory creation failed");
47   filehdr_write (dir_hdr, ROOT_DIR_SECTOR);
48   filehdr_destroy (dir_hdr);
49
50   /* Write out the free map now that we have space reserved
51      for it. */
52   if (!file_open (&free_map_file, FREE_MAP_SECTOR))
53     panic ("can't open free map file");
54   bitmap_write (&free_map, &free_map_file);
55   bitmap_destroy (&free_map);
56   file_close (&free_map_file);
57
58   /* Write out the root directory in the same way. */
59   if (!file_open (&root_dir_file, ROOT_DIR_SECTOR))
60     panic ("can't open root directory");
61   if (!dir_init (&dir, NUM_DIR_ENTRIES))
62     panic ("can't initialize root directory");
63   dir_write (&dir, &root_dir_file);
64   dir_destroy (&dir);
65   file_close (&free_map_file);
66 }
67
68 void
69 filesys_init (bool format) 
70 {
71   filesys_disk = disk_get (1);
72   if (filesys_disk == NULL)
73     panic ("ide1:1 not present, filesystem initialization failed");
74
75   if (format) 
76     do_format ();
77   
78   if (!file_open (&free_map_file, FREE_MAP_SECTOR))
79     panic ("can't open free map file");
80   if (!file_open (&root_dir_file, ROOT_DIR_SECTOR))
81     panic ("can't open root dir file");
82 }
83
84 bool
85 filesys_create (const char *name, off_t initial_size) 
86 {
87   struct dir dir;
88   struct bitmap free_map;
89   disk_sector_no hdr_sector;
90   struct filehdr *filehdr;
91   bool success = false;
92
93   /* Read the root directory. */
94   if (!dir_init (&dir, NUM_DIR_ENTRIES))
95     return false;
96   dir_read (&dir, &root_dir_file);
97   if (dir_lookup (&dir, name, NULL)) 
98     goto exit1;
99
100   /* Allocate a block for the file header. */
101   if (!bitmap_init (&free_map, disk_size (filesys_disk)))
102     goto exit1;
103   bitmap_read (&free_map, &free_map_file);
104   hdr_sector = bitmap_find_and_set (&free_map);
105   if (hdr_sector == BITMAP_ERROR)
106     goto exit2;
107
108   /* Add the file to the directory. */
109   if (!dir_add (&dir, name, hdr_sector))
110     goto exit2;
111
112   /* Allocate space for the file. */
113   filehdr = filehdr_allocate (&free_map, initial_size);
114   if (filehdr == NULL)
115     goto exit2;
116
117   /* Write everything back. */
118   filehdr_write (filehdr, hdr_sector);
119   dir_write (&dir, &root_dir_file);
120   bitmap_write (&free_map, &free_map_file);
121
122   success = true;
123
124   /* Clean up. */
125   filehdr_destroy (filehdr);
126  exit2:
127   bitmap_destroy (&free_map);
128  exit1:
129   dir_destroy (&dir);
130
131   return success;
132 }
133
134 bool
135 filesys_open (const char *name, struct file *file)
136 {
137   struct dir dir;
138   disk_sector_no hdr_sector;
139   bool success = false;
140
141   if (!dir_init (&dir, NUM_DIR_ENTRIES))
142     return false;
143   dir_read (&dir, &root_dir_file);
144   if (dir_lookup (&dir, name, &hdr_sector))
145     success = file_open (file, hdr_sector);
146   
147   dir_destroy (&dir);
148   return success;
149 }
150
151 bool
152 filesys_remove (const char *name) 
153 {
154   struct dir dir;
155   disk_sector_no hdr_sector;
156   struct filehdr *filehdr;
157   struct bitmap free_map;
158   bool success = false;
159
160   /* Read the root directory. */
161   if (!dir_init (&dir, NUM_DIR_ENTRIES))
162     return false;
163   dir_read (&dir, &root_dir_file);
164   if (!dir_lookup (&dir, name, &hdr_sector))
165     goto exit1;
166
167   /* Read the file header. */
168   filehdr = filehdr_read (hdr_sector);
169   if (filehdr == NULL)
170     goto exit1;
171
172   /* Allocate a block for the file header. */
173   if (!bitmap_init (&free_map, disk_size (filesys_disk)))
174     goto exit2;
175   bitmap_read (&free_map, &free_map_file);
176
177   /* Deallocate. */
178   filehdr_deallocate (filehdr, &free_map);
179   bitmap_reset (&free_map, hdr_sector);
180   dir_remove (&dir, name);
181
182   /* Write everything back. */
183   bitmap_write (&free_map, &free_map_file);
184   dir_write (&dir, &root_dir_file);
185
186   success = true;
187
188   /* Clean up. */
189   bitmap_destroy (&free_map);
190  exit2:
191   filehdr_destroy (filehdr);
192  exit1:
193   dir_destroy (&dir);
194
195   return success;
196 }
197
198 static void must_succeed_function (int, int) ATTRIBUTE((noinline));
199
200 static void 
201 must_succeed_function (int line_no, int success) 
202 {
203   if (!success)
204     panic ("filesys_self_test: operation failed on line %d", line_no);
205 }
206
207 #define MUST_SUCCEED(EXPR) must_succeed_function (__LINE__, EXPR)
208
209 void
210 filesys_self_test (void)
211 {
212   static const char s[] = "This is a test string.";
213   struct file file;
214   char s2[sizeof s];
215
216   MUST_SUCCEED (filesys_create ("foo", sizeof s));
217   MUST_SUCCEED (filesys_open ("foo", &file));
218   MUST_SUCCEED (file_write (&file, s, sizeof s) == sizeof s);
219   MUST_SUCCEED (file_tell (&file) == sizeof s);
220   MUST_SUCCEED (file_length (&file) == sizeof s);
221   file_close (&file);
222
223   MUST_SUCCEED (filesys_open ("foo", &file));
224   MUST_SUCCEED (file_read (&file, s2, sizeof s2) == sizeof s2);
225   MUST_SUCCEED (memcmp (s, s2, sizeof s) == 0);
226   MUST_SUCCEED (file_tell (&file) == sizeof s2);
227   MUST_SUCCEED (file_length (&file) == sizeof s2);
228   file_close (&file);
229
230   MUST_SUCCEED (filesys_remove ("foo"));
231
232   printk ("filesys: self test ok\n");
233 }