實(shí)驗(yàn)四 文件資料系統(tǒng) 實(shí)驗(yàn)報告材料
《實(shí)驗(yàn)四 文件資料系統(tǒng) 實(shí)驗(yàn)報告材料》由會員分享,可在線閱讀,更多相關(guān)《實(shí)驗(yàn)四 文件資料系統(tǒng) 實(shí)驗(yàn)報告材料(40頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、word 文件系統(tǒng) 實(shí)驗(yàn)報告 一、 實(shí)驗(yàn)?zāi)康? 了解操作系統(tǒng)中文件系統(tǒng)的原理以與實(shí)現(xiàn)方法。 二、 實(shí)驗(yàn)方法 通過FAT12文件系統(tǒng)的解讀,了解文件系統(tǒng)的原理和實(shí)現(xiàn)。 三、 實(shí)驗(yàn)任務(wù) 通過對FAT12文件系統(tǒng)的了解,編寫程序,讀取并列出一個虛擬軟盤中文件信息〔文件名、屬性、修改時間等〕,以與讀取其中的文件內(nèi)容 四、 實(shí)驗(yàn)要點(diǎn) FAT12文件系統(tǒng)的了解,Linux系統(tǒng)下文件讀寫相關(guān)系統(tǒng)調(diào)用。 五、 實(shí)驗(yàn)過程 1. FAT12 文件系統(tǒng)分析 簇是操作系統(tǒng)分配文件空間的根本單位,簇由假設(shè)干個扇區(qū)組成。在FAT12文件系統(tǒng)中,簇號的有效位是12位,所以這種文件系統(tǒng)就被稱為FAT1
2、2。FAT12文件系統(tǒng)中大致可以分成五個區(qū),這五個區(qū)為: 起始扇區(qū) 占用扇區(qū) 起始地址 完畢地址 分區(qū) 0 1 0x00000000 0x000001FF 引導(dǎo)區(qū) 1 9 0x00000200 0x000013FF FAT區(qū) 10 9 0x00001400 0x000025FF FAT備份區(qū) 19 12 0x00002600 0x00003DFF 根目錄區(qū) 31 - 0x00003E00 - 文件數(shù)據(jù)區(qū) 其中,引導(dǎo)區(qū)中儲存著一些根本的信息。例如,0x0000000B和0x0000000C兩個字節(jié)保存著每個扇區(qū)的大小,0x000000
3、0D保存著每個簇占用多少個扇區(qū)。 FAT區(qū)中儲存著簇號。在0x00000200開始的三個字節(jié),分別儲存設(shè)備類型標(biāo)記(0xF0為軟盤);第二個第三個字節(jié)均為0xFF,是FAT標(biāo)識符。在FAT12文件系統(tǒng)中,每個簇占用12位,即1.5個字節(jié)。簇號與地址的對應(yīng)關(guān)系如下表: 地址偏移 000 001 002 003 004 005 簇序號 000 001 002 003 一個簇號跨越兩個字節(jié),每次讀取簇號時讀取兩個字節(jié),然后對讀出的兩個字節(jié)進(jìn)展位運(yùn)算處理,得到下一簇的簇序號。 注意,這里同樣需要對上下位進(jìn)展處理,即使用位計算的方式提取相應(yīng)的簇號信息。 根據(jù)上述的原理,可
4、以得出一個函數(shù),以一個簇號為參數(shù),返回值為文件下一個簇號。代碼如下: int getNextClutserId(FILE *fp, short clusterId) { unsigned short tmp, low = 0, high = 0;; int address = (clusterId * 3 / 2) + 0x0000200; fseek(fp, address, SEEK_SET); fread((void *)(&tmp), 1, sizeof(unsigned short), fp); low = ((tmp & 0xFFF0) >> 4); high =
5、tmp & 0x0FFF; return (clusterId % 2 == 0 ? high : low); } 其中,fp 是用于讀取文件系統(tǒng)的文件流,clusterID是當(dāng)前簇號,返回值是下一個簇號。 函數(shù)體的第二句代碼,計算出當(dāng)前簇號對應(yīng)的地址,用于文件指針的定位。第三句代碼是根據(jù)第二句計算得到的地址對文件指針進(jìn)展定位,定位到當(dāng)前簇號所對應(yīng)的信息處。第四句代碼是從文件指針的位置為起始位置讀入兩個字節(jié)的內(nèi)容〔fread會自動對上下字節(jié)位進(jìn)展處理〕。并把這兩個字節(jié)的信息儲存到tmp變量之中。例如,讀取002簇號的下一個簇號,根據(jù)公式,計算得到的address是0x00000203,
6、讀取到0x00000203和0x00000204兩個字節(jié)的內(nèi)容。我們需要的是0x00000203整個字節(jié)的內(nèi)容和0x00000204的高四位,所以需要跟0xFFF0進(jìn)展位與運(yùn)算,并向右移四位,得到下一個簇號。 同樣地,讀取003簇號的下一個簇號,根據(jù)公式,計算得到的address是0x00000204,讀取到0x00000204和0x00000205兩個字節(jié)的內(nèi)容,我們需要的是0x00000205整個字節(jié)的內(nèi)容和0x00000204第四位的內(nèi)容,所以需要跟0x0FFF進(jìn)展位與運(yùn)算,得到下一個簇號。所以代碼中需要對簇號的奇偶性進(jìn)展判斷,跟根據(jù)奇偶性的不同返回不同的值。 在根目錄中,保存著
7、根目錄下面的文件或文件夾的信息。每個文件或者文件夾的信息使用32個字節(jié)保存。這些內(nèi)容的含義如下表: 地址 0 1 2 3 4 5 6 7 8 9 A B C D E F 內(nèi)容 文件名 擴(kuò)展名 屬性 保存位 地址 0 1 2 3 4 5 6 7 8 9 A B C D E F 內(nèi)容 保存位 時間 日期 首簇號 文件大小 這里可以看出點(diǎn)問題,F(xiàn)AT中采用4個字節(jié)保存文件的大小,也就是說,文件的大小不能超過232字節(jié),也就是4G;文件名和擴(kuò)展名采用了固定長度,分別為8和3,太長的文件名在FAT中是不允許的。
8、 其中,文件名的第一個字節(jié)還有其他的意義,例如,當(dāng)文件名的第一個字節(jié)為0x00時,表示這一項(xiàng)沒有文件;為0xE5時,如此表示這個文件已經(jīng)被刪除,在編碼時應(yīng)該忽略這個文件。 文件的屬性采用一個字節(jié),也就是8個位來表示文件的6種屬性,最高兩位是保存位,沒有實(shí)際意義。這個字節(jié)的定義為: 位 7 6 5 4 3 2 1 0 屬性 保存 保存 歸檔 目錄 卷標(biāo) 系統(tǒng) 隱藏 只讀 在列出文件列表時,對各個位進(jìn)展位與運(yùn)算以后,對結(jié)果進(jìn)展判斷,從而得出相應(yīng)的屬性值,根據(jù)上表,可以得出一個函數(shù),參數(shù)是表示文件屬性的那個字節(jié),返回值是一個以字符方式顯示文件屬性的一個字符串
9、 char *formatAttribute(char attribute) { char *result = (char *)malloc(sizeof(char)* 7); result[0] = ((attribute & 0x01) == 0x01) ? 'r' : '-'; result[1] = ((attribute & 0x02) == 0x02) ? 'h' : '-'; result[2] = ((attribute & 0x04) == 0x04) ? 's' : '-'; result[3] = ((attribute & 0x08) == 0x08) ?
10、'l' : '-'; result[4] = ((attribute & 0x10) == 0x10) ? 'd' : '-'; result[5] = ((attribute & 0x20) == 0x20) ? 'f' : '-'; result[6] = '\0'; return result; } 因?yàn)槲募傩杂?種,需要6個字符分別存放六種屬性,第7位如此用于儲存字符串的完畢標(biāo)記’\0’,確保輸出的時候不會產(chǎn)生亂碼。 這個函數(shù)代碼是通過位與運(yùn)算對文件的各個屬性進(jìn)展判斷,并在相應(yīng)的字符位用字符或者’-’填充,最后把字符串返回。 時間和日期都采用的是壓縮儲存,儲存時間兩個
11、字節(jié)的各位含義如下: 位 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 時〔0-23〕 分〔0-59〕 兩秒〔0-29〕 儲存日期兩個字節(jié)的各位含義如下: 位 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 距離1980年的年數(shù)〔0-119〕 月〔1-12〕 日〔1-31〕 注:日期和時間都需要對上下字節(jié)進(jìn)展交換然后再讀取。實(shí)驗(yàn)中使用fread方法會自動進(jìn)展交換。 根據(jù)上面的原理,可以得出這樣的一個函數(shù),這個函數(shù)以表示日期和時間的兩個原始值作為
12、參數(shù)輸入,返回的是一個格式形如〞xxxx-xx-xx xx:xx:xx〞的字符串,這個函數(shù)的代碼如下: char *formatDatetime(short date, short time) { int year, month, day, hour, minute, second; char *result = (char *)malloc(sizeof(char)* 20); year = 1980 + ((date & 0xE000) >> 9); month = ((date & 0x01E0) >> 5); day = (date & 0x001F); hour =
13、((time & 0xF800) >> 11); minute = ((time & 0x07E0) >> 5); second = ((time & 0x001F) << 1); sprintf(result, "%d-%d%d-%d%d %d%d:%d%d:%d%d", year, month / 10, month % 10, day / 10, day % 10, hour / 10, hour % 10, minute / 10, minute % 10, second / 10, second % 10); return result; } 函數(shù)的第一句,第二句是
14、為函數(shù)運(yùn)行過程中需要臨時儲存的數(shù)據(jù)分配儲存空間,隨后就是根據(jù)上述的原理,進(jìn)展位與運(yùn)算和移位操作,得到各項(xiàng)的時間屬性。最后通過sprintf函數(shù)對各個屬性按照固定的格式輸出到字符串之中并返回。 首簇號,指的是這個文件儲存在磁盤的第一個簇的簇號,也就是文件存放的具體地址。同樣地,需要對簇號的兩個字節(jié)進(jìn)展上下位交換。 最后一個是文件大小,需要對四個字節(jié)進(jìn)展上下字節(jié)交換,得到文件大小。 在實(shí)驗(yàn)中,會通過read函數(shù)每次讀入32個字節(jié),即讀取FAT表中的每一項(xiàng),在輸出文件信息時予以分析。 另外,每個目錄中都包含兩個虛擬目錄,文件名分別為’.’和’..’,分別表示當(dāng)前目錄和上一級目錄。在目錄的處理
15、時需要對其進(jìn)展判斷,防止在進(jìn)展子目錄迭代顯示時進(jìn)入死循環(huán)。綜上所述,可以得出從文件段中讀出文件信息的源碼。下面的是一些在讀取過程中所使用的一些數(shù)據(jù)結(jié)構(gòu): struct file_info { char filename[8]; char extname[3]; char attributes; char reserved[10]; short time; short date; short pos; int size; }; 上面是表示文件信息原始信息的結(jié)構(gòu)體,每個成員變量對應(yīng)一個屬性。 struct file_info_node { int id; struct
16、file_info *info; struct file_info_node *next; }; 這個文件信息鏈表的結(jié)點(diǎn),相應(yīng)地,在實(shí)驗(yàn)中定義了file_list_new_info方法,將文件信息添加到鏈表之中。 同時,為了防止遞歸調(diào)用,在實(shí)驗(yàn)中,通過一個隊列的方式實(shí)現(xiàn)列出所有子目錄文件的功能。 在下面代碼中,content_char是一個指向儲存上述文件結(jié)構(gòu)的指針,content->size是file_content中表示文件大小的一個整型變量,用于計算文件夾中最大文件數(shù)量,newInfo是一個file_info結(jié)構(gòu)體的指針,用于儲存讀取到的文件信息原始值。 先把一個文件信息的原
17、始信息從文件內(nèi)容中提取出來,為此,可以實(shí)現(xiàn)內(nèi)存復(fù)制的函數(shù),代碼如下: int copyTo(void *desc, void *src, int size) { int counter = 0, i; for (i = 0; i < size; i++, counter++) *(char *)(((char *)desc) + i) = *(char *)(((char *)src) + i); return counter; } 通過這個函數(shù)把文件信息的原始信息復(fù)制到newInfo之中。 上述的文件夾結(jié)構(gòu)不僅僅適用于根目錄,所有的目錄的遵循這種格式,所以這里可以得出一個初
18、步的結(jié)論:文件夾是一種特殊的文件。 if (newInfo->filename[0] != (char)0xE5 && newInfo->filename[0] != (char)0x00) { file_list_new_info(newInfo, &newId, &newInfoNode); if ((newInfo->attributes & 0x10) == 0x10) { if (newInfo->filename[0] == '.') continue; char *buffer = (char *)malloc(sizeof(char)* 9); int j; f
19、or (j = 0; j < 8 && newInfo->filename[j] != (char)0x20; j++) { buffer[j] = newInfo->filename[j]; } buffer[j] = '\0'; queue_new_task(buffer, 0, 0, newInfo->pos); } 這是放在一個for循環(huán)中的代碼,先通過文件名判斷這個文件是否存在,如果存在,如此把文件信息添加到程序的文件信息鏈表之中。再如此判斷是否是目錄,如果是目錄,如此把這個目錄添加到隊列之中。 2. 文件儲存方式 FAT文件系統(tǒng)對空間的分配和管理是以簇為根本單位的
20、。所以,一個邏輯上連續(xù)的文件可能會被分散地儲存在磁盤的各個位置。操作系統(tǒng)輸出文件時,遵循下面的步驟: 1. 會先通過文件夾信息找到文件首簇號。 2. 根據(jù)文件的首簇號,定位到FAT區(qū)相應(yīng)位置;讀出下一個簇的簇號。 3. 如果下一個簇的簇號不是完畢標(biāo)記(0xFFF),如此會根據(jù)讀出的下一個簇號定位,讀出簇里面的內(nèi)容。如果讀出的是完畢標(biāo)記,如此表示文件已經(jīng)讀取完成。 假設(shè)一個文件被分散儲存在0x012,0x022,0x302三個簇里。從目錄的信息中讀出首簇號0x012,讀出0x012簇里的內(nèi)容;然后再通過0x012這個簇號在FAT區(qū)中找到下一個簇號0x022,讀出0x022的內(nèi)容;再通過0
21、x022這個簇號找到下一個簇號0x302,讀出0x302中的內(nèi)容;再通過0x302讀出下一個簇號的內(nèi)容,此時,讀出的簇號為0xFFF,即表示這個文件已經(jīng)完畢。 本實(shí)驗(yàn)中,讀取文件的具體實(shí)現(xiàn)方法如下: 1. 通過一個鏈表,將這個文件的所有簇號儲存起來。 2. 遍歷儲存簇號的鏈表,逐個逐個簇讀取出來并儲存到內(nèi)存之中,返回之。 下面是讀取文件的實(shí)現(xiàn)所需要的一些數(shù)據(jù)結(jié)構(gòu): struct int_linked_list { int data; struct int_linked_list *next; }; struct file_content { struct int_linke
22、d_list *curList; void *content; int size; char *filename; }; 其中,int_linked_list是一個儲存整型的鏈表,file_content是一個用于保存讀出文件內(nèi)容和文件信息的結(jié)構(gòu)體。 遍歷鏈表的過程中,通過一個while循環(huán)實(shí)現(xiàn),把讀取到簇號添加到鏈表之中。具體實(shí)現(xiàn)代碼如下,tail為保存簇號鏈表的末尾結(jié)點(diǎn)指針,fp是用于讀取文件的文件指針,curConnt是一個用于統(tǒng)計文件簇數(shù)的變量,便于后續(xù)步驟分配內(nèi)存空間使用,下文同: while ((clusterId = getNextClutserId(fp, clu
23、sterId)) != 0x00000FFF) { curCount++; tail->next = (struct int_linked_list *)malloc(sizeof(struct int_linked_list)); tail->next->data = clusterId; tail->next->next = NULL; tail = tail->next; } 把簇號讀取完畢以后,開始對文件內(nèi)容進(jìn)展讀取,下面是文件內(nèi)容讀取的具體實(shí)現(xiàn)代碼,下面代碼中的content是一個指向用于存放文件內(nèi)容的內(nèi)存空間的指針變量: content->size = curCo
24、unt * 512; content->content = malloc(content->size); struct int_linked_list *ptr = head; int i = 0, address = 0xFFFFFFF; for (ptr = head; ptr != NULL; ptr = ptr->next, i++) { address = 0x00003E00 + (512 * ptr->data); fseek(fp, address, SEEK_SET); fread((void *)(((char *)(content->content)) +
25、 (512 * i)), 512, 1, fp); } 在for循環(huán)的第一句代碼之中,通過簇號對簇所在的地址進(jìn)展計算,把地址值儲存到address變量之中;第二句代碼如此是通過上一步計算得到的address變量對文件指針進(jìn)展定位,第三句是通過fread方法把文件內(nèi)容讀入到內(nèi)存之中。 六、 實(shí)驗(yàn)結(jié)論 1. FAT12文件系統(tǒng)中,把磁盤劃分成引導(dǎo)區(qū)、FAT區(qū)、FAT備份區(qū)、根目錄區(qū)和文件數(shù)據(jù)區(qū)。 2. 除了根目錄以外,文件系統(tǒng)把每個文件夾都當(dāng)成是一個特殊的文件進(jìn)展處理。 3. FAT12文件系統(tǒng)通過簇進(jìn)展空間的管理和分配。 七、 完整實(shí)驗(yàn)代碼 /* * 操作系統(tǒng)課程 實(shí)驗(yàn) *
26、 FAT12 文件系統(tǒng) 實(shí)驗(yàn)代碼 * * 雖然這個程序在 Windows 和 Linux 環(huán)境下都能運(yùn)行。 * 不過,在 Windows 環(huán)境下運(yùn)行的話,顯示文件內(nèi)容的時候,內(nèi)容的末尾會有幾個奇怪的字符。 * Linux 環(huán)境下完全沒問題 * 暫時推測是 Windows 控制臺的原因,Windows 控制臺會把一些非字符的 ASCII 顯示為奇怪的字符, * 例如,0x0A 會顯示成一個笑臉,Linux 的控制臺下不會對這些非字符的 ASCII 進(jìn)展處理 * * 我是今天早上才發(fā)現(xiàn)這個問題的阿 (╯‵□′)╯︵┻━┻ * * 注意:編
27、譯前,需要把 IMAGE_FILE 那個宏定義改成公郵上面的那個 IMG 文件;
* Linux 下打開這個源碼文件注釋會變成亂碼
*
*/
// 這個定義只是為了程序能在 VS2013 下面正常編譯而已
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif
#include
28、 0x00000000 #define MESSAGE_FILE_NOT_FOUND 0xE0000404 #define ERROR_MALLOC_FAILED 0xF0000001 #define ERROR_IO_ERROR 0xF0000002 // ↓ 這里改路徑 ↓ #define IMAGE_FILE "/home/user/DOS622.IMG" // ↑ 這里改路徑 ↑ /******************** 這里是結(jié)構(gòu)體的定義 ******************
29、********/ // 這里是文件信息 struct file_info { char filename[8]; char extname[3]; char attributes; char reserved[10]; short time; short date; short pos; int size; }; struct file_info_node { int id; struct file_info *info; struct file_info_node *next; }; // 這里是儲存文件夾信息 struct folder_inf
30、o { char *filename; int fileBeginIndex, fileEndIndex; struct file_info_node *beginFile, *endFile; struct folder_info *next; }; // 這里是一個隊列,用于迭代方式遍歷文件系統(tǒng)的一個中間變量 struct queue_info { char *filename; int offset, size, cluster; struct queue_info *next; }; // 一個整數(shù)鏈表結(jié)構(gòu) struct int_linked_list
31、 { int data; struct int_linked_list *next; }; // 這里是一個文件結(jié)構(gòu),表示內(nèi)容,可以讀取文件的其中一段,也可以通過簇的方式完整讀入整個文件 struct file_content { struct int_linked_list *curList; void *content; int size; char *filename; }; /******************** 這里是全局變量的定義 **************************/ struct file_info_node *file_li
32、st_head, *file_list_tail; struct folder_info *folder_info_head, *folder_info_tail; struct queue_info *queue_head, *queue_tail; char decToHex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /******************** 這里是函數(shù)的定義 **************************/ int
33、 file_list_init(); int file_list_new_info(struct file_info *info, int *id, struct file_info_node **newInfoNode); int folder_info_init(); int folder_info_new_info(struct folder_info *info); int queue_init(); int queue_new_task(char *filename, int offset, int size, int cluster); struct queue
34、_info *queue_get_task(); int process_task(struct queue_info* info); struct file_content* readContentFromFixedSection(FILE *fp, int offset, int size); struct file_content* readContentFromCluster(FILE *fp, short clusterId, int isFolder, int *size); struct file_content* find_file_by_id(FILE *fp,
35、int id, int *errCode); int process_file_content(struct file_content* content, struct queue_info *info); int getNextClutserId(FILE *fp, short clusterId); int copyTo(void *desc, void *src, int size); void print_all_list(); void print_file_content(struct file_content *content); char *format
36、Index(int i); char *formatClustNo(int i); char *formatFileName(char *filename, char *ext); char *formatAttribute(char attribute); char *formatDatetime(short date, short time); char *formatSize(int size, int rightAlign); /******************** 主函數(shù) **************************/ int main(int argc
37、, char **args) { struct queue_info *task = NULL; int choose, status; FILE *fp = fopen(IMAGE_FILE, "r"); struct file_content *content; char tmp; if (fp == NULL) { return 1; } getNextClutserId(fopen(IMAGE_FILE, "r"), 2); queue_init(); queue_new_task("Root", 0x00002600, 6144, 0);
38、while ((task = queue_get_task()) != NULL) { process_task(task); } print_all_list(); fflush(stdin); printf("\nThe Number of File you want to view (enter -1 to exit): "); scanf("%d", &choose); content = find_file_by_id(fp, choose, &status); if (status == MESSAGE_FILE_NOT_FOUND) { prin
39、tf("Invaild Number, please input again!\n"); return 0; } else { if (content != NULL) { print_file_content(content); } } return 0; } int process_task(struct queue_info* info) { FILE *fp; struct file_content* content = NULL; int size = 0; fp = fopen(IMAGE_FILE, "r"); if (fp ==
40、NULL) { return ERROR_IO_ERROR; } // 判斷是否對根目錄進(jìn)展讀取 if (info->offset == 0x00002600) { content = readContentFromFixedSection(fp, info->offset, info->size); } else { content = readContentFromCluster(fp, info->cluster, 1, &size); info->size = size; } process_file_content(content, info);
41、 fclose(fp); return OK; } int process_file_content(struct file_content* content, struct queue_info *info) { struct folder_info *node = (struct folder_info *)malloc(sizeof(struct folder_info)); struct file_info *newInfo = NULL; struct file_info_node *newInfoNode = NULL; char *content_char
42、 = (char *)content->content; int newId = -1, fileCount = 0; if (node == NULL) { return ERROR_MALLOC_FAILED; } node->filename = info->filename; // 根據(jù)大小計算目錄中的文件數(shù)量 int maxFile = content->size / 32, i; for (i = 0; i < maxFile; i++) { newInfo = (struct file_info *)malloc(sizeof(struct fi
43、le_info)); if (newInfo == NULL) { printf("malloc failed!\n"); return ERROR_MALLOC_FAILED; } copyTo((void *)newInfo, (void *)(content_char + (32 * i)), 32); if (newInfo->filename[0] != (char)0xE5 && newInfo->filename[0] != (char)0x00) { file_list_new_info(newInfo, &newId, &newInfoNode);
44、 if ((newInfo->attributes & 0x10) == 0x10) { if (newInfo->filename[0] == '.') { continue; } char *buffer = (char *)malloc(sizeof(char)* 9); int j; for (j = 0; j < 8 && newInfo->filename[j] != (char)0x20; j++) { buffer[j] = newInfo->filename[j]; } buffer[j] = '\0'; queue_new_task(bu
45、ffer, 0, 0, newInfo->pos); } if (0 == fileCount) { node->fileBeginIndex = newId; node->beginFile = newInfoNode; } fileCount++; } } node->fileEndIndex = file_list_tail->id; node->endFile = file_list_tail; folder_info_new_info(node); return OK; } int copyTo(void *desc, void *s
46、rc, int size) { int counter = 0, i; for (i = 0; i < size; i++, counter++) { *(char *)(((char *)desc) + i) = *(char *)(((char *)src) + i); } return counter; } int file_list_init() { file_list_head = NULL; file_list_tail = NULL; return OK; } int file_list_new_info(struct file_in
47、fo *info, int *id, struct file_info_node **newInfoNode) { struct file_info_node *newNode = (struct file_info_node*)malloc(sizeof(struct file_info_node)); if (newNode == NULL) { return ERROR_MALLOC_FAILED; } newNode->info = info; newNode->next = NULL; if (file_list_head == NULL) { newN
48、ode->id = 1; file_list_head = newNode; file_list_tail = newNode; } else { newNode->id = file_list_tail->id + 1; file_list_tail->next = newNode; file_list_tail = newNode; } *newInfoNode = newNode; *id = newNode->id; return OK; } int folder_info_init() { folder_info_head = fo
49、lder_info_tail = NULL; return OK; } int folder_info_new_info(struct folder_info *info) { if (info == NULL) { return OK; } if (folder_info_head == NULL) { info->next = NULL; folder_info_head = info; folder_info_tail = info; } else { info->next = NULL; folder_info_tail->next =
50、info; folder_info_tail = info; } return OK; } int queue_init() { queue_head = queue_tail = NULL; return OK; } int queue_new_task(char *filename, int offset, int size, int cluster) { struct queue_info *newNode = (struct queue_info *)malloc(sizeof(struct queue_info)); if (newNode
51、== NULL) { return ERROR_MALLOC_FAILED; } newNode->filename = filename; newNode->offset = offset; newNode->size = size; newNode->cluster = cluster; newNode->next = NULL; if (queue_head == NULL) { queue_head = queue_tail = newNode; } else { queue_tail->next = newNode; queue_tail =
52、newNode; } return OK; } struct queue_info *queue_get_task() { struct queue_info *retValue = queue_head; if (queue_head == NULL) { return NULL; } if (queue_head == queue_tail) { queue_tail = NULL; } queue_head = queue_head->next; retValue->next = NULL; return retValue; }
53、 struct file_content* readContentFromFixedSection(FILE *fp, int offset, int size) { if (fp == NULL) { return NULL; } struct file_content *retValue = (struct file_content *)malloc(sizeof(struct file_content)); if (retValue == NULL) { return NULL; } retValue->curList = NULL; retValu
54、e->size = size; retValue->content = malloc(size); if (retValue->content == NULL) { free(retValue); return NULL; } fseek(fp, offset, SEEK_SET); fread(retValue->content, size, 1, fp); return retValue; } struct file_content* readContentFromCluster(FILE *fp, short clusterId, int isFol
55、der, int *size) { int curCount = 1; struct file_content *content = (struct file_content *)malloc(sizeof(struct file_content)); if (content == NULL) { return NULL; } // 第一步:迭代尋找所有簇號 content->curList = (struct int_linked_list *)malloc(sizeof(struct int_linked_list)); if (content->curList =
56、= NULL) { return NULL; } struct int_linked_list *head = content->curList, *tail = head; head->data = clusterId; head->next = NULL; while ((clusterId = getNextClutserId(fp, clusterId)) != 0x00000FFF) { curCount++; tail->next = (struct int_linked_list *)malloc(sizeof(struct int_linked_li
57、st)); tail->next->data = clusterId; tail->next->next = NULL; tail = tail->next; } // 第二步:開始根據(jù)簇號讀取 content->size = curCount * 512; content->content = malloc(content->size); struct int_linked_list *ptr = head; int i = 0, address = 0xFFFFFFF; for (ptr = head; ptr != NULL; ptr = ptr->next,
58、 i++) { address = 0x00003E00 + (512 * ptr->data); fseek(fp, address, SEEK_SET); fread((void *)(((char *)(content->content)) + (512 * i)), 512, 1, fp); } if (size != NULL) { *size = content->size; } return content; } struct file_content* find_file_by_id(FILE *fp, int id, int *errCod
59、e) { if (id < 1) { *errCode = MESSAGE_FILE_NOT_FOUND; return NULL; } // 先遍歷目錄尋找這個文件 struct folder_info *ptr = folder_info_head; struct file_info_node *node = NULL, *tmp = NULL; struct file_content *content = NULL; while (ptr != NULL) { if (ptr->fileBeginIndex <= id && id <= ptr->fil
60、eEndIndex) { for (tmp = ptr->beginFile; tmp->id != id && id <= ptr->fileEndIndex; tmp = tmp->next); if (tmp->id == id) { node = tmp; break; } } else { ptr = ptr->next; } } *errCode = (node == NULL ? MESSAGE_FILE_NOT_FOUND : OK); if (node != NULL) { content = readContentFromCluster
61、(fp, node->info->pos, 0, NULL); content->size = node->info->size; content->filename = formatFileName(node->info->filename, node->info->extname); } return (node == NULL ? NULL : content); } int getNextClutserId(FILE *fp, short clusterId) { if (clusterId == 0x000000A0) { printf(""); }
62、 unsigned short tmp; int address = (clusterId * 3 / 2) + 0x0000200; unsigned short low = 0, high = 0; fseek(fp, address, SEEK_SET); fread((void *)(&tmp), 1, sizeof(unsigned short), fp); low = ((tmp & 0xFFF0) >> 4); high = tmp & 0x0FFF; return (clusterId % 2 == 0 ? high : low); } vo
63、id print_all_list() { struct folder_info *ptr = folder_info_head; struct file_info_node *node; int index; #ifdef _WIN32 system("cls"); #else printf("\033[2J"); #endif for (; ptr != NULL; ptr = ptr->next) { int count = 0, totalSize = 0; printf("--------------------------------------
64、------------------------------------\n"); printf(" Folder : %s\n", ptr->filename); printf("--------------------------------------------------------------------------\n"); printf(" Num | File Name | Type | CLUSTNO | File Change Time | Size \n"); printf("-----------------------------
65、---------------------------------------------\n"); index = ptr->fileBeginIndex; node = ptr->beginFile; while (node != NULL && node->id <= ptr->fileEndIndex) { // 只是實(shí)現(xiàn)不同平臺下的變色操作 #ifdef _WIN32 HANDLE hOut; hOut = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hOut, ((node->in
66、fo->attributes & 0x10) == 0x10) ? FOREGROUND_GREEN : (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)); #else printf(((node->info->attributes & 0x10) == 0x10) ? "\033[32m" : "\033[0m"); #endif printf(" %s | %s | %s | %s | %s | %s\n", formatIndex(node->id), formatFileName(node->info->filename, node->info->extname), formatAttribute(node->info->attributes), formatClustNo(node->info->pos), formatDatetime(node->info->date, node->info->time), ((node->info->attributes & 0x10) == 0x10) ?
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。