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 device
70 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 device. */
86 src = block_get_role (BLOCK_SCRATCH);
88 PANIC ("couldn't open scratch device");
90 printf ("Extracting ustar archive from %s 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 ("%s: bad ustar header in sector %"PRDSNu" (%s)",
105 block_name (src), sector - 1, error);
107 if (type == USTAR_EOF)
109 /* End of archive. */
112 else if (type == USTAR_DIRECTORY)
113 printf ("ignoring directory %s\n", file_name);
114 else if (type == USTAR_REGULAR)
118 printf ("Putting '%s' into the file system...\n", file_name);
120 /* Create destination file. */
121 if (!filesys_create (file_name, size))
122 PANIC ("%s: create failed", file_name);
123 dst = filesys_open (file_name);
125 PANIC ("%s: open failed", file_name);
130 int chunk_size = (size > BLOCK_SECTOR_SIZE
133 block_read (src, sector++, data);
134 if (file_write (dst, data, chunk_size) != chunk_size)
135 PANIC ("%s: write failed with %"PROTd" bytes unwritten",
145 /* Erase the ustar header from the start of the device, so that
146 the extraction operation is idempotent. We erase two blocks
147 because two blocks of zeros are the ustar end-of-archive
149 printf ("Erasing ustar archive...\n");
150 memset (header, 0, BLOCK_SECTOR_SIZE);
151 block_write (src, 0, header);
152 block_write (src, 1, header);
158 /* Copies file FILE_NAME from the Pintos file system to a
159 ustar-format tar archive maintained on the scratch device.
161 The first call to this function will write starting at the
162 beginning of the scratch device, thus creating a new archive.
163 Therefore, any `extract' calls must precede all `append's.
164 Later calls advance across the device, appending to the
167 fsutil_append (char **argv)
169 static block_sector_t sector = 0;
171 const char *file_name = argv[1];
177 printf ("Getting '%s' from the file system...\n", file_name);
179 /* Allocate buffer. */
180 buffer = malloc (BLOCK_SECTOR_SIZE);
182 PANIC ("couldn't allocate buffer");
184 /* Open source file. */
185 src = filesys_open (file_name);
187 PANIC ("%s: open failed", file_name);
188 size = file_length (src);
190 /* Open target device. */
191 dst = block_get_role (BLOCK_SCRATCH);
193 PANIC ("couldn't open scratch device");
195 /* Write ustar header to first sector. */
196 if (!ustar_make_header (file_name, USTAR_REGULAR, size, buffer))
197 PANIC ("%s: can't get from file system (name too long)", file_name);
198 block_write (dst, sector++, buffer);
203 int chunk_size = size > BLOCK_SECTOR_SIZE ? BLOCK_SECTOR_SIZE : size;
204 if (sector >= block_size (dst))
205 PANIC ("%s: out of space on scratch device", file_name);
206 if (file_read (src, buffer, chunk_size) != chunk_size)
207 PANIC ("%s: read failed with %"PROTd" bytes unread", file_name, size);
208 memset (buffer + chunk_size, 0, BLOCK_SECTOR_SIZE - chunk_size);
209 block_write (dst, sector++, buffer);
213 /* Write ustar end-of-archive marker, which is two consecutive
214 sectors full of zeros. Don't advance our position past
215 them, though, in case we have more files to get. */
216 memset (buffer, 0, BLOCK_SECTOR_SIZE);
217 block_write (dst, sector, buffer);
218 block_write (dst, sector, buffer + 1);