CS318 - Pintos
Pintos source browser for JHU CS318 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. */
15 void
16 fsutil_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. */
33 void
34 fsutil_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  {
48  off_t pos = file_tell (file);
50  if (n == 0)
51  break;
52 
53  hex_dump (pos, buffer, n, true);
54  }
56  file_close (file);
57 }
58 
59 /** Deletes file ARGV[1]. */
60 void
61 fsutil_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. */
72 void
73 fsutil_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);
82  data = 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. */
166 void
167 fsutil_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 }
fsutil_rm
void fsutil_rm(char **argv)
Deletes file ARGV[1].
Definition: fsutil.c:61
name
char * name[]
Definition: insult.c:47
malloc
void * malloc(size_t size)
Obtains and returns a new block of at least SIZE bytes.
Definition: malloc.c:90
filesys_open
struct file * filesys_open(const char *name)
Opens the file with the given NAME.
Definition: filesys.c:67
USTAR_REGULAR
Ordinary file.
Definition: ustar.h:15
NULL
#define NULL
Definition: stddef.h:4
file_close
void file_close(struct file *file)
Closes FILE.
Definition: file.c:46
filesys.h
string.h
dir_open_root
struct dir * dir_open_root(void)
Opens the root directory and returns a directory for it.
Definition: directory.c:55
USTAR_DIRECTORY
Directory.
Definition: ustar.h:16
UNUSED
#define UNUSED
GCC lets us add "attributes" to functions, function parameters, etc.
Definition: debug.h:7
file
An open file.
Definition: file.c:7
off_t
int32_t off_t
An offset within a file.
Definition: off_t.h:9
file::pos
off_t pos
Current position.
Definition: file.c:10
fsutil_append
void fsutil_append(char **argv)
Copies file FILE_NAME from the file system to the scratch device, in ustar format.
Definition: fsutil.c:167
NAME_MAX
#define NAME_MAX
Maximum length of a file name component.
Definition: directory.h:12
dir_readdir
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
free
void free(void *p)
Frees block P, which must have been previously allocated with malloc(), calloc(), or realloc().
Definition: malloc.c:219
PGSIZE
#define PGSIZE
Bytes in a page.
Definition: vaddr.h:20
block::type
enum block_type type
Type of block device.
Definition: block.c:14
palloc_get_page
void * palloc_get_page(enum palloc_flags flags)
Obtains a single free page and returns its kernel virtual address.
Definition: palloc.c:111
block::size
block_sector_t size
Size in sectors.
Definition: block.c:15
ustar_type
ustar_type
Support for the standard Posix "ustar" format.
Definition: ustar.h:13
block_get_role
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
uint32_t block_sector_t
Index of a block device sector.
Definition: block.h:15
filesys_remove
bool filesys_remove(const char *name)
Deletes the file named NAME.
Definition: filesys.c:84
PANIC
#define PANIC(...)
Halts the OS, printing the source file name, line number, and function name, plus a user-specific mes...
Definition: debug.h:14
PAL_ASSERT
Panic on failure.
Definition: palloc.h:9
hex_dump
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
fsutil.h
file_read
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
buffer
static struct intq buffer
Stores keys from the keyboard and serial port.
Definition: input.c:7
printf
int printf(const char *format,...)
Writes formatted output to the console.
Definition: stdio.c:79
directory.h
PRDSNu
#define PRDSNu
Format specifier for printf(), e.g.
Definition: block.h:19
file_tell
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
fsutil_cat
void fsutil_cat(char **argv)
Prints the contents of file ARGV[1] to the system console as hex and ASCII.
Definition: fsutil.c:34
file_write
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
malloc.h
palloc.h
file_length
off_t file_length(struct file *file)
Returns the size of FILE in bytes.
Definition: file.c:145
BLOCK_SCRATCH
Scratch.
Definition: block.h:31
filesys_create
bool filesys_create(const char *name, off_t initial_size)
Creates a file named NAME with the given INITIAL_SIZE.
Definition: filesys.c:46
block
A block device.
Definition: block.c:9
file_name
static const char file_name[]
tests/filesys/base/syn-read.h
Definition: syn-read.h:5
fsutil_extract
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
ustar.h
palloc_free_page
void palloc_free_page(void *page)
Frees the page at PAGE.
Definition: palloc.c:146
BLOCK_SECTOR_SIZE
#define BLOCK_SECTOR_SIZE
Size of a block device sector in bytes.
Definition: block.h:11
PROTd
#define PROTd
Format specifier for printf(), e.g.
Definition: off_t.h:13
ustar_make_header
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
block_read
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
memset
void * memset(void *dst_, int value, size_t size)
Sets the SIZE bytes in DST to VALUE.
Definition: string.c:279
block_size
block_sector_t block_size(struct block *block)
Returns the number of sectors in BLOCK.
Definition: block.c:144
vaddr.h
file.h
stdlib.h
dir
A directory.
Definition: directory.c:10
USTAR_EOF
End of archive (not an official value).
Definition: ustar.h:17
block_write
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
ustar_parse_header
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
debug.h
dir_close
void dir_close(struct dir *dir)
Destroys DIR and frees associated resources.
Definition: directory.c:70
fsutil_ls
void fsutil_ls(char **argv UNUSED)
List files in the root directory.
Definition: fsutil.c:16