int get_entry(int count, FILE *infile, struct program_block *program) { switch (detect_type(infile)) { case t64: { unsigned int offset; if (!get_entry_info(count, infile, &program->info, &offset)) return 0; if (fseek(infile, offset, SEEK_SET) != 0) return 0; } if (fread(&program->data, 1, program->info.end - program->info.start, infile) < 1) return 0; return 1; case p00: case prg: return get_first_entry(infile, program); default: return 0; } }
void __mfs_readdir(const ps16_t route, struct file *file, struct dir_context *ctx) { u8_t cluster[CLUSTER_SIZE] = {0, }; const u32_t entry_per_data_cluster = CLUSTER_SIZE / sizeof(struct mfs_dirent); s16_t composited_file_name[128] = {0, }; BOOL has_long_file_name_entry = FALSE; u128 current_cluster_number = 0; u32_t current_entry_number = 0; u128 read_position = 0; struct mfs_dirent* current_dirent = NULL; static s16_t path[1024]={0}; struct dentry *de = file->f_dentry; struct mfs_volume* volume = de->d_sb->s_fs_info; u128 end_cluster = get_end_cluster(volume); strncpy(path, route, 1024); current_cluster_number = get_cluster_number(volume, path); if(current_cluster_number == 0) { return ; } printk("__mfs_readdir\n"); // 볼륨이 무효하다. if(volume == NULL) return ; read_position = read_cluster(volume, current_cluster_number); #ifdef __KERNEL__ seek_volume(volume, read_position); #else seek_volume(volume, read_position, SEEK_SET); #endif read_volume(volume, cluster, sizeof(u8_t), CLUSTER_SIZE); printk("current cluster number before : %d\n", current_cluster_number); while(current_cluster_number != end_cluster) { // 클러스터의 첫 엔트리를 얻는다. current_dirent = get_first_entry(cluster, ¤t_entry_number, has_long_file_name_entry); printk("current dentry : %x\n", current_dirent); // 클러스터의 모든 엔트리를 검사한다. while(current_entry_number != entry_per_data_cluster) { printk("current cluster number after : %d\n", current_cluster_number); // if(current_dirent->size != 0) { // printk("current_dentry size is NOT 0\n"); // 얻은 엔트리가 LongFileName인지 여부 검사 if(is_long_file_name(current_dirent->attribute) == TRUE) { // LongFileName일 경우 LongFileName을 조합한다. composite_long_file_name(volume, current_cluster_number, current_entry_number, composited_file_name); } else { // 일반 FileName일 경우 복사 strcpy(composited_file_name, current_dirent->name); } if(is_normal_dir(current_dirent->attribute) == TRUE) { static char buf[1024]=""; int len; buf[0]='\0'; strcat(buf,path); len=strlen(path); if(len > 0){ if(path[len-1] != '/') strcat(buf,"/"); } strcat(buf, composited_file_name); if(!dir_emit(ctx, composited_file_name, strlen(composited_file_name), 2, DT_DIR)) { printk("WARNING %s %d", __FILE__, __LINE__); return ; } ctx->pos++; strcat(buf, "*<DIR>\n"); printk(buf); } else if(is_normal_file(current_dirent->attribute) == TRUE) { static char buf[1024]=""; buf[0]='\0'; if(!dir_emit(ctx, composited_file_name, strlen(composited_file_name), 2, DT_REG)) { printk("WARNING %s %d", __FILE__, __LINE__); return ; } ctx->pos++; strcat(buf, composited_file_name); strcat(buf, "*<FILE>\n"); printk(buf); } // } // 다음 엔트리를 얻는다. current_dirent = get_next_entry(cluster, ¤t_entry_number, &has_long_file_name_entry); } current_cluster_number = read_fat_index(volume, current_cluster_number); // 지정된 번호의 클러스터를 읽는다. read_position = read_cluster(volume, current_cluster_number); #ifdef __KERNEL__ seek_volume(volume, read_position); #else seek_volume(volume, read_position, SEEK_SET); #endif read_volume(volume, cluster, sizeof(u8_t), CLUSTER_SIZE); } return ; }
void __mfs_readdir(struct mfs_volume* volume, const ps16_t route, struct printdir *printdir) { u8_t cluster[CLUSTER_SIZE] = {0, }; const u32_t entry_per_data_cluster = CLUSTER_SIZE / sizeof(struct mfs_dirent); s16_t composited_file_name[128] = {0, }; BOOL has_long_file_name_next_entry = FALSE; u128 current_cluster_number = 0; u32_t current_entry_number = 0; u128 read_position = 0; struct mfs_dirent* current_dirent = NULL; static s16_t path[1024]={0}; struct file* filp = printdir->filp; void* dirent = printdir->dirent; filldir_t filldir = printdir->filldir; u128 end_cluster = get_end_cluster(volume); strncpy(path, route, 1024); current_cluster_number = get_cluster_number(volume, path); if(current_cluster_number == 0) { return ; } // 볼륨이 무효하다. if(volume == NULL) return ; read_position = read_cluster(volume, current_cluster_number); seek_volume(volume, read_position); read_volume(volume, cluster, sizeof(u8_t), CLUSTER_SIZE); while(current_cluster_number != end_cluster) { // 클러스터의 첫 엔트리를 얻는다. current_dirent = get_first_entry(cluster, ¤t_entry_number, has_long_file_name_next_entry); // 클러스터의 모든 엔트리를 검사한다. while(current_entry_number != entry_per_data_cluster) { // if(current_dirent->size != 0) // { // 얻은 엔트리가 LongFileName인지 여부 검사 if(is_long_file_name(current_dirent->attribute) == TRUE) { // LongFileName일 경우 LongFileName을 조합한다. composite_long_file_name(volume, current_cluster_number, current_entry_number, composited_file_name); } else { // 일반 FileName일 경우 복사 strcpy(composited_file_name, current_dirent->name); } if(is_normal_dir(current_dirent->attribute) == TRUE) { static char buf[1024] = ""; int len; buf[0] = '\0'; strcat(buf, path); len = strlen(path); if(len > 0){ if(path[len-1] != '/') strcat(buf, "/"); } strcat(buf, composited_file_name); if(filldir(dirent, composited_file_name, strlen(composited_file_name), filp->f_pos++, 2, DT_DIR)){ printk("WARNING %s %d", __FILE__,__LINE__); return ; } strcat(buf, "*<DIR>\n"); printk(buf); } else if(is_normal_file(current_dirent->attribute) == TRUE) { static char buf[1024]=""; buf[0]='\0'; printk("garig %p %p %p %s\n", filp, dirent, filldir, composited_file_name); if(filldir(dirent, composited_file_name, strlen(composited_file_name), filp->f_pos++, 2, DT_REG)){ printk("WARNING %s %d", __FILE__, __LINE__); return ; } strcat(buf, composited_file_name); strcat(buf, "*<FILE>\n"); printk(buf); } // } // 다음 엔트리를 얻는다. current_dirent = get_next_entry(cluster, ¤t_entry_number, &has_long_file_name_next_entry); } current_cluster_number = read_fat_index(volume, current_cluster_number); // 지정된 번호의 클러스터를 읽는다. read_position = read_cluster(volume, current_cluster_number); seek_volume(volume, read_position); read_volume(volume, cluster, sizeof(u8_t), CLUSTER_SIZE); } return ; }
int __mfs_lookup(struct mfs_volume* volume, const ps16_t route, const ps16_t file_name) { u8_t cluster[CLUSTER_SIZE] = {0, }; const u32_t entry_per_data_cluster = CLUSTER_SIZE / sizeof(struct mfs_dirent); s16_t composited_file_name[128] = {0, }; BOOL has_long_file_name_next_entry = FALSE; u128 current_cluster_number = 0; u32_t current_entry_number = 0; u128 read_position = 0; struct mfs_dirent* current_dentry = NULL; static s16_t path[1024]={0}; u128 end_cluster = get_end_cluster(volume); strncpy(path, route, 1024); current_cluster_number = get_cluster_number(volume, route); // if(current_cluster_number == 0) // { // return 0; // } // 볼륨이 무효하다. if(volume == NULL) return 0; read_position = read_cluster(volume, current_cluster_number); #ifdef __KERNEL__ seek_volume(volume, read_position); #else seek_volume(volume, read_position, SEEK_SET); #endif read_volume(volume, cluster, sizeof(u8_t), CLUSTER_SIZE); while(current_cluster_number != end_cluster) { // 클러스터의 첫 엔트리를 얻는다. current_dentry = get_first_entry(cluster, ¤t_entry_number, has_long_file_name_next_entry); // 클러스터의 모든 엔트리를 검사한다. while(current_entry_number != entry_per_data_cluster) { // 얻은 엔트리가 LongFileName인지 여부 검사 if(is_long_file_name(current_dentry->attribute) == TRUE) { // LongFileName일 경우 LongFileName을 조합한다. composite_long_file_name(volume, current_cluster_number, current_entry_number, composited_file_name); } else { // 일반 FileName일 경우 복사 strcpy(composited_file_name, current_dentry->name); } if(strcmp(composited_file_name, file_name) == 0){ if(is_normal_dir(current_dentry->attribute) == TRUE){ return DIR_DENTRY; } else if(is_normal_file(current_dentry->attribute) == TRUE){ return FILE_DENTRY; } } // 다음 엔트리를 얻는다. current_dentry = get_next_entry(cluster, ¤t_entry_number, &has_long_file_name_next_entry); } current_cluster_number = read_fat_index(volume, current_cluster_number); // 지정된 번호의 클러스터를 읽는다. read_position = read_cluster(volume, current_cluster_number); #ifdef __KERNEL__ seek_volume(volume, read_position); #else seek_volume(volume, read_position, SEEK_SET); #endif read_volume(volume, cluster, sizeof(u8_t), CLUSTER_SIZE); } return 0; }
static UINT_PTR APIENTRY frompc_hook_proc(HWND hwnd, UINT uimsg, WPARAM wparam, LPARAM lparam){ HWND preview; char filename[256]; LVCOLUMNA column; preview = GetDlgItem(hwnd, IDC_PREVIEW); switch (uimsg) { case WM_INITDIALOG: column.mask = LVCF_TEXT | LVCF_WIDTH; column.pszText = "No."; column.cx = 40; ListView_InsertColumn(preview, 0, &column); column.pszText = "Name"; column.cx = 160; ListView_InsertColumn(preview, 1, &column); column.pszText = "Start address"; column.cx = 80; ListView_InsertColumn(preview, 2, &column); column.pszText = "End address"; ListView_InsertColumn(preview, 3, &column); SendMessage(GetDlgItem(hwnd, IDC_C64_NAME), EM_LIMITTEXT, 16, 0); break; case WM_NOTIFY: { LPOFNOTIFY notify = (LPOFNOTIFY) lparam; if (notify->hdr.code == CDN_SELCHANGE) { ListView_DeleteAllItems(preview); SetDlgItemTextA(hwnd, IDC_C64_NAME, ""); EnableWindow(GetDlgItem(hwnd, IDC_C64_NAME), FALSE); if (CommDlg_OpenSave_GetFilePath (notify->hdr.hwndFrom, filename, 256) >= 0) write_entries_to_window(hwnd, filename); } else if (notify->hdr.code == CDN_FILEOK) { int entry_num; struct simple_block_list_element **block = (struct simple_block_list_element **)notify->lpOFN->lCustData; FILE *fd = NULL; if (CommDlg_OpenSave_GetFilePath(notify->hdr.hwndFrom, filename, 256) < 0) { MessageBoxA(hwnd, "Cannot get selected file name", "WAV-PRG error", MB_ICONERROR); } else fd = fopen(filename, "rb"); if (fd == NULL) { MessageBoxA(hwnd, "Cannot open selected file", "WAV-PRG error", MB_ICONERROR); SetWindowLong(hwnd, DWL_MSGRESULT, -1); } else { switch (detect_type(fd)) { case not_a_valid_file: MessageBoxA(hwnd, "Selected file is not a supported file", "WAV-PRG error", MB_ICONERROR); break; case t64: { int index; struct simple_block_list_element **current_block = block; for (index = ListView_GetNextItem(preview, -1, LVNI_SELECTED); index != -1; index = ListView_GetNextItem(preview, index, LVNI_SELECTED)) { LVITEMA sel_item; char sel_num[6]; sel_item.mask = LVIF_TEXT; sel_item.iItem = index; sel_item.iSubItem = 0; sel_item.pszText = sel_num; sel_item.cchTextMax = sizeof(sel_num); if (!ListView_GetItem(preview, &sel_item)) continue; entry_num = atoi(sel_num); add_simple_block_list_element(current_block); if (!get_entry(entry_num, fd, &(*current_block)->block)){ remove_simple_block_list_element(current_block); continue; } current_block = &(*current_block)->next; } } if (*block == NULL) add_all_entries_from_file(block, fd); if (*block == NULL) MessageBoxA(hwnd, "You chose a T64 file with no entries", "WAV-PRG error", MB_ICONERROR); break; case p00: case prg: add_simple_block_list_element(block); if (!get_first_entry(fd, &(*block)->block)) { MessageBoxA(hwnd, "Error in reading file", "WAV-PRG error", MB_ICONERROR); remove_simple_block_list_element(block);; } else { int i; char pad_with_spaces = 0; GetDlgItemTextA(hwnd, IDC_C64_NAME, (*block)->block.info.name, 17); for (i = 0; i < 16; i++) { if ((*block)->block.info.name[i] == 0) pad_with_spaces = 1; if (pad_with_spaces) (*block)->block.info.name[i] = 32; } } break; default: break; } } if (fd != NULL) fclose(fd); if (*block == NULL){ SetWindowLong(hwnd, DWL_MSGRESULT, -1); return 1; } } break; } default: break; } return 0; }
/* Walk a path string, either changing directories or finding the right path If mode is WALK_CHDIR, the result of this function is entering into the new directory on success, or the old directory being returned on failure. If mode is WALK_OPEN, the result of this function is the directory remains unchanged and a pointer to the directory entry for the requested file or directory is returned. If it is a file, the directory entry for the file itself is returned. If it is a directory, the directory entry of the first file or directory inside that directory is returned. The type specifier allows a person to specify that only a directory or file should be returned. This works for WALK_OPEN only. */ static int recurse_path(const char * const path, int mode, directory_entry_t **dirent, int type) { int ret = DFS_ESUCCESS; char token[MAX_FILENAME_LEN+1]; char *cur_path = (char *)path; uint32_t dir_stack[MAX_DIRECTORY_DEPTH]; uint32_t dir_loc = directory_top; int last_type = TYPE_ANY; int ignore = 1; // Do not, by default, read again during the first while /* Save directory stack */ memcpy(dir_stack, directories, sizeof(uint32_t) * MAX_DIRECTORY_DEPTH); /* Grab first token, make sure it isn't root */ cur_path = get_next_token(cur_path, token); if(strcmp(token, "/") == 0) { /* It is an absolute path */ clear_directory(); /* Ensure that we remember this as a directory */ last_type = TYPE_DIR; /* We need to read through the first while loop */ ignore = 0; } /* Loop through the rest */ while(cur_path || ignore) { /* Grab out the next token */ if(!ignore) { cur_path = get_next_token(cur_path, token); } ignore = 0; if( (token[0] == '/' || token[0] == '.') ) { if(token[1] == '.') pop_directory();/* Up one directory */ last_type = TYPE_DIR; } else { /* Find directory entry, push */ directory_entry_t *tmp_node = find_dirent(token, peek_directory()); if(tmp_node) { /* Grab node, make sure it is a directory, push subdirectory, try again! */ directory_entry_t node; grab_sector(tmp_node, &node); uint32_t flags = get_flags(&node); if(FILETYPE(flags) == FLAGS_DIR) { /* Push subdirectory onto stack and loop */ push_directory(get_first_entry(&node)); last_type = TYPE_DIR; } else { if(mode == WALK_CHDIR) { /* Not found, this is a file */ ret = DFS_ENOFILE; break; } else { last_type = TYPE_FILE; /* Only count if this is the last thing we are doing */ if(!cur_path) { /* Push file entry onto stack in preparation of a return */ push_directory(tmp_node); } else { /* Not found, this is a file */ ret = DFS_ENOFILE; break; } } } } else { /* Not found! */ ret = DFS_ENOFILE; break; } } } if(type != TYPE_ANY && type != last_type) { /* Found an entry, but it was the wrong type! */ ret = DFS_ENOFILE; } if(mode == WALK_OPEN) { /* Must return the node found if we found one */ if(ret == DFS_ESUCCESS && dirent) { *dirent = peek_directory(); } } if(mode == WALK_OPEN || ret != DFS_ESUCCESS) { /* Restore stack */ directory_top = dir_loc; memcpy(directories, dir_stack, sizeof(uint32_t) * MAX_DIRECTORY_DEPTH); } return ret; }
/* 함수명 : search_fileDirectoryEntryInDirCluster 하는일 : 디렉토리 클러스터 안에 파일 디렉토리 엔트리를 찾는다. 디렉토리가 가지고 있는 모든 클러스터를 순환하여 파일 이름과 같은 엔트리를 찾는다. 인자 : fVolume : 루프백이미지/파일 볼륨의 포인터 nDirClusterNumber : 디렉토리 클러스터 번호 pFileName : 파일이름의 문자열 포인터 pSearchedDirEntry : 검색된 디렉토리 엔트리의 포인터 리턴 값 : BOOL */ BOOL get_dentry(struct mfs_volume* volume, u128 dir_cluster_number, ps16_t file_name, struct mfs_dirent* searched_dir_entry) { u8_t cluster[CLUSTER_SIZE] = {0, }; const u32_t entry_per_data_cluster = CLUSTER_SIZE / sizeof(struct mfs_dirent); s16_t composited_file_name[128] = {0, }; BOOL has_long_file_name_next_entry = FALSE; u128 read_position = 0; u128 current_cluster_number = dir_cluster_number; u32_t current_entry_number = 0; struct mfs_dirent* current_dir_entry = NULL; u128 end_cluster = get_end_cluster(volume); printf("get_dentry: %s\n", file_name); // 디렉토리의 모든 클러스터를 검사한다. while(current_cluster_number != end_cluster) { printf("current_cluster_number: %d\n", current_cluster_number); read_position = read_cluster(volume, current_cluster_number); #ifdef __KERNEL__ seek_volume(volume, read_position); #else seek_volume(volume, read_position, SEEK_SET); #endif read_volume(volume, cluster, sizeof(u8_t), CLUSTER_SIZE); current_dir_entry = get_first_entry(cluster, ¤t_entry_number, has_long_file_name_next_entry); while(current_entry_number != entry_per_data_cluster) { printf("current entry number after : %d\n", current_entry_number); if(is_normal_file(current_dir_entry->attribute) == TRUE) { // 얻은 엔트리가 LongFileName인지 여부 검사 if(is_long_file_name(current_dir_entry->attribute) == TRUE) { // LongFileName일 경우 LongFileName을 조합한다. composite_long_file_name(volume, current_cluster_number, current_entry_number, composited_file_name); } else { // 일반 FileName일 경우 복사 strcpy(composited_file_name, current_dir_entry->name); } // Name 비교 if(!strcmp(file_name, composited_file_name)) { memcpy(searched_dir_entry, current_dir_entry, sizeof(struct mfs_dirent)); return TRUE; } } // 다음 엔트리를 얻는다. current_dir_entry = get_next_entry(cluster, ¤t_entry_number, &has_long_file_name_next_entry); } current_cluster_number = read_fat_index(volume, current_cluster_number); printf("read fat index : %d\n", current_cluster_number); } printf("file not exist\n"); return FALSE; }
/* 함수명 : writeDirEntryInDirCluster 하는일 : 디렉토리 클러스터안에 디렉토리 엔트리를 추가한다. 디렉토리의 모든 클러스터를 검사하여, 빈 엔트리를 찾고 그 위치에 디렉토리 엔트리를 추가한다. 인자 : fVolume : 루프백이미지/파일 볼륨의 포인터 nDirClusterNumber : 디렉토리 클러스터 번호 pDirectoryEntry : 디렉토리 엔트리의 포인터 pFileName : 파일 이름의 문자열 포인터 리턴 값 : BOOL */ BOOL alloc_new_dirent(struct mfs_volume* volume, u128 dir_cluster_number, struct mfs_dirent* dirent, ps16_t file_name) { u8_t cluster[CLUSTER_SIZE] = {0, }; const u32_t entry_per_data_cluster = CLUSTER_SIZE / sizeof(struct mfs_dirent); BOOL has_long_file_name_next_entry = FALSE; u128 read_position = 0; u128 wirte_position = 0; u128 current_cluster_number = dir_cluster_number; u128 before_cluster_number = 0; u32_t current_entry_number = 0; struct mfs_dirent* current_dirent = NULL; u128 end_cluster = get_end_cluster(volume); // 디렉토리의 모든 클러스터를 검사한다. while(current_cluster_number != end_cluster) { read_position = read_cluster(volume, current_cluster_number); #ifdef __KERNEL__ seek_volume(volume, read_position); #else seek_volume(volume, read_position, SEEK_SET); #endif read_volume(volume, cluster, sizeof(u8_t), CLUSTER_SIZE); current_dirent = get_first_entry(cluster, ¤t_entry_number, has_long_file_name_next_entry); while(current_entry_number != entry_per_data_cluster) { // if (current_dirent->size == 0) if( is_deleted_file(current_dirent->attribute) || is_deleted_dir(current_dirent->attribute) ) { wirte_position = read_position + (current_entry_number * sizeof(struct mfs_dirent)); #ifdef __KERNEL__ seek_volume(volume, wirte_position); #else seek_volume(volume, wirte_position, SEEK_SET); #endif write_volume(volume, dirent, sizeof(struct mfs_dirent), 1); printf("alloc_new_dirent %d %d\n", current_cluster_number, wirte_position); return TRUE; } // 다음 엔트리를 얻는다. current_dirent = get_next_entry(cluster, ¤t_entry_number, &has_long_file_name_next_entry); } before_cluster_number = current_cluster_number; current_cluster_number = read_fat_index(volume, current_cluster_number); } // 디렉토리 클러스터에 빈 공간이 없다, 클러스터 추가 current_cluster_number = find_empty_fat_index(volume); write_in_fat_index(volume, before_cluster_number, current_cluster_number); write_in_fat_index(volume, current_cluster_number, end_cluster); wirte_position = read_cluster(volume, current_cluster_number); #ifdef __KERNEL__ seek_volume(volume, wirte_position); #else seek_volume(volume, wirte_position, SEEK_SET); #endif write_volume(volume, dirent, sizeof(struct mfs_dirent), 1); printf("alloc_new_dirent %d %d\n", current_cluster_number, wirte_position); return TRUE; }
u32_t get_cluster_number(struct mfs_volume* volume, ps16_t path) { u8_t current_cluster[CLUSTER_SIZE] = {0, }; ps16_t seperated_path = strtok(path, "/"); const u32_t entry_per_data_cluster = CLUSTER_SIZE / sizeof(struct mfs_dirent); struct mfs_dirent* current_dir_entry = NULL; s16_t composited_file_name[128] = {0, }; u128 current_cluster_number = 2; // Root Directory의 클러스터 값 u32_t current_entry_number = 0; BOOL is_dir_changed = FALSE; BOOL has_long_file_name_next_entry = FALSE; u128 end_cluster = get_end_cluster(volume); u128 read_position = read_cluster(volume, current_cluster_number); #ifdef __KERNEL__ seek_volume(volume, read_position); #else seek_volume(volume, read_position, SEEK_SET); #endif read_volume(volume, current_cluster, sizeof(u8_t), CLUSTER_SIZE); while(seperated_path != NULL) { is_dir_changed = FALSE; // 클러스터의 첫 엔트리를 얻는다. current_dir_entry = get_first_entry(current_cluster, ¤t_entry_number, has_long_file_name_next_entry); // 클러스터의 모든 엔트리를 검사한다. while(current_entry_number != entry_per_data_cluster) { // 얻은 엔트리가 폴더일 경우 if(is_normal_dir(current_dir_entry->attribute) == TRUE) { // 얻은 엔트리가 LongFileName인지 여부 검사 if(is_long_file_name(current_dir_entry->attribute) == TRUE) { // LongFileName일 경우 LongFileName을 조합한다. composite_long_file_name(volume, current_cluster_number, current_entry_number, composited_file_name); } else { // 일반 FileName일 경우 복사 strcpy(composited_file_name, current_dir_entry->name); } // Name 비교 if(!strcmp(seperated_path, composited_file_name)) { // 일치한다면 다음 route 경로 명을 얻는다. seperated_path = strtok(NULL, "/"); current_cluster_number = current_dir_entry->head_cluster_number; is_dir_changed = TRUE; break; } } // 다음 엔트리를 얻는다. current_dir_entry = get_next_entry(current_cluster, ¤t_entry_number, &has_long_file_name_next_entry); } // 현재 탐색 디렉토리가 변경되지 않았다면 현재 디렉토리의 다음 클러스터를 얻는다. if (is_dir_changed == FALSE) { current_cluster_number = read_fat_index(volume, current_cluster_number); // route 경로가 잘못되었다. if(current_cluster_number == end_cluster) { printf("wrong route\n"); return 0; } } // 지정된 번호의 클러스터를 읽는다. read_position = read_cluster(volume, current_cluster_number); #ifdef __KERNEL__ seek_volume(volume, read_position); #else seek_volume(volume, read_position, SEEK_SET); #endif read_volume(volume, current_cluster, sizeof(u8_t), CLUSTER_SIZE); } return current_cluster_number; }