기본적인 파일 시스템에서 모든 파일들은 하나의 디렉토리에 있다. 디렉토리 엔트리가 파일이나 다른 디렉토리를 가르키도록 수정해야 한다. 즉 root 디렉토리 내 파일과 디렉토리를 생성할 수 있도록 계층구조를 구현해야 한다.
전 포스팅에서 현대 파일 시스템은 초기 사이즈가 0으로 생성되고 파일 끝 부분에 write될 때 확장된다고 했다. 디렉토리 역시 원래 크기 이상으로 확장될 수 있도록 하자.
기본 파일 시스템은 파일 이름이 14 character 제한이 있다. 개별적으로 파일 이름 구성요소에 대한 제한을 유지하거나 확정하거나 등 원하는대로 확장할 수 있다.
각 프로세스에 대해 별도의 현재 디렉토리를 유지하라. 시작 시 루트(root)를 초기화한 프로세스의 현재 디렉토리로 설정해라. 하나의 프로세스가 fork 시스템 콜에 희해 다른 것을 시작할 때, 자식 프로세스는 부모의 현재 디렉토리를 상속한다. 그 후, 두 프로세스의 현재 디렉토리는 독립적이게 되는데, 자신의 현재 디렉토리를 변경하는 것은 다른 프로세스에 영향을 미치지 않는다.
호출자로부터 제공받는 파일 이름이 모든 위치에서 절대적, 상대적 경로 이름을 사용할 수 있도록 기존의 시스템 콜을 업데이트해라. 디렉토리 구분 문자는 슬래시('/')이다. 또한 Unix와 동일한 의미를 가지는 특수 파일 이름 '.'과 '..'도 지원해야 한다.
또한 디렉토리를 열 수 있도록 open 시스템콜도 업데이트해라. 기존 시스템 콜에서는 오직 close만 하나의 디렉토리에서 파일 디스크립터를 수요하는 것을 필요로 했다.
remove 시스템 콜도 수정해야 한다. 일반 파일뿐만 아니라 빈 디렉토리도 지우는 기능을 구현해야 한다는 말(루트 디렉토리 제외). 디렉토리는 파일이나 하위 디렉토리를 가지지 않았을 때만 삭제된다('.' 및 '..' 제외). 한 프로세스가 열려 있거나 현재 사용 중인 프로세스가 있는 디렉토리를 삭제해야 하는지 여부를 결정할 수도 있다. 만약 이게 허용된다면, 삭제된 디렉토리 안의 파일을 열거나 생성하는 것은 허용하면 안 된다. 아래의 새로운 시스템 콜들을 구현해라! 시스템 콜은 어디에서 구현? userporg/syscall.c 내에 시스템콜 핸들러 스위치문에 추가하고 함수도 새로 만들자.
먼저 bool chdir() 함수다. 이 함수는 현재 실행 중인 프로세스의 디렉토리를 절대적 혹은 상대적인 dir로 바꾸는 기능을 한다. 성공한다면 true를 리턴, 실패한다면 false 리턴
이 함수 구현 이전에 선행해야 할 작업들이 있다. 먼저 프로세스별로 다른 디렉토리를 설정하기 위해 thread 구조체에 디렉토리를 구분할 수 있는 변수를 생성한다.
struct thread {
...
#ifdef VM
...
// directory 표시
struct dir *cur_dir;
#endif
...
};
inode_disk 구조체에도 마찬가지로 디렉토리를 구분하는 변수를 만들어준다.
/* On-disk inode.
* Must be exactly DISK_SECTOR_SIZE bytes long. */
struct inode_disk {
disk_sector_t start; /* First data sector. */
off_t length; /* File size in bytes. */
unsigned magic; /* Magic number. */
uint32_t unused[125]; /* Not used. */
uint32_t is_dir; // 디렉토리 구분
};
그리고 inode가 디렉토리인지 아닌지 판단하는 함수 inode_is_dir()을 filesys/inode.c에 생성한다.
// inode가 directory인지 판단
bool inode_is_dir(const struct inode* inode) {
bool result;
// inode_disk 자료구조를 메모리에 할당
struct inode_disk *disk_inode = calloc (1, sizeof *disk_inode);
// in-memory inode의on-disk inode를읽어inode_disk에저장
disk_read(filesys_disk, cluster_to_sector(inode->sector), disk_inode);
// on-disk inode의is_dir을result에저장하여반환
result = disk_inode->is_dir;
free(disk_inode);
return result;
}
이제 sys_chdir() 함수 구현
// 현재 디렉토리의 위치 변경
bool sys_chdir(const char *path_name) {
if (path_name == NULL) {
return false;
}
// name의 파일 경로 를 cp_name에 복사
char *cp_name = (char *)malloc(strlen(path_name) + 1);
strlcpy(cp_name, path_name, strlen(path_name) + 1);
struct dir *chdir = NULL;
if (cp_name[0] == '/') { // 절대 경로로 디렉토리 되어 있다면
chdir = dir_open_root();
}
else { // 상대 경로로 디렉토리 되어 있다면
chdir = dir_reopen(thread_current()->cur_dir);
}
// dir경로를 분석하여 디렉터리를 반환
char *token, *savePtr;
token = strtok_r(cp_name, "/", &savePtr);
struct inode *inode = NULL;
while (token != NULL) {
// dir에서 token이름의 파일을 검색하여 inode의 정보를 저장
if (!dir_lookup(chdir, token, &inode)) {
dir_close(chdir);
return false;
}
// inode가 파일일 경우 NULL 반환
if (!inode_is_dir(inode)) {
dir_close(chdir);
return false;
}
// dir의 디렉터리 정보를 메모리에서 해지
dir_close(chdir);
// inode의 디렉터리 정보를 dir에저장
chdir = dir_open(inode);
// token에검색할경로이름저장
token = strtok_r(NULL, "/", &savePtr);
}
// 스레드의현재작업디렉터리를변경
dir_close(thread_current()->cur_dir);
thread_current()->cur_dir = chdir;
free(cp_name);
return true;
}
다음은 mkdir() 함수 구현이다. 변수 이름처럼 새로운 디렉토리를 생성하는 함수다. 이 때 기존에 이미 존재하는 디렉토리 이름으로 생성할 수 없다. 하나의 예시로는 mkdir("a/b/c") 는 a/b 라는 디렉토리가 기존에 존재했다면 생성이 되지만, a/b/c 디렉토리가 기존에 있었다면 생성되지 않는다.
// directory 생성
bool sys_mkdir(const char *dir) {
lock_acquire(&file_rw_lock);
bool new_dir = filesys_create_dir(dir);
lock_release(&file_rw_lock);
return new_dir;
}
new_dir = filesys_create_dir(), 즉 디렉토리를 생성하기 위한 함수를 filesys.c에 구현한다.
bool filesys_create_dir(const char* name) {
bool success = false;
// name의 파일경로를 cp_name에복사
char* cp_name = (char *)malloc(strlen(name) + 1);
strlcpy(cp_name, name, strlen(name) + 1);
// name 경로분석
char* file_name = (char *)malloc(strlen(name) + 1);
struct dir* dir = parse_path(cp_name, file_name);
// bitmap에서 inode sector 번호 할당
cluster_t inode_cluster = fat_create_chain(0);
struct inode *sub_dir_inode;
struct dir *sub_dir = NULL;
/* 할당 받은 sector에 file_name의 디렉터리 생성
디렉터리 엔트리에 file_name의 엔트리 추가
디렉터리 엔트리에 ‘.’, ‘..’ 파일의 엔트리 추가 */
success = ( // ".", ".." 추가
dir != NULL
&& dir_create(inode_cluster, 16)
&& dir_add(dir, file_name, inode_cluster)
&& dir_lookup(dir, file_name, &sub_dir_inode)
&& dir_add(sub_dir = dir_open(sub_dir_inode), ".", inode_cluster)
&& dir_add(sub_dir, "..", inode_get_inumber(dir_get_inode(dir))));
if (!success && inode_cluster != 0) {
fat_remove_chain(inode_cluster, 0);
}
dir_close(sub_dir);
dir_close(dir);
free(cp_name);
free(file_name);
return success;
}
// 경로 분석 함수 구현
struct dir *parse_path(char *path_name, char *file_name) { // file_name: path_name을 분석하여 파일, 디렉터리의 이름을 포인팅
struct dir *dir = NULL;
if (path_name == NULL || file_name == NULL)
return NULL;
if (strlen(path_name) == 0)
return NULL;
// path_name의 절대/상대 경로에 따른 디렉터리 정보 저장
if(path_name[0] == '/') {
dir = dir_open_root();
}
else {
dir = dir_reopen(thread_current()->cur_dir);
}
char *token, *nextToken, *savePtr;
token = strtok_r(path_name, "/", &savePtr);
nextToken = strtok_r(NULL, "/", &savePtr);
// "/"를 open하려는 케이스
if(token == NULL) {
token = (char*)malloc(2);
strlcpy(token, ".", 2);
}
struct inode *inode;
while (token != NULL && nextToken != NULL) {
// dir에서 token이름의 파일을 검색하여 inode의 정보를 저장
if (!dir_lookup(dir, token, &inode)) {
dir_close(dir);
return NULL;
}
if(inode->data.is_link) { // 링크 파일인 경우
char* new_path = (char*)malloc(sizeof(strlen(inode->data.link_name)) + 1);
strlcpy(new_path, inode->data.link_name, strlen(inode->data.link_name) + 1);
strlcpy(path_name, new_path, strlen(new_path) + 1);
free(new_path);
strlcat(path_name, "/", strlen(path_name) + 2);
strlcat(path_name, nextToken, strlen(path_name) + strlen(nextToken) + 1);
strlcat(path_name, savePtr, strlen(path_name) + strlen(savePtr) + 1);
dir_close(dir);
// 파싱된 경로로 다시 시작한다
if(path_name[0] == '/') {
dir = dir_open_root();
}
else {
dir = dir_reopen(thread_current()->cur_dir);
}
token = strtok_r(path_name, "/", &savePtr);
nextToken = strtok_r(NULL, "/", &savePtr);
continue;
}
// inode가 파일일 경우 NULL 반환
if(!inode_is_dir(inode)) {
dir_close(dir);
inode_close(inode);
return NULL;
}
// dir의 디렉터리 정보를 메모리에서 해지
dir_close(dir);
// inode의 디렉터리 정보를 dir에 저장
dir = dir_open(inode);
// token에 검색할 경로이름 저장
token = nextToken;
nextToken = strtok_r(NULL, "/", &savePtr);
}
// token의 파일이름을 file_name에 저장
strlcpy (file_name, token, strlen(token) + 1);
// dir정보반환
return dir;
}
이 때, dir_create()함수에서 inode가 디렉토리 여부를 파악하기 위해 이 함수 내 inode_create() 함수에서 파일시스템일 때 동작하는 코드를 구현하자. 기존 함수 인자 뒤에 uint32_t is_dir 인자를 추가해준다.
bool inode_create (disk_sector_t sector, off_t length, uint32_t is_dir) {
// for filesystem
#ifdef EFILESYS
struct inode_disk *disk_inode = NULL;
bool success = false;
ASSERT (length >= 0);
/* If this assertion fails, the inode structure is not exactly
* one sector in size, and you should fix that. */
ASSERT (sizeof *disk_inode == DISK_SECTOR_SIZE);
disk_inode = calloc (1, sizeof *disk_inode);
if (disk_inode != NULL) {
size_t sectors = bytes_to_sectors (length);
disk_inode->length = length;
disk_inode->magic = INODE_MAGIC;
// directory 여부 추가
disk_inode->is_dir = is_dir;
// inode의 파일 정보를 저장할 cluster
cluster_t cluster = fat_create_chain(0);
if(cluster) {
// inode disk 정보 기록
disk_inode->start = cluster;
disk_write (filesys_disk, cluster_to_sector(sector), disk_inode);
if (sectors > 0) {
static char zeros[DISK_SECTOR_SIZE];
size_t i;
// inode file 공간 할당
disk_write (filesys_disk, cluster_to_sector(disk_inode->start), zeros);
for (i = 1; i < sectors; i++){
cluster_t tmp = cluster_to_sector(fat_create_chain(cluster));
disk_write (filesys_disk, tmp, zeros);
}
}
success = true;
}
free (disk_inode);
}
return success;
#else
...
#endif
}
다음 함수에서 inode_create() 호출 시, 변경된 인터페이스에 맞게 is_dir값을 설정한다.
디렉터리의 on-disk inode 생성시 is_dir값을 1로 설정
bool dir_create (disk_sector_t sector, size_t entry_cnt) {
return inode_create (sector, entry_cnt * sizeof (struct dir_entry), 1);
}
파일의 on-disk inode 생성시 is_dir값을 0으로 설정
bool filesys_create (const char *name, off_t initial_size) {
...
&& inode_create (inode_sector, initial_size, 0)
...
}
free-map의 on-disk inode 생성시 is_dir값을 0으로 설정
void free_map_create (void) {
/* Create inode. */
if (!inode_create (FREE_MAP_SECTOR, bitmap_file_size (free_map), 0))
PANIC ("free map creation failed");
...
}
thread 자료구조 초기화 시 추가한 필드를 초기화하는 코드도 삽입한다.
void thread_init (void) {
...
#ifdef EFILESYS
initial_thread->cur_dir = NULL;
#endif
}
filesystem 초기화 후, 스레드의 현재 작업 디렉토리를 root 디렉토리로 설정한다.
void filesys_init (bool format) {
filesys_disk = disk_get (0, 1);
if (filesys_disk == NULL)
PANIC ("hd0:1 (hdb) not present, file system initialization failed");
inode_init ();
#ifdef EFILESYS
fat_init ();
if (format)
do_format ();
fat_open ();
// 루트디렉토리 설정
thread_current()->cur_dir = dir_open_root(); // dir_open_root(): root 디렉터리 정보 반환
#else
/* Original FS */
free_map_init ();
if (format)
do_format ();
free_map_open ();
#endif
}
스레드 생성시, 자식 스레드의 작업 디렉토리를 부모 스레드의 작업 디렉토리의 위치로 저장한다.
tid_t thread_create (const char *name, int priority,
...
// 자식 스레드의 작업 디렉터리를 부모 스레드의 작업 디렉터리로 디렉터리 다시 오픈하여 설정
#ifdef EFILESYS
if(thread_current()->cur_dir != NULL) {
t->cur_dir = dir_reopen(thread_current()->cur_dir);
}
#endif
...
}
프로세스의 리소스를 해지 시, 스레드의 cur_dir을 해지한다.
void process_exit (void) {
...
#ifdef EFILESYS
dir_close(thread_current()->cur_dir); // 스레드의 현재 작업 디렉터리의 정보 메모리에서 해지
#endif
}
inode를 open할 때, 디스크를 읽는 부분 수정
struct inode *inode_open (disk_sector_t sector) {
...
disk_read (filesys_disk, cluster_to_sector(inode->sector), &inode->data);
return inode;
}
파일이 생성될 때 root 디렉터리에 생성되는 것을 name 경로에 생성되로록 변경
bool filesys_create (const char *name, off_t initial_size) {
bool success = false;
#ifdef EFILESYS
// name의 파일경로를 cp_name에 복사
char *cp_name = (char *)malloc(strlen(name) + 1);
strlcpy(cp_name, name, strlen(name) + 1);
// cp_name의 경로분석
char *file_name = (char *)malloc(strlen(name) + 1);
struct dir *dir = parse_path(cp_name, file_name);
cluster_t inode_cluster = fat_create_chain(0);
success = (dir != NULL
// 파일의 inode를 생성하고 디렉토리에 추가한다
&& inode_create(inode_cluster, initial_size, 0)
&& dir_add(dir, file_name, inode_cluster));
if (!success && inode_cluster != 0) {
fat_remove_chain(inode_cluster, 0);
}
dir_close(dir);
free(cp_name);
free(file_name);
return success;
#else
disk_sector_t inode_sector = 0;
struct dir *dir = dir_open_root ();
bool success = (dir != NULL
&& free_map_allocate (1, &inode_sector)
&& inode_create (inode_sector, initial_size, 0)
&& dir_add (dir, name, inode_sector));
if (!success && inode_sector != 0)
free_map_release (inode_sector, 1);
dir_close (dir);
return success;
#endif
}
다음은 파일을 open할 때 name 경로에 파일 생성하도록 변경
struct file *filesys_open (const char *name) {
#ifdef EFILESYS
// name의 파일경로를 cp_name에 복사
char* cp_name = (char *)malloc(strlen(name) + 1);
char* file_name = (char *)malloc(strlen(name) + 1);
struct dir* dir = NULL;
struct inode *inode = NULL;
while(true) {
strlcpy(cp_name, name, strlen(name) + 1);
// cp_name의경로분석
dir = parse_path(cp_name, file_name);
if (dir != NULL) {
dir_lookup(dir, file_name, &inode);
if(inode && inode->data.is_link) { // 파일이 존재하고, 링크 파일인 경우
dir_close(dir);
name = inode->data.link_name;
continue;
}
}
free(cp_name);
free(file_name);
dir_close(dir);
break;
}
return file_open(inode);
#else
struct dir *dir = dir_open_root ();
struct inode *inode = NULL;
if (dir != NULL)
dir_lookup (dir, name, &inode);
dir_close (dir);
return file_open (inode);
#endif
}
remove()함수도 마찬가지로 수정
bool filesys_remove (const char *name) {
#ifdef EFILESYS
// name의 파일경로를 cp_name에 복사
char* cp_name = (char *)malloc(strlen(name) + 1);
strlcpy(cp_name, name, strlen(name) + 1);
// cp_name의 경로분석
char* file_name = (char *)malloc(strlen(name) + 1);
struct dir* dir = parse_path(cp_name, file_name);
struct inode *inode = NULL;
bool success = false;
if (dir != NULL) {
dir_lookup(dir, file_name, &inode);
if(inode_is_dir(inode)) { // 디렉토리인 경우
struct dir* cur_dir = dir_open(inode);
char* tmp = (char *)malloc(NAME_MAX + 1);
dir_seek(cur_dir, 2 * sizeof(struct dir_entry));
if(!dir_readdir(cur_dir, tmp)) { // 디렉토리가 비었다
// 현재 디렉토리가 아니면 지우게 한다
if(inode_get_inumber(dir_get_inode(thread_current()->cur_dir)) != inode_get_inumber(dir_get_inode(cur_dir)))
success = dir_remove(dir, file_name);
}
else { // 디렉토리가 비지 않았다.
// 찾은 디렉토리에서 지운다
success = dir_remove(cur_dir, file_name);
}
dir_close(cur_dir);
free(tmp);
}
else { // 파일인 경우
inode_close(inode);
success = dir_remove(dir, file_name);
}
}
dir_close(dir);
free(cp_name);
free(file_name);
return success;
#else
struct dir *dir = dir_open_root ();
bool success = dir != NULL && dir_remove (dir, name);
dir_close (dir);
return success;
#endif
}
다음은 readdir(). 이 함수는 파일의 fd로부터 디렉토리 엔트리를 읽는다. 성공하면 NULL로 종료된 파일 이름을 이름에 저장하고, 이는 READDIR_MAX_LEN + 1byte의 공간이 있어야 한다(lib/user/syscall.h에 정의). 성공 시 true 리턴. 디렉토리에 엔트리가 없다면 false를 리턴한다.
'.' 과 '..'은 readdir로부터 반환될 수 없다. 만약 디렉토리가 열려 있을 때 디렉토리를 변경하면, 일부 엔트리는 아예 읽을 수 없거나 중복되에 읽힐 수 있다. 그렇지 않은 경우, 각 디렉토리 엔트리는 순서에 상관없이 한 번 읽혀야 한다.
// directory 내 파일 존재 여부 확인
bool sys_readdir(int fd, char *name) {
if (name == NULL) {
return false;
}
// fd리스트에서 fd에 대한 file정보 얻어옴
struct file *target = find_file_by_fd(fd);
if (target == NULL) {
return false;
}
// fd의 file->inode가 디렉터리인지 검사
if (!inode_is_dir(file_get_inode(target))) {
return false;
}
// p_file을 dir자료구조로 포인팅
struct dir *p_file = target;
if (p_file->pos == 0) {
dir_seek(p_file, 2 * sizeof(struct dir_entry)); // ".", ".." 제외
}
// 디렉터리의 엔트리에서 ".", ".." 이름을 제외한 파일이름을 name에 저장
bool result = dir_readdir(p_file, name);
return result;
}
여기서 p_file을 디렉토리 자료구조로 포인팅하기 위해 디렉토리 포인터를 수정하는 함수를 directory.c 파일에 생성한다.
// 디렉토리 포지션 변경
void dir_seek (struct dir *dir, off_t new_pos) {
ASSERT (dir != NULL);
ASSERT (new_pos >= 0);
dir->pos = new_pos;
}
sys_readdir 함수에서 dir과 dir_entry 구조체를 사용하는데 참조가 되지 않는 문제가 발생했다. 두 구조체의 위치를 보니, direcotry.c에 위치해 있다. 이 구조체를 헤더파일로 옮겼더니 문제 해결.
// ../include/filesys/directory.h
...
/* A directory. */
struct dir {
struct inode *inode; /* Backing store. */
off_t pos; /* Current position. */
};
/* A single directory entry. */
struct dir_entry {
disk_sector_t inode_sector; /* Sector number of header. */
char name[NAME_MAX + 1]; /* Null terminated file name. */
bool in_use; /* In use or free? */
};
...
isdir()은 fd가 디렉토리를 나타낼 때 true, 일반 파일일 때 false를 반환하는 함수다.
// file의 directory 여부 판단
bool is_dir(int fd) {
struct file *target = find_file_by_fd(fd);
if (target == NULL) {
return false;
}
return inode_is_dir(file_get_inode(target));
}
inumber()는 디렉토리인지 파일인지를 나타내는 fd와 연관된 inode의 번호를 리턴한다. inode 번호는 지속적으로 파일이나 디렉토리를 식별한다. pintos에서 inode의 섹터 번호는 inode 번호로 사용된다.
// file의 inode가 기록된 sector 찾기
struct cluster_t *sys_inumber(int fd) {
struct file *target = find_file_by_fd(fd);
if (target == NULL) {
return false;
}
return inode_get_inumber(file_get_inode(target));
}
이제 파일 시스템 포맷 함수를 수정해야 한다. 파일 시스템 포맷 시 root 디렉토리 엔트리에 '.', '..'파일을 추가한다.
/* Formats the file system. */
static void do_format (void) {
printf ("Formatting file system...");
#ifdef EFILESYS
/* Create FAT and save it to the disk. */
fat_create ();
// '.' '..' 파일 추가
if (!dir_create(ROOT_DIR_SECTOR, 16)) {
PANIC("root directory creation failed");
}
struct dir* root_dir = dir_open_root();
dir_add(root_dir, ".", ROOT_DIR_SECTOR);
dir_add(root_dir, "..", ROOT_DIR_SECTOR);
dir_close(root_dir);
fat_close ();
#else
free_map_create ();
if (!dir_create (ROOT_DIR_SECTOR, 16))
PANIC ("root directory creation failed");
free_map_close ();
#endif
printf ("done.\n");
}
여기까지 했으면 subdirectories 파트 끝! 다음은 soft link다.
핀토스에서 소프트 링크 메카니즘을 구현하라고 한다. soft link(aka. Symbolic link)는 다른 파일이나 디렉토리를 참조하는 수도 파일 개체다. 이 파일에는 절대/상대 경로 측면에서 포인트로 지정된 파일의 경로 정보가 포함되어 있다.
/a에 link1이라 명명된 소프트 링크는 /file을 가리키고(절대 경로), link2는 ../file을 가리킨다(상대 경로). link1 과 link2를 읽는 것은 /file을 읽는 것과 동일하다.
symlink()는 링크 경로로 이름 지어진 soft link를 생성하고, 이 링크는 문자열 타겟을 포함한다. 성공적이라면 0을 리턴하고, 실패했다면 -1을 리턴한다.
// 바로가기 file 생성
int symlink (const char *target, const char *linkpath) {
// SOFT LINK
bool success = false;
char* cp_link = (char *)malloc(strlen(linkpath) + 1);
strlcpy(cp_link, linkpath, strlen(linkpath) + 1);
// cp_name의경로분석
char* file_link = (char *)malloc(strlen(cp_link) + 1);
struct dir* dir = parse_path(cp_link, file_link);
cluster_t inode_cluster = fat_create_chain(0);
// link file 전용 inode 생성 및 directory에 추가
success = (dir != NULL
&& link_inode_create(inode_cluster, target)
&& dir_add(dir, file_link, inode_cluster));
if (!success && inode_cluster != 0) {
fat_remove_chain(inode_cluster, 0);
}
dir_close(dir);
free(cp_link);
free(file_link);
return success - 1;
}
그리고 link_inode_create() 함수 구현
// link file 만드는 함수
bool link_inode_create (disk_sector_t sector, char* path_name) {
struct inode_disk *disk_inode = NULL;
bool success = false;
ASSERT (strlen(path_name) >= 0);
/* If this assertion fails, the inode structure is not exactly
* one sector in size, and you should fix that. */
ASSERT (sizeof *disk_inode == DISK_SECTOR_SIZE);
disk_inode = calloc (1, sizeof *disk_inode);
if (disk_inode != NULL) {
disk_inode->length = strlen(path_name) + 1;
disk_inode->magic = INODE_MAGIC;
// link file 여부 추가
disk_inode->is_dir = 0;
disk_inode->is_link = 1;
strlcpy(disk_inode->link_name, path_name, strlen(path_name) + 1);
cluster_t cluster = fat_create_chain(0);
if(cluster)
{
disk_inode->start = cluster;
disk_write (filesys_disk, cluster_to_sector(sector), disk_inode);
success = true;
}
free (disk_inode);
}
return success;
}
inode_disk 구조체에도 변수 추가
/* On-disk inode.
* Must be exactly DISK_SECTOR_SIZE bytes long. */
struct inode_disk {
disk_sector_t start; /* First data sector. */
off_t length; /* File size in bytes. */
unsigned magic; /* Magic number. */
uint32_t unused[125]; /* Not used. */
uint32_t is_dir; // 디렉토리 구분
uint32_t is_link; // symlink 구분
// 멤버 추가시마다 512바이트 맞추기
char link_name[492];
};
'개발자 도전기 > [OS] pintOS' 카테고리의 다른 글
pintOS | Project 4 회고 (0) | 2021.11.02 |
---|---|
pintOS | Project 4 | Indexed and Extensible Files (0) | 2021.10.29 |
pintOS | Project 4 | Introduction (0) | 2021.10.28 |
pintOS | Project 3 회고 (0) | 2021.10.28 |
pintOS | Project 3 | 버그잡자 (1) | 2021.10.22 |
댓글