Make tests public. Rewrite most tests. Add tests.
[pintos-anon] / src / filesys / fsutil.c
index 81466c2a66dfa008d7d3c1415a9211a392e733c5..8ef5d98f2045f88d3f0a2fb5ed1490476a85a5db 100644 (file)
 #include "filesys/fsutil.h"
 #include <debug.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "filesys/file.h"
 #include "filesys/filesys.h"
+#include "devices/disk.h"
 #include "threads/mmu.h"
+#include "threads/malloc.h"
 #include "threads/palloc.h"
 
-/* Destination filename and size for copy-in operations. */
-char *fsutil_copyin_file;
-int fsutil_copyin_size;
+/* List files in the root directory. */
+void
+fsutil_ls (char **argv UNUSED) 
+{
+  printf ("Files in the root directory:\n");
+  filesys_list ();
+  printf ("End of listing.\n");
+}
 
-/* Source filename for copy-out operations. */
-char *fsutil_copyout_file;
+/* Prints the contents of file ARGV[1] to the system console as
+   hex and ASCII. */
+void
+fsutil_cat (char **argv)
+{
+  const char *filename = argv[1];
+  
+  struct file *file;
+  char *buffer;
 
-/* Name of a file print to print to console. */
-char *fsutil_print_file;
+  printf ("Printing '%s' to the console...\n", filename);
+  file = filesys_open (filename);
+  if (file == NULL)
+    PANIC ("%s: open failed", filename);
+  buffer = palloc_get_page (PAL_ASSERT);
+  for (;;) 
+    {
+      off_t pos = file_tell (file);
+      off_t n = file_read (file, buffer, PGSIZE);
+      if (n == 0)
+        break;
 
-/* Name of a file to delete. */
-char *fsutil_remove_file;
+      hex_dump (pos, buffer, n, true); 
+    }
+  palloc_free_page (buffer);
+  file_close (file);
+}
+
+/* Deletes file ARGV[1]. */
+void
+fsutil_rm (char **argv) 
+{
+  const char *filename = argv[1];
+  
+  printf ("Deleting '%s'...\n", filename);
+  if (!filesys_remove (filename))
+    PANIC ("%s: delete failed\n", filename);
+}
+
+/* Copies from the "scratch" disk, hdc or hd1:0 to file ARGV[1]
+   in the filesystem.
 
-/* List all files in the filesystem to the system console? */
-bool fsutil_list_files;
+   The current sector on the scratch disk must begin with the
+   string "PUT\0" followed by a 32-bit little-endian integer
+   indicating the file size in bytes.  Subsequent sectors hold
+   the file content.
 
-/* Copies from the "scratch" disk, hdc or hd1:0,
-   to a file named FILENAME in the filesystem.
-   The file will be SIZE bytes in length. */
-static void
-copy_in (const char *filename, off_t size) 
+   The first call to this function will read starting at the
+   beginning of the scratch disk.  Later calls advance across the
+   disk.  This disk position is independent of that used for
+   fsutil_get(), so all `put's should precede all `get's. */
+void
+fsutil_put (char **argv) 
 {
+  static disk_sector_t sector = 0;
+
+  const char *filename = argv[1];
   struct disk *src;
   struct file *dst;
-  disk_sector_t sector;
+  off_t size;
   void *buffer;
 
-  /* Open source disk. */
+  printf ("Putting '%s' into the file system...\n", filename);
+
+  /* Allocate buffer. */
+  buffer = malloc (DISK_SECTOR_SIZE);
+  if (buffer == NULL)
+    PANIC ("couldn't allocate buffer");
+
+  /* Open source disk and read file size. */
   src = disk_get (1, 0);
   if (src == NULL)
     PANIC ("couldn't open source disk (hdc or hd1:0)");
-  if (size > (off_t) disk_size (src) * DISK_SECTOR_SIZE)
-    PANIC ("source disk is too small for %lld-byte file",
-           (unsigned long long) size);
+
+  /* Read file size. */
+  disk_read (src, sector++, buffer);
+  if (memcmp (buffer, "PUT", 4))
+    PANIC ("%s: missing PUT signature on scratch disk", filename);
+  size = ((int32_t *) buffer)[1];
+  if (size < 0)
+    PANIC ("%s: invalid file size %d", filename, size);
   
   /* Create destination file. */
   if (!filesys_create (filename, size))
@@ -52,36 +109,49 @@ copy_in (const char *filename, off_t size)
     PANIC ("%s: open failed", filename);
 
   /* Do copy. */
-  buffer = palloc_get_page (PAL_ASSERT);
-  sector = 0;
   while (size > 0)
     {
       int chunk_size = size > DISK_SECTOR_SIZE ? DISK_SECTOR_SIZE : size;
       disk_read (src, sector++, buffer);
       if (file_write (dst, buffer, chunk_size) != chunk_size)
-        PANIC ("%s: write failed with %lld bytes unwritten",
-               filename, (unsigned long long) size);
+        PANIC ("%s: write failed with %"PROTd" bytes unwritten",
+               filename, size);
       size -= chunk_size;
     }
-  palloc_free_page (buffer);
 
+  /* Finish up. */
   file_close (dst);
+  free (buffer);
 }
 
