해당 INODE에 해당하는 디렉터리를 관리하는 struct dir를 메모리에 만들고 이 주소를 리턴한다.
struct dir *dir_open (struct inode *inode) {
struct dir *dir = calloc (1, sizeof *dir);
if (inode != NULL && dir != NULL) {
dir->inode = inode;
dir->pos = 0;
return dir;
} else {
inode_close (inode);
free (dir);
return NULL;
}
}
해당 디렉터리의 아이노드의 reference count(open cnt)를 1 감소시킨다. 만약 reference count가 0, 즉 이 아이노드를 열고 있는 프로세스가 없다면 해당 디렉터리가 소유하고 있는 자원들을 모두 반환한 후에 디렉터리 자체도 반환하면서 닫는다.
void dir_close (struct dir *dir) {
if (dir != NULL) {
inode_close (dir->inode);
free (dir);
}
}
---
void inode_close (struct inode *inode) {
if (inode == NULL)
return;
/* 이 프로세스가 아이노드를 열고 있는 마지막 프로세스라면 자원들을 해제해준다. */
if (--inode->open_cnt == 0) { // reference count를 1 낮추고
list_remove (&inode->elem); // open inode list에서 지워준다.
if (inode->removed) { // 지워져야 할 아이노드라면 할당된 클러스터를 다 반환한다.
#ifdef EFILESYS
fat_remove_chain(sector_to_cluster(inode->sector), 0); // 클러스터 할당 여부 false로.
#else
free_map_release (inode->sector, 1);
free_map_release (inode->data.start, bytes_to_sectors (inode->data.length));
}
free (inode); // 아이노드 구조체도 메모리에서 반환한다.
}
}
해당 디렉터리의 아이노드 구조체의 reference count를 1 증가시킨다. 그 후 해당 디렉터리를 관리하는 struct dir를 따로 만든다.
즉, 같은 아이노드의 디렉터리를 여러 프로세스에서 열 수 있으나, 그 각각의 디렉터리는 따로따로 관리해주어야 한다.
dir_reopen (struct dir *dir) {
return dir_open (inode_reopen (dir->inode));
}
디렉터리 내의 디렉터리 엔트리들을 쭉 살피면서 NAME과 같은 이름을 가진 파일을 찾는다.
static bool lookup (const struct dir *dir, const char *name,
struct dir_entry *ep, off_t *ofsp) {
struct dir_entry e;
size_t ofs;
ASSERT (dir != NULL);
ASSERT (name != NULL);
/* 디렉터리의 데이터 영역에서 디렉터리 엔트리를 하나씩 읽어서 E에 저장한다.
만약 디렉터리가 사용되었고 NAME과 같은 이름이라면
TRUE를 리턴한다. */
for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
ofs += sizeof e)
if (e.in_use && !strcmp (name, e.name)) {
if (ep != NULL)
*ep = e;
if (ofsp != NULL)
*ofsp = ofs;
return true;
}
return false;
}