Start work on partition support.
[pintos-anon] / src / filesys / fsutil.c
1 #include "filesys/fsutil.h"
2 #include <debug.h>
3 #include <stdbool.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "filesys/file.h"
8 #include "filesys/filesys.h"
9 #include "devices/partition.h"
10 #include "threads/mmu.h"
11 #include "threads/palloc.h"
12
13 /* Destination filename and size for copy-in operations. */
14 char *fsutil_copyin_file;
15 int fsutil_copyin_size;
16
17 /* Source filename for copy-out operations. */
18 char *fsutil_copyout_file;
19
20 /* Name of a file print to print to console. */
21 char *fsutil_print_file;
22
23 /* Name of a file to delete. */
24 char *fsutil_remove_file;
25
26 /* List all files in the file system to the system console? */
27 bool fsutil_list_files;
28
29 /* Dump full contents of file system to the system console? */
30 bool fsutil_dump_filesys;
31
32 /* Copies from the "scratch" disk, hdc or hd1:0,
33    to a file named FILENAME in the file system.
34    The file will be SIZE bytes in length. */
35 static void
36 copy_in (const char *filename, off_t size) 
37 {
38   struct partition *src;
39   struct file *dst;
40   disk_sector_t sector;
41   void *buffer;
42
43   /* Open scratch partition. */
44   src = partition_get (PARTITION_SCRATCH);
45   if (src == NULL)
46     PANIC ("couldn't open scratch partition");
47   if (size > (off_t) partition_size (src) * DISK_SECTOR_SIZE)
48     PANIC ("scratch partition is too small for %lld-byte file",
49            (unsigned long long) size);
50   
51   /* Create destination file. */
52   if (!filesys_create (filename, size))
53     PANIC ("%s: create failed", filename);
54   dst = filesys_open (filename);
55   if (dst == NULL)
56     PANIC ("%s: open failed", filename);
57
58   /* Do copy. */
59   buffer = palloc_get_page (PAL_ASSERT);
60   sector = 0;
61   while (size > 0)
62     {
63       int chunk_size = size > DISK_SECTOR_SIZE ? DISK_SECTOR_SIZE : size;
64       partition_read (src, sector++, buffer);
65       if (file_write (dst, buffer, chunk_size) != chunk_size)
66         PANIC ("%s: write failed with %lld bytes unwritten",
67                filename, (unsigned long long) size);
68       size -= chunk_size;
69     }
70   palloc_free_page (buffer);
71
72   file_close (dst);
73 }
74
75 /* Copies FILENAME from the file system to the scratch disk.
76    The first four bytes of the first sector in the disk
77    receive the file's size in bytes as a little-endian integer.
78    The second and subsequent sectors receive the file's data. */
79 static void
80 copy_out (const char *filename) 
81 {
82   void *buffer;
83   struct file *src;
84   struct partition *dst;
85   off_t size;
86   disk_sector_t sector;
87
88   buffer = palloc_get_page (PAL_ASSERT | PAL_ZERO);
89
90   /* Open source file. */
91   src = filesys_open (filename);
92   if (src == NULL)
93     PANIC ("%s: open failed", filename);
94   size = file_length (src);
95
96   /* Open target partition. */
97   dst = partition_get (PARTITION_SCRATCH);
98   if (dst == NULL)
99     PANIC ("couldn't open scratch partition");
100   if (size + DISK_SECTOR_SIZE
101       > (off_t) partition_size (dst) * DISK_SECTOR_SIZE)
102     PANIC ("scratch partition is too small for %lld-byte file",
103            (unsigned long long) size);
104   
105   /* Write size to sector 0. */
106   *(uint32_t *) buffer = size;
107   partition_write (dst, 0, buffer);
108   
109   /* Do copy. */
110   sector = 1;
111   while (size > 0) 
112     {
113       int chunk_size = size > DISK_SECTOR_SIZE ? DISK_SECTOR_SIZE : size;
114       if (file_read (src, buffer, chunk_size) != chunk_size)
115         PANIC ("%s: read failed with %lld bytes unread",
116                filename, (unsigned long long) size);
117       partition_write (dst, sector++, buffer);
118       size -= chunk_size;
119     }
120   palloc_free_page (buffer);
121
122   file_close (src);
123 }
124
125 /* Executes the file system operations described by the variables
126    declared in fsutil.h. */
127 void
128 fsutil_run (void) 
129 {
130   if (fsutil_copyin_file != NULL) 
131     copy_in (fsutil_copyin_file, fsutil_copyin_size);
132
133   if (fsutil_copyout_file != NULL)
134     copy_out (fsutil_copyout_file);
135
136   if (fsutil_print_file != NULL)
137     fsutil_print (fsutil_print_file);
138
139   if (fsutil_remove_file != NULL) 
140     {
141       if (filesys_remove (fsutil_remove_file))
142         printf ("%s: removed\n", fsutil_remove_file);
143       else
144         PANIC ("%s: remove failed\n", fsutil_remove_file);
145     }
146
147   if (fsutil_list_files)
148     filesys_list ();
149
150   if (fsutil_dump_filesys)
151     filesys_dump ();
152 }
153
154 /* Prints the contents of file FILENAME to the system console as
155    hex and ASCII. */
156 void
157 fsutil_print (const char *filename) 
158 {
159   struct file *file;
160   char *buffer;
161
162   file = filesys_open (filename);
163   if (file == NULL)
164     PANIC ("%s: open failed", filename);
165   buffer = palloc_get_page (PAL_ASSERT);
166   for (;;) 
167     {
168       off_t n = file_read (file, buffer, PGSIZE);
169       if (n == 0)
170         break;
171
172       hex_dump (0, buffer, n, true);
173     }
174   palloc_free_page (buffer);
175   file_close (file);
176 }