void output_single_file(char *filename, const struct print_f *format) { static struct stat file_st; static char file_path[MAXDIR]; glob_t dir; int glob_mode = 0; if (lstat(filename, &file_st) == -1) { perror(filename); return; } if (S_ISLNK(file_st.st_mode)) if ((filename = read_link(filename)) == NULL) return; /*如果这不是一个目录,或者递归目录没开,则显示这条记录*/ /*递归的时候没有显示目录名字?*/ if (!S_ISDIR(file_st.st_mode) || format->dire_flag == DISABLE) print_single_record(&file_st,format,filename,0); /*if -R, 但要忽略 . 和 .. 两个目录*/ if (format->dire_flag && S_ISDIR(file_st.st_mode)) { if (is_dot_file(filename)) { /* 但是要显示*/ print_single_record(&file_st, format,filename,0); return; } /* 获取下级目录项*/ if (format->hide_flag) { sprintf(file_path, "%s/.*", filename); if (glob(file_path, 0, NULL, &dir) != 0) return; glob_mode = GLOB_APPEND; } sprintf(file_path, "%s/*", filename); if (glob(file_path, glob_mode, NULL, &dir) != 0) return; printf("\n%s:\n", filename); rec_dir(&dir, format); } return; }
int main(int argc, char *argv[]) { char *filename; struct print_f format = {0,0,0,0,0,0,0,0,0,0,0,0}; static glob_t dir; char *argv_temp[3], **my_argv; int glob_mode = 0, ret, err_opt = -1; argv_temp[0] = argv[0]; argv_temp[1] = "*"; argv_temp[2] = NULL; if ((ret = get_format(&format, argv, &err_opt)) == -1) { print_help("help", err_opt); return -1; } /* 没有指定任何文件名 */ if (argc - ret == 1) my_argv = argv_temp; else my_argv = argv; if (format.hide_flag) argv_temp[1] = "."; while ((filename = *++my_argv) != NULL) { if (filename[0] == '-') /* 忽略参数*/ continue; if (format.hide_flag) { if (glob(extend_dir(*my_argv, &format, 1), 0, NULL, &dir) != 0) continue; glob_mode = GLOB_APPEND; } if (glob(extend_dir(*my_argv, &format, 0),glob_mode, NULL, &dir) != 0) continue; rec_dir(&dir, &format); } return 0; }
int main(int argc, char *argv[]) { char *filename; struct print_f format = {0,0,0,0,0,0,0,0,0,0,0}; static glob_t dir; char *argv_temp[3], **my_argv; int glob_mode = 0; argv_temp[0] = argv[0]; argv_temp[1] = "*"; argv_temp[2] = NULL; /* 没有指定任何文件名 */ if (argc - get_format(&format, argv) == 1) my_argv = argv_temp; else my_argv = argv; if (format.hide_flag) argv_temp[1] = "."; while ((filename = *++my_argv) != NULL) { if (filename[0] == '-') /* 忽略参数*/ continue; if (format.hide_flag) { if (glob(extend_dir(*my_argv, &format, 1), 0, NULL, &dir) != 0) continue; glob_mode = GLOB_APPEND; } if (glob(extend_dir(*my_argv, &format, 0),glob_mode, NULL, &dir) != 0) continue; rec_dir(&dir, &format); } if (format.newl_flag == DISABLE) /* 末行需要打印回车*/ printf("\n"); return 0; }
U32 rec_file(DirEntry* rData, U32 rec_entry, U32* fat_entry, U32 Flag, U32 upClus) { /* * ------------- 변수설명----------------- * i : 반복 변수 * useClus : 빈 클러스터 * reset_buf : 빈 클러스터 초기화용 버퍼 * rec_buf : 파일 내용 백업용 버퍼 * dir_buf : 디렉토리를 복구할 경우의 서브 디렉토리의 Directory Entry 덤프를 위한 버퍼 * FstClustNum : 첫 번째 클러스터를 저장하기 위한 변수 * StartSec : 복구 시작 섹터 저장을 위한 변수 -> 최초에는 Root Directory Sector에서 복구가 진행되지만 * 그 이후 부터는 Sub Directory에서 진행되기 때문에 고정값 X * Flag : 0 -> Root Directory, 1 -> Sub Directory * upClus : 상위 디렉토리의 클러스터 번호 * ----------------------------------------- */ U32 i, useClus; U8 reset_buf[4096]; U8 rec_buf[4096]; U8 dir_buf[4096]; U32 FstClustNum; U32 StartSec; memset(reset_buf, 0x00, sizeof(reset_buf)); // 초기화용 메모리 제작(0x00 으로 전체 초기화 시킴) memset(rec_buf, 0x00, sizeof(rec_buf)); // 복제 메모리 초기화 FstClustNum = rData[rec_entry].FstClustLow | rData[rec_entry].FstClusHi << 16; // First Cluster Total 저장 HDD_read(gVol.Drive, gVol.RootDirSec + (FstClustNum - 2)*gVol.SecPerClus, 8, rec_buf); // 파일 내용 복사 for(i=0;;i++) { if(fat_entry[i] == 0x00000000) { useClus = i; // 빈 클러스터 발견 시 해당 클러스터 번호 useClus에 저장 break; } } // for(;;) // FAT 영역에서의 빈 클러스터 검색 // -------------------------------------------------------------------------------------- 삭제 파일 복구(적용 X) fat_entry[useClus] = 0x0FFFFFFF; // 빈 클러스터를 사용 클러스터로 변경 rData[rec_entry].Name[0] = 'R'; // 삭제 시그니쳐 0xE5 -> R 문자열로 변경 // -------------------------------------------------------------------------------------- 삭제 파일 복구(적용 X) // -------------------------------------------------------------------------------------- 복구 내용 적용 구간 HDD_write(gVol.Drive, gVol.RootDirSec + (useClus-2)*gVol.SecPerClus, 8, reset_buf); // 사용할 클러스터 초기화 if(Flag == 0) { StartSec = gVol.RootDirSec; Flag = 1; } else { StartSec = gVol.RootDirSec + (upClus - 2 ) * gVol.SecPerClus; } // Root Directory와 Sub Directory 에 따른 Directory Entry 의 시작 주소 변경을 위한 분기 rData[rec_entry].FstClustLow = useClus; // 삭제 이전 클러스터 -> 사용할 클러스터 HDD_write(gVol.Drive, gVol.RootDirSec + (useClus-2)*gVol.SecPerClus, 8, rec_buf); // 백업해둔 파일 내용 새로운 클러스터에 복사 HDD_write(gVol.Drive, StartSec, 8, rData); // 삭제 시그니쳐 -> R 시그니처 적용 HDD_write(gVol.Drive, gVol.FATStartSec, 8, fat_entry); // 빈 클러스터 -> 사용 클러스터 변경 내용 적용 // -------------------------------------------------------------------------------------- 복구 내용 적용 구간 /* * ---------------- 개선해야할 사항 ---------------- * 해당 파일의 크기가 1 Cluster 를 넘어갈 때의 복구 * ------------------------------------------------- */ if(rData[rec_entry].Attr == 0x10) { StartSec = gVol.RootDirSec + (FstClustNum - 2 ) * gVol.SecPerClus; // Sub Directory Entry 의 시작 위치 HDD_read(gVol.Drive, StartSec, 8, dir_buf); // Sub Directory Entry Dump rec_dir(dir_buf, Flag, useClus); // Directory 에 대한 복구를 위한 rec_dir 함수 호출 }// 해당 Directory Entry가 Directory 일 경우의 복구 printf("%s 이/가 복구 완료 되었습니다. \n", rData[rec_entry].Name); // 복구된 파일/디렉토리 명과 완료 메세지 출력 return 0; }