Major revisions to documentation.
[pintos-anon] / src / filesys / fsutil.c
1 #include "filesys/fsutil.h"
2 #include <debug.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "filesys/file.h"
7 #include "filesys/filesys.h"
8 #include "devices/disk.h"
9 #include "threads/malloc.h"
10 #include "threads/palloc.h"
11 #include "threads/vaddr.h"
12
13 /* List files in the root directory. */
14 void
15 fsutil_ls (char **argv UNUSED) 
16 {
17   printf ("Files in the root directory:\n");
18   filesys_list ();
19   printf ("End of listing.\n");
20 }
21
22 /* Prints the contents of file ARGV[1] to the system console as
23    hex and ASCII. */
24 void
25 fsutil_cat (char **argv)
26 {
27   const char *filename = argv[1];
28   
29   struct file *file;
30   char *buffer;
31
32   printf ("Printing '%s' to the console...\n", filename);
33   file = filesys_open (filename);
34   if (file == NULL)
35     PANIC ("%s: open failed", filename);
36   buffer = palloc_get_page (PAL_ASSERT);
37   for (;;) 
38     {
39       off_t pos = file_tell (file);
40       off_t n = file_read (file, buffer, PGSIZE);
41       if (n == 0)
42         break;
43
44       hex_dump (pos, buffer, n, true); 
45     }
46   palloc_free_page (buffer);
47   file_close (file);
48 }
49
50 /* Deletes file ARGV[1]. */
51 void
52 fsutil_rm (char **argv) 
53 {
54   const char *filename = argv[1];
55   
56   printf ("Deleting '%s'...\n", filename);
57   if (!filesys_remove (filename))
58     PANIC ("%s: delete failed\n", filename);
59 }
60
61 /* Copies from the "scratch" disk, hdc or hd1:0 to file ARGV[1]
62    in the filesystem.
63
64    The current sector on the scratch disk must begin with the
65    string "PUT\0" followed by a 32-bit little-endian integer
66    indicating the file size in bytes.  Subsequent sectors hold
67    the file content.
68
69    The first call to this function will read starting at the
70    beginning of the scratch disk.  Later calls advance across the
71    disk.  This disk position is independent of that used for
72    fsutil_get(), so all `put's should precede all `get's. */
73 void
74 fsutil_put (char **argv) 
75 {
76   static disk_sector_t sector = 0;
77
78   const char *filename = argv[1];
79   struct disk *src;
80   struct file *dst;
81   off_t size;
82   void *buffer;
83
84   printf ("Putting '%s' into the file system...\n", filename);
85
86   /* Allocate buffer. */
87   buffer = malloc (DISK_SECTOR_SIZE);
88   if (buffer == NULL)
89     PANIC ("couldn't allocate buffer");
90
91   /* Open source disk and read file size. */
92   src = disk_get (1, 0);
93   if (src == NULL)
94     PANIC ("couldn't open source disk (hdc or hd1:0)");
95
96   /* Read file size. */
97   disk_read (src, sector++, buffer);
98   if (memcmp (buffer, "PUT", 4))
99     PANIC ("%s: missing PUT signature on scratch disk", filename);
100   size = ((int32_t *) buffer)[1];
101   if (size < 0)
102     PANIC ("%s: invalid file size %d", filename, size);
103   
104   /* Create destination file. */
105   if (!filesys_create (filename, size))
106     PANIC ("%s: create failed", filename);
107   dst = filesys_open (filename);
108   if (dst == NULL)
109     PANIC ("%s: open failed", filename);
110
111   /* Do copy. */
112   while (size > 0)
113     {
114       int chunk_size = size > DISK_SECTOR_SIZE ? DISK_SECTOR_SIZE : size;
115       disk_read (src, sector++, buffer);
116       if (file_write (dst, buffer, chunk_size) != chunk_size)
117         PANIC ("%s: write failed with %"PROTd" bytes unwritten",
118                filename, size);
119       size -= chunk_size;
120     }
121
122   /* Finish up. */
123   file_close (dst);
124   free (buffer);
125 }
126
127 /* Copies file FILENAME from the file system to the scratch disk.
128
129    The current sector on the scratch disk will receive "GET\0"
130    followed by the file's size in bytes as a 32-bit,
131    little-endian integer.  Subsequent sectors receive the file's
132    data.
133
134    The first call to this function will write starting at the
135    beginning of the scratch disk.  Later calls advance across the
136    disk.  This disk position is independent of that used for
137    fsutil_put(), so all `put's should precede all `get's. */
138 void
139 fsutil_get (char **argv)
140 {
141   static disk_sector_t sector = 0;
142
143   const char *filename = argv[1];
144   void *buffer;
145   struct file *src;
146   struct disk *dst;
147   off_t size;
148
149   printf ("Getting '%s' from the file system...\n", filename);
150
151   /* Allocate buffer. */
152   buffer = malloc (DISK_SECTOR_SIZE);
153   if (buffer == NULL)
154     PANIC ("couldn't allocate buffer");
155
156   /* Open source file. */
157   src = filesys_open (filename);
158   if (src == NULL)
159     PANIC ("%s: open failed", filename);
160   size = file_length (src);
161
162   /* Open target disk. */
163   dst = disk_get (1, 0);
164   if (dst == NULL)
165     PANIC ("couldn't open target disk (hdc or hd1:0)");
166   
167   /* Write size to sector 0. */
168   memset (buffer, 0, DISK_SECTOR_SIZE);
169   memcpy (buffer, "GET", 4);
170   ((int32_t *) buffer)[1] = size;
171   disk_write (dst, sector++, buffer);
172   
173   /* Do copy. */
174   while (size > 0) 
175     {
176       int chunk_size = size > DISK_SECTOR_SIZE ? DISK_SECTOR_SIZE : size;
177       if (sector >= disk_size (dst))
178         PANIC ("%s: out of space on scratch disk", filename);
179       if (file_read (src, buffer, chunk_size) != chunk_size)
180         PANIC ("%s: read failed with %"PROTd" bytes unread", filename, size);
181       memset (buffer + chunk_size, 0, DISK_SECTOR_SIZE - chunk_size);
182       disk_write (dst, sector++, buffer);
183       size -= chunk_size;
184     }
185
186   /* Finish up. */
187   file_close (src);
188   free (buffer);
189 }