PKUOS - Pintos
Pintos source browser for PKU Operating System course
directory.c
Go to the documentation of this file.
1#include "filesys/directory.h"
2#include <stdio.h>
3#include <string.h>
4#include <list.h>
5#include "filesys/filesys.h"
6#include "filesys/inode.h"
7#include "threads/malloc.h"
8
9/** A directory. */
10struct dir
11 {
12 struct inode *inode; /**< Backing store. */
13 off_t pos; /**< Current position. */
14 };
15
16/** A single directory entry. */
17struct dir_entry
18 {
19 block_sector_t inode_sector; /**< Sector number of header. */
20 char name[NAME_MAX + 1]; /**< Null terminated file name. */
21 bool in_use; /**< In use or free? */
22 };
23
24/** Creates a directory with space for ENTRY_CNT entries in the
25 given SECTOR. Returns true if successful, false on failure. */
26bool
27dir_create (block_sector_t sector, size_t entry_cnt)
28{
29 return inode_create (sector, entry_cnt * sizeof (struct dir_entry));
30}
31
32/** Opens and returns the directory for the given INODE, of which
33 it takes ownership. Returns a null pointer on failure. */
34struct dir *
36{
37 struct dir *dir = calloc (1, sizeof *dir);
38 if (inode != NULL && dir != NULL)
39 {
40 dir->inode = inode;
41 dir->pos = 0;
42 return dir;
43 }
44 else
45 {
47 free (dir);
48 return NULL;
49 }
50}
51
52/** Opens the root directory and returns a directory for it.
53 Return true if successful, false on failure. */
54struct dir *
56{
58}
59
60/** Opens and returns a new directory for the same inode as DIR.
61 Returns a null pointer on failure. */
62struct dir *
63dir_reopen (struct dir *dir)
64{
65 return dir_open (inode_reopen (dir->inode));
66}
67
68/** Destroys DIR and frees associated resources. */
69void
70dir_close (struct dir *dir)
71{
72 if (dir != NULL)
73 {
75 free (dir);
76 }
77}
78
79/** Returns the inode encapsulated by DIR. */
80struct inode *
82{
83 return dir->inode;
84}
85
86/** Searches DIR for a file with the given NAME.
87 If successful, returns true, sets *EP to the directory entry
88 if EP is non-null, and sets *OFSP to the byte offset of the
89 directory entry if OFSP is non-null.
90 otherwise, returns false and ignores EP and OFSP. */
91static bool
92lookup (const struct dir *dir, const char *name,
93 struct dir_entry *ep, off_t *ofsp)
94{
95 struct dir_entry e;
96 size_t ofs;
97
98 ASSERT (dir != NULL);
99 ASSERT (name != NULL);
100
101 for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
102 ofs += sizeof e)
103 if (e.in_use && !strcmp (name, e.name))
104 {
105 if (ep != NULL)
106 *ep = e;
107 if (ofsp != NULL)
108 *ofsp = ofs;
109 return true;
110 }
111 return false;
112}
113
114/** Searches DIR for a file with the given NAME
115 and returns true if one exists, false otherwise.
116 On success, sets *INODE to an inode for the file, otherwise to
117 a null pointer. The caller must close *INODE. */
118bool
119dir_lookup (const struct dir *dir, const char *name,
120 struct inode **inode)
121{
122 struct dir_entry e;
123
124 ASSERT (dir != NULL);
125 ASSERT (name != NULL);
126
127 if (lookup (dir, name, &e, NULL))
129 else
130 *inode = NULL;
131
132 return *inode != NULL;
133}
134
135/** Adds a file named NAME to DIR, which must not already contain a
136 file by that name. The file's inode is in sector
137 INODE_SECTOR.
138 Returns true if successful, false on failure.
139 Fails if NAME is invalid (i.e. too long) or a disk or memory
140 error occurs. */
141bool
143{
144 struct dir_entry e;
145 off_t ofs;
146 bool success = false;
147
148 ASSERT (dir != NULL);
149 ASSERT (name != NULL);
150
151 /* Check NAME for validity. */
152 if (*name == '\0' || strlen (name) > NAME_MAX)
153 return false;
154
155 /* Check that NAME is not in use. */
156 if (lookup (dir, name, NULL, NULL))
157 goto done;
158
159 /* Set OFS to offset of free slot.
160 If there are no free slots, then it will be set to the
161 current end-of-file.
162
163 inode_read_at() will only return a short read at end of file.
164 Otherwise, we'd need to verify that we didn't get a short
165 read due to something intermittent such as low memory. */
166 for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
167 ofs += sizeof e)
168 if (!e.in_use)
169 break;
170
171 /* Write slot. */
172 e.in_use = true;
173 strlcpy (e.name, name, sizeof e.name);
175 success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
176
177 done:
178 return success;
179}
180
181/** Removes any entry for NAME in DIR.
182 Returns true if successful, false on failure,
183 which occurs only if there is no file with the given NAME. */
184bool
185dir_remove (struct dir *dir, const char *name)
186{
187 struct dir_entry e;
188 struct inode *inode = NULL;
189 bool success = false;
190 off_t ofs;
191
192 ASSERT (dir != NULL);
193 ASSERT (name != NULL);
194
195 /* Find directory entry. */
196 if (!lookup (dir, name, &e, &ofs))
197 goto done;
198
199 /* Open inode. */
201 if (inode == NULL)
202 goto done;
203
204 /* Erase directory entry. */
205 e.in_use = false;
206 if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e)
207 goto done;
208
209 /* Remove inode. */
211 success = true;
212
213 done:
215 return success;
216}
217
218/** Reads the next directory entry in DIR and stores the name in
219 NAME. Returns true if successful, false if the directory
220 contains no more entries. */
221bool
222dir_readdir (struct dir *dir, char name[NAME_MAX + 1])
223{
224 struct dir_entry e;
225
226 while (inode_read_at (dir->inode, &e, sizeof e, dir->pos) == sizeof e)
227 {
228 dir->pos += sizeof e;
229 if (e.in_use)
230 {
231 strlcpy (name, e.name, NAME_MAX + 1);
232 return true;
233 }
234 }
235 return false;
236}
uint32_t block_sector_t
Index of a block device sector.
Definition: block.h:15
#define ASSERT(CONDITION)
This is outside the header guard so that debug.h may be included multiple times with different settin...
Definition: debug.h:31
struct dir * dir_open(struct inode *inode)
Opens and returns the directory for the given INODE, of which it takes ownership.
Definition: directory.c:35
struct inode * dir_get_inode(struct dir *dir)
Returns the inode encapsulated by DIR.
Definition: directory.c:81
bool dir_lookup(const struct dir *dir, const char *name, struct inode **inode)
Searches DIR for a file with the given NAME and returns true if one exists, false otherwise.
Definition: directory.c:119
bool dir_add(struct dir *dir, const char *name, block_sector_t inode_sector)
Adds a file named NAME to DIR, which must not already contain a file by that name.
Definition: directory.c:142
struct dir * dir_reopen(struct dir *dir)
Opens and returns a new directory for the same inode as DIR.
Definition: directory.c:63
void dir_close(struct dir *dir)
Destroys DIR and frees associated resources.
Definition: directory.c:70
static bool lookup(const struct dir *dir, const char *name, struct dir_entry *ep, off_t *ofsp)
Searches DIR for a file with the given NAME.
Definition: directory.c:92
bool dir_create(block_sector_t sector, size_t entry_cnt)
Creates a directory with space for ENTRY_CNT entries in the given SECTOR.
Definition: directory.c:27
bool dir_remove(struct dir *dir, const char *name)
Removes any entry for NAME in DIR.
Definition: directory.c:185
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
struct dir * dir_open_root(void)
Opens the root directory and returns a directory for it.
Definition: directory.c:55
#define NAME_MAX
Maximum length of a file name component.
Definition: directory.h:12
#define ROOT_DIR_SECTOR
Root directory file inode sector.
Definition: filesys.h:9
off_t inode_write_at(struct inode *inode, const void *buffer_, off_t size, off_t offset)
Writes SIZE bytes from BUFFER into INODE, starting at OFFSET.
Definition: inode.c:258
off_t inode_read_at(struct inode *inode, void *buffer_, off_t size, off_t offset)
Reads SIZE bytes from INODE into BUFFER, starting at position OFFSET.
Definition: inode.c:201
struct inode * inode_reopen(struct inode *inode)
Reopens and returns INODE.
Definition: inode.c:146
void inode_close(struct inode *inode)
Closes INODE and writes it to disk.
Definition: inode.c:164
struct inode * inode_open(block_sector_t sector)
Reads an inode from SECTOR and returns a ‘struct inode’ that contains it.
Definition: inode.c:112
bool inode_create(block_sector_t sector, off_t length)
Initializes an inode with LENGTH bytes of data and writes the new inode to sector SECTOR on the file ...
Definition: inode.c:73
void inode_remove(struct inode *inode)
Marks INODE to be deleted when it is closed by the last caller who has it open.
Definition: inode.c:191
char * name[]
Definition: insult.c:47
void * calloc(size_t a, size_t b)
Allocates and return A times B bytes initialized to zeroes.
Definition: malloc.c:159
void free(void *p)
Frees block P, which must have been previously allocated with malloc(), calloc(), or realloc().
Definition: malloc.c:219
int32_t off_t
An offset within a file.
Definition: off_t.h:9
#define NULL
Definition: stddef.h:4
size_t strlen(const char *string)
Returns the length of STRING.
Definition: string.c:293
size_t strlcpy(char *dst, const char *src, size_t size)
Copies string SRC to DST.
Definition: string.c:326
int strcmp(const char *a_, const char *b_)
Finds the first differing characters in strings A and B.
Definition: string.c:73
A single directory entry.
Definition: directory.c:18
block_sector_t inode_sector
Sector number of header.
Definition: directory.c:19
bool in_use
In use or free?
Definition: directory.c:21
char name[NAME_MAX+1]
Null terminated file name.
Definition: directory.c:20
A directory.
Definition: directory.c:11
off_t pos
Current position.
Definition: directory.c:13
struct inode * inode
Backing store.
Definition: directory.c:12
In-memory inode.
Definition: inode.c:33