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);
28 printf ("End of listing.\n");
31 /* Prints the contents of file ARGV[1] to the system console as
34 fsutil_cat (char **argv)
36 const char *file_name = argv[1];
41 printf ("Printing '%s' to the console...\n", file_name);
42 file = filesys_open (file_name);
44 PANIC ("%s: open failed", file_name);
45 buffer = palloc_get_page (PAL_ASSERT);
48 off_t pos = file_tell (file);
49 off_t n = file_read (file, buffer, PGSIZE);
53 hex_dump (pos, buffer, n, true);
55 palloc_free_page (buffer);
59 /* Deletes file ARGV[1]. */
61 fsutil_rm (char **argv)
63 const char *file_name = argv[1];
65 printf ("Deleting '%s'...\n", file_name);
66 if (!filesys_remove (file_name))
67 PANIC ("%s: delete failed\n", file_name);
70 /* Extracts a ustar-format tar archive from the scratch block
71 device into the Pintos file system. */
73 fsutil_extract (char **argv UNUSED)
75 static block_sector_t sector = 0;
80 /* Allocate buffers. */
81 header = malloc (BLOCK_SECTOR_SIZE);
82 data = malloc (BLOCK_SECTOR_SIZE);
83 if (header == NULL || data == NULL)
84 PANIC ("couldn't allocate buffers");
86 /* Open source block device. */
87 src = block_get_role (BLOCK_SCRATCH);
89 PANIC ("couldn't open scratch device");
91 printf ("Extracting ustar archive from scratch device "
92 "into file system...\n");
96 const char *file_name;
101 /* Read and parse ustar header. */
102 block_read (src, sector++, header);
103 error = ustar_parse_header (header, &file_name, &type, &size);
105 PANIC ("bad ustar header in sector %"PRDSNu" (%s)", 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 %d bytes unwritten",
145 /* Erase the ustar header from the start of the block device,
146 so that the extraction operation is idempotent. We erase
147 two blocks because two blocks of zeros are the ustar
148 end-of-archive marker. */
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 file system to the scratch
159 device, in ustar format.
161 The first call to this function will write starting at the
162 beginning of the scratch device. Later calls advance across
163 the device. This position is independent of that used for
164 fsutil_extract(), so `extract' should precede all
167 fsutil_append (char **argv)
169 static block_sector_t sector = 0;
171 const char *file_name = argv[1];
177 printf ("Appending '%s' to ustar archive on scratch device...\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 block 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: name too long for ustar format", 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 append. */
216 memset (buffer, 0, BLOCK_SECTOR_SIZE);
217 block_write (dst, sector, buffer);
218 block_write (dst, sector, buffer + 1);