5df0d9d6b01145d7b132fab8cfa4577c039097da
[pintos-anon] / src / filesys / filesys.c
1 #include "filesys/filesys.h"
2 #include <debug.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include "filesys/file.h"
6 #include "filesys/free-map.h"
7 #include "filesys/inode.h"
8 #include "filesys/directory.h"
9 #include "devices/disk.h"
10
11 /* The disk that contains the file system. */
12 struct disk *filesys_disk;
13
14 static void do_format (void);
15
16 /* Initializes the file system module.
17    If FORMAT is true, reformats the file system. */
18 void
19 filesys_init (bool format) 
20 {
21   filesys_disk = disk_get (0, 1);
22   if (filesys_disk == NULL)
23     PANIC ("hd0:1 (hdb) not present, file system initialization failed");
24
25   inode_init ();
26   free_map_init ();
27
28   if (format) 
29     do_format ();
30
31   free_map_open ();
32 }
33
34 /* Shuts down the file system module, writing any unwritten data
35    to disk. */
36 void
37 filesys_done (void) 
38 {
39   free_map_close ();
40 }
41 \f
42 /* Creates a file named NAME with the given INITIAL_SIZE.
43    Returns true if successful, false otherwise.
44    Fails if a file named NAME already exists,
45    or if internal memory allocation fails. */
46 bool
47 filesys_create (const char *name, off_t initial_size) 
48 {
49   disk_sector_t inode_sector = 0;
50   struct dir *dir = dir_open_root ();
51   bool success = (dir != NULL
52                   && free_map_allocate (1, &inode_sector)
53                   && inode_create (inode_sector, initial_size)
54                   && dir_add (dir, name, inode_sector));
55   if (!success && inode_sector != 0) 
56     free_map_release (inode_sector, 1);
57   dir_close (dir);
58
59   return success;
60 }
61
62 /* Opens the file with the given NAME.
63    Returns the new file if successful or a null pointer
64    otherwise.
65    Fails if no file named NAME exists,
66    or if an internal memory allocation fails. */
67 struct file *
68 filesys_open (const char *name)
69 {
70   struct dir *dir = dir_open_root ();
71   struct inode *inode = NULL;
72
73   if (dir != NULL)
74     dir_lookup (dir, name, &inode);
75   dir_close (dir);
76
77   return file_open (inode);
78 }
79
80 /* Deletes the file named NAME.
81    Returns true if successful, false on failure.
82    Fails if no file named NAME exists,
83    or if an internal memory allocation fails. */
84 bool
85 filesys_remove (const char *name) 
86 {
87   struct dir *dir = dir_open_root ();
88   bool success = dir != NULL && dir_remove (dir, name);
89   dir_close (dir); 
90
91   return success;
92 }
93 \f
94 static void must_succeed_function (int, bool) NO_INLINE;
95 #define MUST_SUCCEED(EXPR) must_succeed_function (__LINE__, EXPR)
96
97 /* Performs basic sanity checks on the file system.
98    The file system should not contain a file named `foo' when
99    called. */
100 void
101 filesys_self_test (void)
102 {
103   static const char s[] = "This is a test string.";
104   static const char zeros[sizeof s] = {0};
105   struct file *file;
106   char s2[sizeof s];
107   int i;
108
109   filesys_remove ("foo");
110   for (i = 0; i < 2; i++) 
111     {
112       /* Create file and check that it contains zeros
113          throughout the created length. */
114       MUST_SUCCEED (filesys_create ("foo", sizeof s));
115       MUST_SUCCEED ((file = filesys_open ("foo")) != NULL);
116       MUST_SUCCEED (file_read (file, s2, sizeof s2) == sizeof s2);
117       MUST_SUCCEED (memcmp (s2, zeros, sizeof s) == 0);
118       MUST_SUCCEED (file_tell (file) == sizeof s);
119       MUST_SUCCEED (file_length (file) == sizeof s);
120       file_close (file);
121
122       /* Reopen file and write to it. */
123       MUST_SUCCEED ((file = filesys_open ("foo")) != NULL);
124       MUST_SUCCEED (file_write (file, s, sizeof s) == sizeof s);
125       MUST_SUCCEED (file_tell (file) == sizeof s);
126       MUST_SUCCEED (file_length (file) == sizeof s);
127       file_close (file);
128
129       /* Reopen file and verify that it reads back correctly.
130          Delete file while open to check proper semantics. */
131       MUST_SUCCEED ((file = filesys_open ("foo")) != NULL);
132       MUST_SUCCEED (filesys_remove ("foo"));
133       MUST_SUCCEED (filesys_open ("foo") == NULL);
134       MUST_SUCCEED (file_read (file, s2, sizeof s) == sizeof s);
135       MUST_SUCCEED (memcmp (s, s2, sizeof s) == 0);
136       MUST_SUCCEED (file_tell (file) == sizeof s);
137       MUST_SUCCEED (file_length (file) == sizeof s);
138       file_close (file);
139     }
140   
141   printf ("filesys: self test ok\n");
142 }
143
144 /* If SUCCESS is false, panics with an error complaining about
145    LINE_NO. */
146 static void 
147 must_succeed_function (int line_no, bool success) 
148 {
149   if (!success)
150     PANIC ("filesys_self_test: operation failed on line %d", line_no);
151 }
152 \f
153 /* Formats the file system. */
154 static void
155 do_format (void)
156 {
157   printf ("Formatting file system...");
158   free_map_create ();
159   if (!dir_create (ROOT_DIR_SECTOR, 16))
160     PANIC ("root directory creation failed");
161   free_map_close ();
162   printf ("done.\n");
163 }