struct path {
char **dirnames; // path 상의 디렉터리들의 목록
int dircount; // level of directory
char *filename;
char *pathStart_forFreeing; //
};
인자로 들어온 파일 이름(path)을 struct path의 필드에 저장한다. 이 때, “/” 기준으로 파싱하여 각각의 디렉터리 이름을 묶어 배열로 만들어 저장한다.
struct path* parse_filepath (const char* name_original){
const int MAX_PATH_CNT = 30;
struct path* path = malloc(sizeof(struct path));
char **buf = calloc(sizeof(char *), MAX_PATH_CNT);
int i = 0;
int pathlen = strlen(name_original) + 1;
char* name = malloc(pathlen);
strlcpy(name, name_original, pathlen);
path->pathStart_forFreeing = name; // free this later
/* root부터 buf에 담기 */
if (name[0] == '/'){ // path from root dir
buf[0] = "root";
i++;
}
/* "/" 기준으로 path 파싱하기. 파싱 후 buf에 담는다. */
char *token, *save_ptr;
token = strtok_r(name, "/", &save_ptr);
while (token != NULL)
{
// File name too long - 'test: create-long.c'
if(strlen(token) > NAME_MAX){
path->dircount = -1; // invalid path
return path;
}
buf[i] = token;
token = strtok_r(NULL, "/", &save_ptr);
i++;
}
/* path 구조체 초기화하기 */
path->dirnames = buf; // dirnames에 파싱 완료한 디렉토리 이름들을 담는다.
path->dircount = i-1;
path->filename = buf[i-1]; // last name in the path
return path;
}
파일이 아닌 디렉토리 역시 닫을 수 있도록 수정한다.
void close(int fd) {
struct file *fileobj = find_file_by_fd(fd);
if (fileobj == NULL) {
return;
}
if (fileobj <= 2) // stdin 하고 stdout 은 지우면 안된다.
return;
remove_file_from_fdt(fd);
if(fd <= 1 || fileobj <= 2)
return;
if (inode_isdir(fileobj->inode)){ // 수정!
remove_file_from_fdt(fd);
dir_close((struct dir*)fileobj);
}
else if (fileobj->dupCount == 0)
file_close(fileobj);
else
fileobj->dupCount--;
}
일반 파일뿐만 아니라 비어있는 디렉터리도 지울 수 있게 한다. 이 때 디렉터리는 그 안에 ‘.’이나 ‘..’을 제외한 다른 디렉터리나 파일이 없을 때만 지울 수 있어야 한다.
bool remove(const char *filename)
{
bool return_code;
check_address(filename);
lock_acquire(&filesys_lock);
return_code = filesys_remove(filename);
lock_release(&filesys_lock);
return return_code;
}