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