Redo makefiles.
[pintos-anon] / src / filesys / directory.c
1 #include "directory.h"
2 #include "file.h"
3 #include "fsutil.h"
4 #include "lib/lib.h"
5 #include "threads/malloc.h"
6
7 /* Initializes D as a directory that holds ENTRY_CNT entries. */
8 bool
9 dir_init (struct dir *d, size_t entry_cnt) 
10 {
11   ASSERT (d != NULL);
12   d->entry_cnt = entry_cnt;
13   d->entries = calloc (1, sizeof *d->entries * entry_cnt);
14   return d->entries != NULL;
15 }
16
17 /* Destroys D and frees associated resources. */
18 void
19 dir_destroy (struct dir *d) 
20 {
21   if (d != NULL) 
22     free (d->entries);
23 }
24
25 /* Returns the size of D in bytes. */
26 static off_t
27 dir_size (struct dir *d) 
28 {
29   ASSERT (d != NULL);
30   return d->entry_cnt * sizeof *d->entries;
31 }
32
33 /* Reads D from FILE.
34    D must have already been initialized, to the correct number of
35    entries, with dir_init(). */
36 void
37 dir_read (struct dir *d, struct file *file) 
38 {
39   ASSERT (d != NULL);
40   ASSERT (file != NULL);
41   ASSERT (file_length (file) >= dir_size (d));
42
43   file_read_at (file, d->entries, dir_size (d), 0);
44 }
45
46 /* Writes D to FILE.
47    D must have already been initialized, to the correct number of
48    entries, with dir_init(). */
49 void
50 dir_write (struct dir *d, struct file *file) 
51 {
52   file_write_at (file, d->entries, dir_size (d), 0);
53 }
54
55 /* Searches D for a file named NAME.
56    If successful, returns the file's entry;
57    otherwise, returns a null pointer. */
58 static struct dir_entry *
59 lookup (const struct dir *d, const char *name) 
60 {
61   size_t i;
62   
63   ASSERT (d != NULL);
64   ASSERT (name != NULL);
65
66   if (strlen (name) > NAME_MAX)
67     return NULL;
68
69   for (i = 0; i < d->entry_cnt; i++) 
70     {
71       struct dir_entry *e = &d->entries[i];
72       if (e->in_use && !strcmp (name, e->name))
73         return e;
74     }
75   return NULL;
76 }
77
78 /* Searches D for a file named NAME
79    and returns true if one exists, false otherwise.
80    If FILEHDR_SECTOR is nonnull, then on success *FILEHDR_SECTOR
81    is set to the sector that contains the file's header. */
82 bool
83 dir_lookup (const struct dir *d, const char *name,
84             disk_sector_t *filehdr_sector) 
85 {
86   const struct dir_entry *e;
87
88   ASSERT (d != NULL);
89   ASSERT (name != NULL);
90   
91   e = lookup (d, name);
92   if (e != NULL) 
93     {
94       if (filehdr_sector != NULL)
95         *filehdr_sector = e->filehdr_sector;
96       return true;
97     }
98   else
99     return false;
100 }
101
102 /* Adds a file named NAME to D, which must not already contain a
103    file by that name.  The file's header is in sector
104    FILEHDR_SECTOR.
105    Returns true if successful, false on failure.
106    Fails if NAME is invalid (i.e. too long) or if D has no free
107    directory entries. */
108 bool
109 dir_add (struct dir *d, const char *name, disk_sector_t filehdr_sector) 
110 {
111   size_t i;
112   
113   ASSERT (d != NULL);
114   ASSERT (name != NULL);
115   ASSERT (lookup (d, name) == NULL);
116
117   if (strlen (name) > NAME_MAX)
118     return false;
119
120   for (i = 0; i < d->entry_cnt; i++)
121     {
122       struct dir_entry *e = &d->entries[i];
123       if (!e->in_use) 
124         {
125           e->in_use = true;
126           strlcpy (e->name, name, sizeof e->name);
127           e->filehdr_sector = filehdr_sector;
128           return true;
129         }
130     }
131   return false;
132 }
133
134 /* Removes any entry for NAME in D.
135    Returns true if successful, false on failure,
136    which occurs only if there is no file with the given NAME. */
137 bool
138 dir_remove (struct dir *d, const char *name) 
139 {
140   struct dir_entry *e;
141
142   ASSERT (d != NULL);
143   ASSERT (name != NULL);
144
145   e = lookup (d, name);
146   if (e != NULL) 
147     {
148       e->in_use = false;
149       return true;
150     }
151   else
152     return false;
153 }
154
155 /* Prints the names of the files in D to the system console. */
156 void
157 dir_list (const struct dir *d)
158 {
159   struct dir_entry *e;
160   
161   for (e = d->entries; e < d->entries + d->entry_cnt; e++)
162     if (e->in_use)
163       printk ("%s\n", e->name);
164 }
165
166 /* Dumps the contents of D, including its files' names and their
167    contents, to the system console. */
168 void
169 dir_dump (const struct dir *d) 
170 {
171   struct dir_entry *e;
172   
173   for (e = d->entries; e < d->entries + d->entry_cnt; e++)
174     if (e->in_use) 
175       {
176         printk ("Contents of %s:\n", e->name);
177         fsutil_print (e->name);
178         printk ("\n");
179       }
180 }