PKUOS - Pintos
Pintos source browser for PKU Operating System course
fsutil.c
Go to the documentation of this file.
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 dir_close (dir);
28 printf ("End of listing.\n");
29}
30
31/** Prints the contents of file ARGV[1] to the system console as
32 hex and ASCII. */
33void
34fsutil_cat (char **argv)
35{
36 const char *file_name = argv[1];
37
38 struct file *file;
39 char *buffer;
40
41 printf ("Printing '%s' to the console...\n", file_name);
43 if (file == NULL)
44 PANIC ("%s: open failed", file_name);
46 for (;;)
47 {
50 if (n == 0)
51 break;
52
53 hex_dump (pos, buffer, n, true);
54 }
57}
58
59/** Deletes file ARGV[1]. */
60void
61fsutil_rm (char **argv)
62{
63 const char *file_name = argv[1];
64
65 printf ("Deleting '%s'...\n", file_name);
67 PANIC ("%s: delete failed\n", file_name);
68}
69
70/** Extracts a ustar-format tar archive from the scratch block
71 device into the Pintos file system. */
72void
73fsutil_extract (char **argv UNUSED)
74{
75 static block_sector_t sector = 0;
76
77 struct block *src;
78 void *header, *data;
79
80 /* Allocate buffers. */
81 header = malloc (BLOCK_SECTOR_SIZE);
83 if (header == NULL || data == NULL)
84 PANIC ("couldn't allocate buffers");
85
86 /* Open source block device. */
88 if (src == NULL)
89 PANIC ("couldn't open scratch device");
90
91 printf ("Extracting ustar archive from scratch device "
92 "into file system...\n");
93
94 for (;;)
95 {
96 const char *file_name;
97 const char *error;
98 enum ustar_type type;
99 int size;
100
101 /* Read and parse ustar header. */
102 block_read (src, sector++, header);
103 error = ustar_parse_header (header, &file_name, &type, &size);
104 if (error != NULL)
105 PANIC ("bad ustar header in sector %"PRDSNu" (%s)", sector - 1, error);
106
107 if (type == USTAR_EOF)
108 {
109 /* End of archive. */
110 break;
111 }
112 else if (type == USTAR_DIRECTORY)
113 printf ("ignoring directory %s\n", file_name);
114 else if (type == USTAR_REGULAR)
115 {
116 struct file *dst;
117
118 printf ("Putting '%s' into the file system...\n", file_name);
119
120 /* Create destination file. */
121 if (!filesys_create (file_name, size))
122 PANIC ("%s: create failed", file_name);
123 dst = filesys_open (file_name);
124 if (dst == NULL)
125 PANIC ("%s: open failed", file_name);
126
127 /* Do copy. */
128 while (size > 0)
129 {
130 int chunk_size = (size > BLOCK_SECTOR_SIZE
132 : 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",
136 file_name, size);
137 size -= chunk_size;
138 }
139
140 /* Finish up. */
141 file_close (dst);
142 }
143 }
144
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);
153
154 free (data);
155 free (header);
156}
157
158/** Copies file FILE_NAME from the file system to the scratch
159 device, in ustar format.
160
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
165 `append's. */
166void
167fsutil_append (char **argv)
168{
169 static block_sector_t sector = 0;
170
171 const char *file_name = argv[1];
172 void *buffer;
173 struct file *src;
174 struct block *dst;
175 off_t size;
176
177 printf ("Appending '%s' to ustar archive on scratch device...\n", file_name);
178
179 /* Allocate buffer. */
181 if (buffer == NULL)
182 PANIC ("couldn't allocate buffer");
183
184 /* Open source file. */
185 src = filesys_open (file_name);
186 if (src == NULL)
187 PANIC ("%s: open failed", file_name);
188 size = file_length (src);
189
190 /* Open target block device. */
192 if (dst == NULL)
193 PANIC ("couldn't open scratch device");
194
195 /* Write ustar header to first sector. */
197 PANIC ("%s: name too long for ustar format", file_name);
198 block_write (dst, sector++, buffer);
199
200 /* Do copy. */
201 while (size > 0)
202 {
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);
210 size -= chunk_size;
211 }
212
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. */
217 block_write (dst, sector, buffer);
218 block_write (dst, sector, buffer + 1);
219
220 /* Finish up. */
221 file_close (src);
222 free (buffer);
223}
struct block * block_get_role(enum block_type role)
Returns the block device fulfilling the given ROLE, or a null pointer if no block device has been ass...
Definition: block.c:54
block_sector_t block_size(struct block *block)
Returns the number of sectors in BLOCK.
Definition: block.c:144
void block_read(struct block *block, block_sector_t sector, void *buffer)
Reads sector SECTOR from BLOCK into BUFFER, which must have room for BLOCK_SECTOR_SIZE bytes.
Definition: block.c:121
void block_write(struct block *block, block_sector_t sector, const void *buffer)
Write sector SECTOR to BLOCK from BUFFER, which must contain BLOCK_SECTOR_SIZE bytes.
Definition: block.c:134
uint32_t block_sector_t
Index of a block device sector.
Definition: block.h:15
#define BLOCK_SECTOR_SIZE
Size of a block device sector in bytes.
Definition: block.h:11
#define PRDSNu
Format specifier for printf(), e.g.
Definition: block.h:19
@ BLOCK_SCRATCH
Scratch.
Definition: block.h:31
#define PANIC(...)
Halts the OS, printing the source file name, line number, and function name, plus a user-specific mes...
Definition: debug.h:14
#define UNUSED
GCC lets us add "attributes" to functions, function parameters, etc.
Definition: debug.h:7
void dir_close(struct dir *dir)
Destroys DIR and frees associated resources.
Definition: directory.c:70
bool dir_readdir(struct dir *dir, char name[NAME_MAX+1])
Reads the next directory entry in DIR and stores the name in NAME.
Definition: directory.c:222
struct dir * dir_open_root(void)
Opens the root directory and returns a directory for it.
Definition: directory.c:55
#define NAME_MAX
Maximum length of a file name component.
Definition: directory.h:12
void file_close(struct file *file)
Closes FILE.
Definition: file.c:46
off_t file_write(struct file *file, const void *buffer, off_t size)
Writes SIZE bytes from BUFFER into FILE, starting at the file's current position.
Definition: file.c:95
off_t file_length(struct file *file)
Returns the size of FILE in bytes.
Definition: file.c:145
off_t file_read(struct file *file, void *buffer, off_t size)
Reads SIZE bytes from FILE into BUFFER, starting at the file's current position.
Definition: file.c:69
off_t file_tell(struct file *file)
Returns the current position in FILE as a byte offset from the start of the file.
Definition: file.c:164
struct file * filesys_open(const char *name)
Opens the file with the given NAME.
Definition: filesys.c:67
bool filesys_remove(const char *name)
Deletes the file named NAME.
Definition: filesys.c:84
bool filesys_create(const char *name, off_t initial_size)
Creates a file named NAME with the given INITIAL_SIZE.
Definition: filesys.c:46
void fsutil_cat(char **argv)
Prints the contents of file ARGV[1] to the system console as hex and ASCII.
Definition: fsutil.c:34
void fsutil_ls(char **argv UNUSED)
List files in the root directory.
Definition: fsutil.c:16
void fsutil_append(char **argv)
Copies file FILE_NAME from the file system to the scratch device, in ustar format.
Definition: fsutil.c:167
void fsutil_extract(char **argv UNUSED)
Extracts a ustar-format tar archive from the scratch block device into the Pintos file system.
Definition: fsutil.c:73
void fsutil_rm(char **argv)
Deletes file ARGV[1].
Definition: fsutil.c:61
static struct intq buffer
Stores keys from the keyboard and serial port.
Definition: input.c:7
char * name[]
Definition: insult.c:47
int printf(const char *format,...)
Writes formatted output to the console.
Definition: stdio.c:79
void hex_dump(uintptr_t ofs, const void *buf_, size_t size, bool ascii)
Dumps the SIZE bytes in BUF to the console as hex bytes arranged 16 per line.
Definition: stdio.c:593
void * malloc(size_t size)
Obtains and returns a new block of at least SIZE bytes.
Definition: malloc.c:90
void free(void *p)
Frees block P, which must have been previously allocated with malloc(), calloc(), or realloc().
Definition: malloc.c:219
#define PROTd
Format specifier for printf(), e.g.
Definition: off_t.h:13
int32_t off_t
An offset within a file.
Definition: off_t.h:9
void * palloc_get_page(enum palloc_flags flags)
Obtains a single free page and returns its kernel virtual address.
Definition: palloc.c:111
void palloc_free_page(void *page)
Frees the page at PAGE.
Definition: palloc.c:146
@ PAL_ASSERT
Panic on failure.
Definition: palloc.h:9
#define NULL
Definition: stddef.h:4
void * memset(void *dst_, int value, size_t size)
Sets the SIZE bytes in DST to VALUE.
Definition: string.c:279
A block device.
Definition: block.c:10
enum block_type type
Type of block device.
Definition: block.c:14
block_sector_t size
Size in sectors.
Definition: block.c:15
A directory.
Definition: directory.c:11
An open file.
Definition: file.c:8
off_t pos
Current position.
Definition: file.c:10
static const char file_name[]
tests/filesys/base/syn-read.h
Definition: syn-read.h:5
bool ustar_make_header(const char *file_name, enum ustar_type type, int size, char header[USTAR_HEADER_SIZE])
Composes HEADER as a USTAR_HEADER_SIZE (512)-byte archive header in ustar format for a SIZE-byte file...
Definition: ustar.c:83
const char * ustar_parse_header(const char header[USTAR_HEADER_SIZE], const char **file_name, enum ustar_type *type, int *size)
Parses HEADER as a ustar-format archive header for a regular file or directory.
Definition: ustar.c:182
ustar_type
Support for the standard Posix "ustar" format.
Definition: ustar.h:14
@ USTAR_REGULAR
Ordinary file.
Definition: ustar.h:15
@ USTAR_EOF
End of archive (not an official value).
Definition: ustar.h:17
@ USTAR_DIRECTORY
Directory.
Definition: ustar.h:16
#define PGSIZE
Bytes in a page.
Definition: vaddr.h:20