1 #include "filesys/fsutil.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"
14 /* List files in the root directory. */
16 fsutil_ls (char **argv UNUSED)
19 char name[NAME_MAX + 1];
21 printf ("Files in the root directory:\n");
22 dir = dir_open_root ();
24 PANIC ("root dir open failed");
25 while (dir_readdir (dir, name))
26 printf ("%s\n", name);
27 printf ("End of listing.\n");
30 /* Prints the contents of file ARGV[1] to the system console as
33 fsutil_cat (char **argv)
35 const char *file_name = argv[1];
40 printf ("Printing '%s' to the console...\n", file_name);
41 file = filesys_open (file_name);
43 PANIC ("%s: open failed", file_name);
44 buffer = palloc_get_page (PAL_ASSERT);
47 off_t pos = file_tell (file);
48 off_t n = file_read (file, buffer, PGSIZE);
52 hex_dump (pos, buffer, n, true);
54 palloc_free_page (buffer);
58 /* Deletes file ARGV[1]. */
60 fsutil_rm (char **argv)
62 const char *file_name = argv[1];
64 printf ("Deleting '%s'...\n", file_name);
65 if (!filesys_remove (file_name))
66 PANIC ("%s: delete failed\n", file_name);
69 /* Extracts a ustar-format tar archive from the scratch block
70 device into the Pintos file system. */
72 fsutil_extract (char **argv UNUSED)
74 static block_sector_t sector = 0;
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");
85 /* Open source block device. */
86 src = block_get_role (BLOCK_SCRATCH);
88 PANIC ("couldn't open scratch device");
90 printf ("Extracting ustar archive from scratch device "
91 "into file system...\n");
95 const char *file_name;
100 /* Read and parse ustar header. */
101 block_read (src, sector++, header);
102 error = ustar_parse_header (header, &file_name, &type, &size);
104 PANIC ("bad ustar header in sector %"PRDSNu" (%s)", sector - 1, error);
106 if (type == USTAR_EOF)
108 /* End of archive. */
111 else if (type == USTAR_DIRECTORY)
112 printf ("ignoring directory %s\n", file_name);
113 else if (type == USTAR_REGULAR)
117 printf ("Putting '%s' into the file system...\n", file_name);
119 /* Create destination file. */
120 if (!filesys_create (file_name, size))
121 PANIC ("%s: create failed", file_name);
122 dst = filesys_open (file_name);
124 PANIC ("%s: open failed", file_name);
129 int chunk_size = (size > BLOCK_SECTOR_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",
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);
157 /* Copies file FILE_NAME from the file system to the scratch
158 device, in ustar format.
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
166 fsutil_append (char **argv)
168 static block_sector_t sector = 0;
170 const char *file_name = argv[1];
176 printf ("Appending '%s' to ustar archive on scratch device...\n", file_name);
178 /* Allocate buffer. */
179 buffer = malloc (BLOCK_SECTOR_SIZE);
181 PANIC ("couldn't allocate buffer");
183 /* Open source file. */
184 src = filesys_open (file_name);
186 PANIC ("%s: open failed", file_name);
187 size = file_length (src);
189 /* Open target block device. */
190 dst = block_get_role (BLOCK_SCRATCH);
192 PANIC ("couldn't open scratch device");
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);
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);
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);