summaryrefslogtreecommitdiffstats
path: root/filesys/fsutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'filesys/fsutil.c')
-rw-r--r--filesys/fsutil.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/filesys/fsutil.c b/filesys/fsutil.c
new file mode 100644
index 0000000..447f291
--- /dev/null
+++ b/filesys/fsutil.c
@@ -0,0 +1,222 @@
1#include "filesys/fsutil.h"
2#include <debug.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <ustar.h>
7#include "filesys/directory.h"
8#include "filesys/file.h"
9#include "filesys/filesys.h"
10#include "threads/malloc.h"
11#include "threads/palloc.h"
12#include "threads/vaddr.h"
13
14/* List files in the root directory. */
15void
16fsutil_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. */
32void
33fsutil_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]. */
59void
60fsutil_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/* Extracts a ustar-format tar archive from the scratch block
70 device into the Pintos file system. */
71void
72fsutil_extract (char **argv UNUSED)
73{
74 static block_sector_t sector = 0;
75
76 struct block *src;
77 void *header, *data;
78
79 /* Allocate buffers. */
80 header = malloc (BLOCK_SECTOR_SIZE);
81 data = malloc (BLOCK_SECTOR_SIZE);
82 if (header == NULL || data == NULL)
83 PANIC ("couldn't allocate buffers");
84
85 /* Open source block device. */
86 src = block_get_role (BLOCK_SCRATCH);
87 if (src == NULL)
88 PANIC ("couldn't open scratch device");
89
90 printf ("Extracting ustar archive from scratch device "
91 "into file system...\n");
92
93 for (;;)
94 {
95 const char *file_name;
96 const char *error;
97 enum ustar_type type;
98 int size;
99
100 /* Read and parse ustar header. */
101 block_read (src, sector++, header);
102 error = ustar_parse_header (header, &file_name, &type, &size);
103 if (error != NULL)
104 PANIC ("bad ustar header in sector %"PRDSNu" (%s)", sector - 1, error);
105
106 if (type == USTAR_EOF)
107 {
108 /* End of archive. */
109 break;
110 }
111 else if (type == USTAR_DIRECTORY)
112 printf ("ignoring directory %s\n", file_name);
113 else if (type == USTAR_REGULAR)
114 {
115 struct file *dst;
116
117 printf ("Putting '%s' into the file system...\n", file_name);
118
119 /* Create destination file. */
120 if (!filesys_create (file_name, size))
121 PANIC ("%s: create failed", file_name);
122 dst = filesys_open (file_name);
123 if (dst == NULL)
124 PANIC ("%s: open failed", file_name);
125
126 /* Do copy. */
127 while (size > 0)
128 {
129 int chunk_size = (size > BLOCK_SECTOR_SIZE
130 ? BLOCK_SECTOR_SIZE
131 : size);
132 block_read (src, sector++, data);
133 if (file_write (dst, data, chunk_size) != chunk_size)
134 PANIC ("%s: write failed with %d bytes unwritten",
135 file_name, size);
136 size -= chunk_size;
137 }
138
139 /* Finish up. */
140 file_close (dst);
141 }
142 }
143
144 /* Erase the ustar header from the start of the block device,
145 so that the extraction operation is idempotent. We erase
146 two blocks because two blocks of zeros are the ustar
147 end-of-archive marker. */
148 printf ("Erasing ustar archive...\n");
149 memset (header, 0, BLOCK_SECTOR_SIZE);
150 block_write (src, 0, header);
151 block_write (src, 1, header);
152
153 free (data);
154 free (header);
155}
156
157/* Copies file FILE_NAME from the file system to the scratch
158 device, in ustar format.
159
160 The first call to this function will write starting at the
161 beginning of the scratch device. Later calls advance across
162 the device. This position is independent of that used for
163 fsutil_extract(), so `extract' should precede all
164 `append's. */
165void
166fsutil_append (char **argv)
167{
168 static block_sector_t sector = 0;
169
170 const char *file_name = argv[1];
171 void *buffer;
172 struct file *src;
173 struct block *dst;
174 off_t size;
175
176 printf ("Appending '%s' to ustar archive on scratch device...\n", file_name);
177
178 /* Allocate buffer. */
179 buffer = malloc (BLOCK_SECTOR_SIZE);
180 if (buffer == NULL)
181 PANIC ("couldn't allocate buffer");
182
183 /* Open source file. */
184 src = filesys_open (file_name);
185 if (src == NULL)
186 PANIC ("%s: open failed", file_name);
187 size = file_length (src);
188
189 /* Open target block device. */
190 dst = block_get_role (BLOCK_SCRATCH);
191 if (dst == NULL)
192 PANIC ("couldn't open scratch device");
193
194 /* Write ustar header to first sector. */
195 if (!ustar_make_header (file_name, USTAR_REGULAR, size, buffer))
196 PANIC ("%s: name too long for ustar format", file_name);
197 block_write (dst, sector++, buffer);
198
199 /* Do copy. */
200 while (size > 0)
201 {
202 int chunk_size = size > BLOCK_SECTOR_SIZE ? BLOCK_SECTOR_SIZE : size;
203 if (sector >= block_size (dst))
204 PANIC ("%s: out of space on scratch device", file_name);
205 if (file_read (src, buffer, chunk_size) != chunk_size)
206 PANIC ("%s: read failed with %"PROTd" bytes unread", file_name, size);
207 memset (buffer + chunk_size, 0, BLOCK_SECTOR_SIZE - chunk_size);
208 block_write (dst, sector++, buffer);
209 size -= chunk_size;
210 }
211
212 /* Write ustar end-of-archive marker, which is two consecutive
213 sectors full of zeros. Don't advance our position past
214 them, though, in case we have more files to append. */
215 memset (buffer, 0, BLOCK_SECTOR_SIZE);
216 block_write (dst, sector, buffer);
217 block_write (dst, sector, buffer + 1);
218
219 /* Finish up. */
220 file_close (src);
221 free (buffer);
222}