00001 #include "filesys/directory.h"
00002
00003 #include <stdio.h>
00004 #include <string.h>
00005 #include <list.h>
00006 #include "filesys/filesys.h"
00007 #include "filesys/inode.h"
00008 #include "threads/malloc.h"
00009
00010
00011 struct dir
00012 {
00013 struct inode *inode;
00014 off_t pos;
00015 };
00016
00017
00018 struct dir_entry
00019 {
00020 block_sector_t inode_sector;
00021 char name[NAME_MAX + 1];
00022 bool in_use;
00023 };
00024
00025
00026
00027 bool
00028 dir_create (block_sector_t sector, size_t entry_cnt)
00029 {
00030 return inode_create (sector, entry_cnt * sizeof (struct dir_entry));
00031 }
00032
00033
00034
00035 struct dir *
00036 dir_open (struct inode *inode)
00037 {
00038 struct dir *dir = calloc (1, sizeof *dir);
00039 if (inode != NULL && dir != NULL)
00040 {
00041 dir->inode = inode;
00042 dir->pos = 0;
00043 return dir;
00044 }
00045 else
00046 {
00047 inode_close (inode);
00048 free (dir);
00049 return NULL;
00050 }
00051 }
00052
00053
00054
00055 struct dir *
00056 dir_open_root (void)
00057 {
00058 return dir_open (inode_open (ROOT_DIR_SECTOR));
00059 }
00060
00061
00062
00063 struct dir *
00064 dir_reopen (struct dir *dir)
00065 {
00066 return dir_open (inode_reopen (dir->inode));
00067 }
00068
00069
00070 void
00071 dir_close (struct dir *dir)
00072 {
00073 if (dir != NULL)
00074 {
00075 inode_close (dir->inode);
00076 free (dir);
00077 }
00078 }
00079
00080
00081 struct inode *
00082 dir_get_inode (struct dir *dir)
00083 {
00084 return dir->inode;
00085 }
00086
00087
00088
00089
00090
00091
00092 static bool
00093 lookup (const struct dir *dir, const char *name,
00094 struct dir_entry *ep, off_t *ofsp)
00095 {
00096 struct dir_entry e;
00097 size_t ofs;
00098
00099 ASSERT (dir != NULL);
00100 ASSERT (name != NULL);
00101
00102 for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
00103 ofs += sizeof e)
00104 if (e.in_use && !strcmp (name, e.name))
00105 {
00106 if (ep != NULL)
00107 *ep = e;
00108 if (ofsp != NULL)
00109 *ofsp = ofs;
00110 return true;
00111 }
00112 return false;
00113 }
00114
00115
00116
00117
00118
00119 bool
00120 dir_lookup (const struct dir *dir, const char *name,
00121 struct inode **inode)
00122 {
00123 struct dir_entry e;
00124
00125 ASSERT (dir != NULL);
00126 ASSERT (name != NULL);
00127
00128 if (lookup (dir, name, &e, NULL))
00129 *inode = inode_open (e.inode_sector);
00130 else
00131 *inode = NULL;
00132
00133 return *inode != NULL;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142 bool
00143 dir_add (struct dir *dir, const char *name, block_sector_t inode_sector)
00144 {
00145 struct dir_entry e;
00146 off_t ofs;
00147 bool success = false;
00148
00149 ASSERT (dir != NULL);
00150 ASSERT (name != NULL);
00151
00152
00153 if (*name == '\0' || strlen (name) > NAME_MAX)
00154 return false;
00155
00156
00157 if (lookup (dir, name, NULL, NULL))
00158 goto done;
00159
00160
00161
00162
00163
00164
00165
00166
00167 for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
00168 ofs += sizeof e)
00169 if (!e.in_use)
00170 break;
00171
00172
00173 e.in_use = true;
00174 strlcpy (e.name, name, sizeof e.name);
00175 e.inode_sector = inode_sector;
00176 success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
00177
00178 done:
00179 return success;
00180 }
00181
00182
00183
00184
00185 bool
00186 dir_remove (struct dir *dir, const char *name)
00187 {
00188 struct dir_entry e;
00189 struct inode *inode = NULL;
00190 bool success = false;
00191 off_t ofs;
00192
00193 ASSERT (dir != NULL);
00194 ASSERT (name != NULL);
00195
00196
00197 if (!lookup (dir, name, &e, &ofs))
00198 goto done;
00199
00200
00201 inode = inode_open (e.inode_sector);
00202 if (inode == NULL)
00203 goto done;
00204
00205
00206 e.in_use = false;
00207 if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e)
00208 goto done;
00209
00210
00211 inode_remove (inode);
00212 success = true;
00213
00214 done:
00215 inode_close (inode);
00216 return success;
00217 }
00218
00219
00220
00221
00222 bool
00223 dir_readdir (struct dir *dir, char name[NAME_MAX + 1])
00224 {
00225 struct dir_entry e;
00226
00227 while (inode_read_at (dir->inode, &e, sizeof e, dir->pos) == sizeof e)
00228 {
00229 dir->pos += sizeof e;
00230 if (e.in_use)
00231 {
00232 strlcpy (name, e.name, NAME_MAX + 1);
00233 return true;
00234 }
00235 }
00236 return false;
00237 }