-/* Copies FILENAME from the file system to the scratch disk.
-   The first four bytes of the first sector in the disk
-   receive the file's size in bytes as a little-endian integer.
-   The second and subsequent sectors receive the file's data. */
-static void
-copy_out (const char *filename) 
+/* Copies file FILENAME from the file system to the scratch disk.
+
+   The current sector on the scratch disk will receive "GET\0"
+   followed by the file's size in bytes as a 32-bit,
+   little-endian integer.  Subsequent sectors receive the file's
+   data.
+
+   The first call to this function will write starting at the
+   beginning of the scratch disk.  Later calls advance across the
+   disk.  This disk position is independent of that used for
+   fsutil_put(), so all `put's should precede all `get's. */
+void
+fsutil_get (char **argv)
 {
+  static disk_sector_t sector = 0;
+
+  const char *filename = argv[1];
   void *buffer;
   struct file *src;
   struct disk *dst;
   off_t size;
-  disk_sector_t sector;
 
-  buffer = palloc_get_page (PAL_ASSERT | PAL_ZERO);
+  printf ("Getting '%s' from the file system...\n", filename);
+
+  /* Allocate buffer. */
+  buffer = malloc (DISK_SECTOR_SIZE);
+  if (buffer == NULL)
+    PANIC ("couldn't allocate buffer");
 
   /* Open source file. */
   src = filesys_open (filename);
@@ -93,76 +163,27 @@ copy_out (const char *filename)
   dst = disk_get (1, 0);
   if (dst == NULL)
     PANIC ("couldn't open target disk (hdc or hd1:0)");
-  if (size + DISK_SECTOR_SIZE > (off_t) disk_size (dst) * DISK_SECTOR_SIZE)
-    PANIC ("target disk is too small for %lld-byte file",
-           (unsigned long long) size);
   
   /* Write size to sector 0. */
-  *(uint32_t *) buffer = size;
-  disk_write (dst, 0, buffer);
+  memset (buffer, 0, DISK_SECTOR_SIZE);
+  memcpy (buffer, "GET", 4);
+  ((int32_t *) buffer)[1] = size;
+  disk_write (dst, sector++, buffer);
   
   /* Do copy. */
-  sector = 1;
   while (size > 0) 
     {
       int chunk_size = size > DISK_SECTOR_SIZE ? DISK_SECTOR_SIZE : size;
+      if (sector >= disk_size (dst))
+        PANIC ("%s: out of space on scratch disk", filename);
       if (file_read (src, buffer, chunk_size) != chunk_size)
-        PANIC ("%s: read failed with %lld bytes unread",
-               filename, (unsigned long long) size);
+        PANIC ("%s: read failed with %"PROTd" bytes unread", filename, size);
+      memset (buffer + chunk_size, 0, DISK_SECTOR_SIZE - chunk_size);
       disk_write (dst, sector++, buffer);
       size -= chunk_size;
     }
-  palloc_free_page (buffer);
 
+  /* Finish up. */
   file_close (src);
-}
-
-/* Executes the filesystem operations described by the variables
-   declared in fsutil.h. */
-void
-fsutil_run (void) 
-{
-  if (fsutil_copyin_file != NULL) 
-    copy_in (fsutil_copyin_file, fsutil_copyin_size);
-
-  if (fsutil_copyout_file != NULL)
-    copy_out (fsutil_copyout_file);
-
-  if (fsutil_print_file != NULL)
-    fsutil_print (fsutil_print_file);
-
-  if (fsutil_remove_file != NULL) 
-    {
-      if (filesys_remove (fsutil_remove_file))
-        printf ("%s: removed\n", fsutil_remove_file);
-      else
-        PANIC ("%s: remove failed\n", fsutil_remove_file);
-    }
-
-  if (fsutil_list_files)
-    filesys_list ();
-}
-
-/* Prints the contents of file FILENAME to the system console as
-   hex and ASCII. */
-void
-fsutil_print (const char *filename) 
-{
-  struct file *file;
-  char *buffer;
-
-  file = filesys_open (filename);
-  if (file == NULL)
-    PANIC ("%s: open failed", filename);
-  buffer = palloc_get_page (PAL_ASSERT);
-  for (;;) 
-    {
-      off_t n = file_read (file, buffer, PGSIZE);
-      if (n == 0)
-        break;
-
-      hex_dump (0, buffer, n, true);
-    }
-  palloc_free_page (buffer);
-  file_close (file);
+  free (buffer);
 }