+
+/* Prints a list of files in the filesystem to the system
+ console.
+ Returns true if successful, false on failure,
+ which occurs only if an internal memory allocation fails. */
+bool
+filesys_list (void)
+{
+ struct dir *dir = dir_create (NUM_DIR_ENTRIES);
+ if (dir == NULL)
+ return false;
+ dir_read (dir, root_dir_file);
+ dir_list (dir);
+ dir_destroy (dir);
+
+ return true;
+}
+
+/* Dumps the filesystem state to the system console,
+ including the free map, the list of files, and file contents.
+ Returns true if successful, false on failure,
+ which occurs only if an internal memory allocation fails. */
+bool
+filesys_dump (void)
+{
+ struct bitmap *free_map;
+ struct dir *dir;
+
+ printf ("Free map:\n");
+ free_map = bitmap_create (disk_size (filesys_disk));
+ if (free_map == NULL)
+ return false;
+ bitmap_read (free_map, free_map_file);
+ bitmap_dump (free_map);
+ bitmap_destroy (free_map);
+ printf ("\n");
+
+ dir = dir_create (NUM_DIR_ENTRIES);
+ if (dir == NULL)
+ return false;
+ dir_read (dir, root_dir_file);
+ dir_dump (dir);
+ dir_destroy (dir);
+
+ return true;
+}
+
+static void must_succeed_function (int, bool) NO_INLINE;
+#define MUST_SUCCEED(EXPR) must_succeed_function (__LINE__, EXPR)
+
+/* Performs basic sanity checks on the filesystem.
+ The filesystem should not contain a file named `foo' when
+ called. */
+void
+filesys_self_test (void)
+{
+ static const char s[] = "This is a test string.";
+ static const char zeros[sizeof s] = {0};
+ struct file *file;
+ char s2[sizeof s];
+ int i;
+
+ filesys_remove ("foo");
+ for (i = 0; i < 2; i++)
+ {
+ /* Create file and check that it contains zeros
+ throughout the created length. */
+ MUST_SUCCEED (filesys_create ("foo", sizeof s));
+ MUST_SUCCEED ((file = filesys_open ("foo")) != NULL);
+ MUST_SUCCEED (file_read (file, s2, sizeof s2) == sizeof s2);
+ MUST_SUCCEED (memcmp (s2, zeros, sizeof s) == 0);
+ MUST_SUCCEED (file_tell (file) == sizeof s);
+ MUST_SUCCEED (file_length (file) == sizeof s);
+ file_close (file);
+
+ /* Reopen file and write to it. */
+ MUST_SUCCEED ((file = filesys_open ("foo")) != NULL);
+ MUST_SUCCEED (file_write (file, s, sizeof s) == sizeof s);
+ MUST_SUCCEED (file_tell (file) == sizeof s);
+ MUST_SUCCEED (file_length (file) == sizeof s);
+ file_close (file);
+
+ /* Reopen file and verify that it reads back correctly.
+ Delete file while open to check proper semantics. */
+ MUST_SUCCEED ((file = filesys_open ("foo")) != NULL);
+ MUST_SUCCEED (filesys_remove ("foo"));
+ MUST_SUCCEED (file_read (file, s2, sizeof s) == sizeof s);
+ MUST_SUCCEED (memcmp (s, s2, sizeof s) == 0);
+ MUST_SUCCEED (file_tell (file) == sizeof s);
+ MUST_SUCCEED (file_length (file) == sizeof s);
+ file_close (file);
+
+ /* Make sure file is deleted. */
+ MUST_SUCCEED ((file = filesys_open ("foo")) == NULL);
+ }
+
+ printf ("filesys: self test ok\n");
+}
+\f
+/* Formats the filesystem. */
+static void
+do_format (void)
+{
+ struct bitmap *free_map;
+ struct inode *map_inode, *dir_inode;
+ struct dir *dir;
+
+ printf ("Formatting filesystem...");
+
+ /* Create the initial bitmap and reserve sectors for the
+ free map and root directory inodes. */
+ free_map = bitmap_create (disk_size (filesys_disk));
+ if (free_map == NULL)
+ PANIC ("bitmap creation failed--disk is too large");
+ bitmap_mark (free_map, FREE_MAP_SECTOR);
+ bitmap_mark (free_map, ROOT_DIR_SECTOR);
+
+ /* Allocate data sector(s) for the free map file
+ and write its inode to disk. */
+ map_inode = inode_create (free_map, FREE_MAP_SECTOR,
+ bitmap_file_size (free_map));
+ if (map_inode == NULL)
+ PANIC ("free map creation failed--disk is too large");
+ inode_commit (map_inode);
+ inode_close (map_inode);
+
+ /* Allocate data sector(s) for the root directory file
+ and write its inodes to disk. */
+ dir_inode = inode_create (free_map, ROOT_DIR_SECTOR,
+ dir_size (NUM_DIR_ENTRIES));
+ if (dir_inode == NULL)
+ PANIC ("root directory creation failed");
+ inode_commit (dir_inode);
+ inode_close (dir_inode);
+
+ /* Write out the free map now that we have space reserved
+ for it. */
+ free_map_file = file_open (FREE_MAP_SECTOR);
+ if (free_map_file == NULL)
+ PANIC ("can't open free map file");
+ bitmap_write (free_map, free_map_file);
+ bitmap_destroy (free_map);
+ file_close (free_map_file);
+
+ /* Write out the root directory in the same way. */
+ root_dir_file = file_open (ROOT_DIR_SECTOR);
+ if (root_dir_file == NULL)
+ PANIC ("can't open root directory");
+ dir = dir_create (NUM_DIR_ENTRIES);
+ if (dir == NULL)
+ PANIC ("can't initialize root directory");
+ dir_write (dir, root_dir_file);
+ dir_destroy (dir);
+ file_close (root_dir_file);
+
+ printf ("done.\n");
+}
+
+/* If SUCCESS is false, panics with an error complaining about
+ LINE_NO. */
+static void
+must_succeed_function (int line_no, bool success)
+{
+ if (!success)
+ PANIC ("filesys_self_test: operation failed on line %d", line_no);
+}