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