#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))
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);
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);
}