CS318 - Pintos
Pintos source browser for JHU CS318 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. */
10 struct dir
11  {
12  struct inode *inode; /**< Backing store. */
13  off_t pos; /**< Current position. */
14  };
15 
16 /** A single directory entry. */
17 struct 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. */
26 bool
27 dir_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. */
34 struct dir *
35 dir_open (struct inode *inode)
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. */
54 struct dir *
56 {
58 }
59 
60 /** Opens and returns a new directory for the same inode as DIR.
61  Returns a null pointer on failure. */
62 struct dir *
63 dir_reopen (struct dir *dir)
64 {
65  return dir_open (inode_reopen (dir->inode));
66 }
67 
68 /** Destroys DIR and frees associated resources. */
69 void
70 dir_close (struct dir *dir)
71 {
72  if (dir != NULL)
73  {
75  free (dir);
76  }
77 }
78 
79 /** Returns the inode encapsulated by DIR. */
80 struct inode *
81 dir_get_inode (struct dir *dir)
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. */
91 static bool
92 lookup (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. */
118 bool
119 dir_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. */
141 bool
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. */
184 bool
185 dir_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:
214  inode_close (inode);
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. */
221 bool
222 dir_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 }
name
char * name[]
Definition: insult.c:47
dir::pos
off_t pos
Current position.
Definition: directory.c:13
dir_open
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
inode_remove
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
dir_entry::name
char name[NAME_MAX+1]
Null terminated file name.
Definition: directory.c:20
NULL
#define NULL
Definition: stddef.h:4
filesys.h
string.h
dir_open_root
struct dir * dir_open_root(void)
Opens the root directory and returns a directory for it.
Definition: directory.c:55
strcmp
int strcmp(const char *a_, const char *b_)
Finds the first differing characters in strings A and B.
Definition: string.c:73
dir_lookup
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
off_t
int32_t off_t
An offset within a file.
Definition: off_t.h:9
NAME_MAX
#define NAME_MAX
Maximum length of a file name component.
Definition: directory.h:12
dir_readdir
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
free
void free(void *p)
Frees block P, which must have been previously allocated with malloc(), calloc(), or realloc().
Definition: malloc.c:219
block_sector_t
uint32_t block_sector_t
Index of a block device sector.
Definition: block.h:15
dir_get_inode
struct inode * dir_get_inode(struct dir *dir)
Returns the inode encapsulated by DIR.
Definition: directory.c:81
inode_write_at
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
directory.h
ROOT_DIR_SECTOR
#define ROOT_DIR_SECTOR
Root directory file inode sector.
Definition: filesys.h:9
inode
In-memory inode.
Definition: inode.c:32
dir_create
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
inode_create
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
dir_entry::in_use
bool in_use
In use or free?
Definition: directory.c:21
malloc.h
calloc
void * calloc(size_t a, size_t b)
Allocates and return A times B bytes initialized to zeroes.
Definition: malloc.c:159
dir_entry::inode_sector
block_sector_t inode_sector
Sector number of header.
Definition: directory.c:19
ASSERT
#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
dir::inode
struct inode * inode
Backing store.
Definition: directory.c:12
strlen
size_t strlen(const char *string)
Returns the length of STRING.
Definition: string.c:293
dir_add
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
dir_entry
A single directory entry.
Definition: directory.c:17
inode_open
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
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Copies string SRC to DST.
Definition: string.c:326
dir_remove
bool dir_remove(struct dir *dir, const char *name)
Removes any entry for NAME in DIR.
Definition: directory.c:185
inode_read_at
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
list.h
dir_reopen
struct dir * dir_reopen(struct dir *dir)
Opens and returns a new directory for the same inode as DIR.
Definition: directory.c:63
inode_reopen
struct inode * inode_reopen(struct inode *inode)
Reopens and returns INODE.
Definition: inode.c:146
dir
A directory.
Definition: directory.c:10
lookup
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
dir_close
void dir_close(struct dir *dir)
Destroys DIR and frees associated resources.
Definition: directory.c:70
inode_close
void inode_close(struct inode *inode)
Closes INODE and writes it to disk.
Definition: inode.c:164
inode.h