1 #include "filesys/directory.h"
5 #include "filesys/filesys.h"
6 #include "filesys/inode.h"
7 #include "threads/malloc.h"
12 struct inode
*inode
; /* Backing store. */
13 off_t pos
; /* Current position. */
16 /* A single directory entry. */
19 disk_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? */
24 /* Creates a directory with space for ENTRY_CNT entries in the
25 given SECTOR. Returns true if successful, false on failure. */
27 dir_create (disk_sector_t sector
, size_t entry_cnt
)
29 return inode_create (sector
, entry_cnt
* sizeof (struct dir_entry
));
32 /* Opens and returns the directory for the given INODE, of which
33 it takes ownership. Returns a null pointer on failure. */
35 dir_open (struct inode
*inode
)
37 struct dir
*dir
= calloc (1, sizeof *dir
);
38 if (inode
!= NULL
&& dir
!= NULL
)
52 /* Opens the root directory and returns a directory for it.
53 Return true if successful, false on failure. */
57 return dir_open (inode_open (ROOT_DIR_SECTOR
));
60 /* Opens and returns a new directory for the same inode as DIR.
61 Returns a null pointer on failure. */
63 dir_reopen (struct dir
*dir
)
65 return dir_open (inode_reopen (dir
->inode
));
68 /* Destroys DIR and frees associated resources. */
70 dir_close (struct dir
*dir
)
74 inode_close (dir
->inode
);
79 /* Returns the inode encapsulated by DIR. */
81 dir_get_inode (struct dir
*dir
)
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. */
92 lookup (const struct dir
*dir
, const char *name
,
93 struct dir_entry
*ep
, off_t
*ofsp
)
99 ASSERT (name
!= NULL
);
101 for (ofs
= 0; inode_read_at (dir
->inode
, &e
, sizeof e
, ofs
) == sizeof e
;
103 if (e
.in_use
&& !strcmp (name
, e
.name
))
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. */
119 dir_lookup (const struct dir
*dir
, const char *name
,
120 struct inode
**inode
)
124 ASSERT (dir
!= NULL
);
125 ASSERT (name
!= NULL
);
127 if (lookup (dir
, name
, &e
, NULL
))
128 *inode
= inode_open (e
.inode_sector
);
132 return *inode
!= NULL
;
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
138 Returns true if successful, false on failure.
139 Fails if NAME is invalid (i.e. too long) or a disk or memory
142 dir_add (struct dir
*dir
, const char *name
, disk_sector_t inode_sector
)
146 bool success
= false;
148 ASSERT (dir
!= NULL
);
149 ASSERT (name
!= NULL
);
151 /* Check NAME for validity. */
152 if (*name
== '\0' || strlen (name
) > NAME_MAX
)
155 /* Check that NAME is not in use. */
156 if (lookup (dir
, name
, NULL
, NULL
))
159 /* Set OFS to offset of free slot.
160 If there are no free slots, then it will be set to the
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
;
173 strlcpy (e
.name
, name
, sizeof e
.name
);
174 e
.inode_sector
= inode_sector
;
175 success
= inode_write_at (dir
->inode
, &e
, sizeof e
, ofs
) == sizeof e
;
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. */
185 dir_remove (struct dir
*dir
, const char *name
)
188 struct inode
*inode
= NULL
;
189 bool success
= false;
192 ASSERT (dir
!= NULL
);
193 ASSERT (name
!= NULL
);
195 /* Find directory entry. */
196 if (!lookup (dir
, name
, &e
, &ofs
))
200 inode
= inode_open (e
.inode_sector
);
204 /* Erase directory entry. */
206 if (inode_write_at (dir
->inode
, &e
, sizeof e
, ofs
) != sizeof e
)
210 inode_remove (inode
);
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. */
222 dir_readdir (struct dir
*dir
, char name
[NAME_MAX
+ 1])
226 while (inode_read_at (dir
->inode
, &e
, sizeof e
, dir
->pos
) == sizeof e
)
228 dir
->pos
+= sizeof e
;
231 strlcpy (name
, e
.name
, NAME_MAX
+ 1);