d7d2cc2af52ba24cc31f21419dd606c28f6a0fec
[pintos-anon] / src / filesys / filehdr.c
1 #include "filehdr.h"
2 #include "bitmap.h"
3 #include "debug.h"
4 #include "malloc.h"
5 #include "filesys.h"
6 #include "lib.h"
7
8 /* Allocates sectors from bitmap B for the content of a file
9    whose size is LENGTH bytes, and returns a new `struct filehdr'
10    properly initialized for the file.
11    It is the caller's responsible to allocate a sector for the
12    file header itself, and to write the file header and bitmap
13    to disk.
14    If memory or disk allocation fails, returns a null pointer,
15    leaving bitmap B is unchanged. */
16 struct filehdr *
17 filehdr_allocate (struct bitmap *b, off_t length) 
18 {
19   struct filehdr *h;
20   size_t sector_cnt;
21
22   ASSERT (b != NULL);
23   ASSERT (length >= 0);
24
25   sector_cnt = (length / DISK_SECTOR_SIZE) + (length % DISK_SECTOR_SIZE > 0);
26   if (sector_cnt > DIRECT_CNT)
27     return false;
28
29   h = calloc (1, sizeof *h);
30   if (h == NULL)
31     return NULL;
32
33   h->length = length;
34   while (h->sector_cnt < sector_cnt)
35     {
36       size_t sector = bitmap_find_and_set (b);
37       if (sector == BITMAP_ERROR)
38         {
39           filehdr_deallocate (h, b);
40           free (h);
41           return NULL;
42         }
43       h->sectors[h->sector_cnt++] = sector;
44     }
45
46   return h;
47 }
48
49 /* Marks the sectors for H's content as free in bitmap B.
50    Neither H's own disk sector nor its memory are freed. */
51 void
52 filehdr_deallocate (struct filehdr *h, struct bitmap *b) 
53 {
54   size_t i;
55   
56   ASSERT (h != NULL);
57   ASSERT (b != NULL);
58
59   for (i = 0; i < h->sector_cnt; i++)
60     bitmap_reset (b, h->sectors[i]);
61 }
62
63 /* Reads a file header from FILEHDR_SECTOR
64    and returns a new `struct filehdr' that contains it.
65    Returns a null pointer fi memory allocation fails. */
66 struct filehdr *
67 filehdr_read (disk_sector_t filehdr_sector) 
68 {
69   struct filehdr *h = calloc (1, sizeof *h);
70   if (h == NULL)
71     return NULL;
72
73   ASSERT (sizeof *h == DISK_SECTOR_SIZE);
74   disk_read (filesys_disk, filehdr_sector, h);
75
76   return h;
77 }
78
79 /* Writes H to disk in sector FILEHDR_SECTOR. */
80 void
81 filehdr_write (const struct filehdr *h, disk_sector_t filehdr_sector) 
82 {
83   ASSERT (h != NULL);
84   ASSERT (sizeof *h == DISK_SECTOR_SIZE);
85   disk_write (filesys_disk, filehdr_sector, h);
86 }
87
88 /* Frees the memory (but not the on-disk sector) associated with
89    H. */
90 void
91 filehdr_destroy (struct filehdr *h) 
92 {
93   free (h);
94 }
95
96 /* Returns the disk sector that contains byte offset POS within
97    the file with header H.
98    Returns -1 if H does not contain data for a byte at offset
99    POS. */
100 disk_sector_t
101 filehdr_byte_to_sector (const struct filehdr *h, off_t pos) 
102 {
103   size_t idx;
104
105   ASSERT (h != NULL);
106
107   idx = pos / DISK_SECTOR_SIZE;
108   return idx < h->sector_cnt ? h->sectors[idx] : (disk_sector_t) -1;
109 }
110
111 /* Returns the length, in bytes, of the file with header H, */
112 off_t
113 filehdr_length (const struct filehdr *h)
114 {
115   ASSERT (h != NULL);
116   return h->length;
117 }
118
119 /* Prints a representation of H to the system console. */
120 void
121 filehdr_print (const struct filehdr *h) 
122 {
123   size_t i;
124   
125   printk ("File header: %jd bytes, %zd sectors (",
126           (intmax_t) h->length, h->sector_cnt);
127
128   /* This loop could be unsafe for large h->sector_cnt, can you
129      see why? */
130   for (i = 0; i < h->sector_cnt; i++) 
131     {
132       if (i != 0)
133         printk (", ");
134       printk ("%jd", (intmax_t) h->sectors[i]); 
135     }
136   printk (")\n");
137 }