實(shí)驗(yàn)四 文件資料系統(tǒng) 實(shí)驗(yàn)報(bào)告材料
《實(shí)驗(yàn)四 文件資料系統(tǒng) 實(shí)驗(yàn)報(bào)告材料》由會(huì)員分享,可在線閱讀,更多相關(guān)《實(shí)驗(yàn)四 文件資料系統(tǒng) 實(shí)驗(yàn)報(bào)告材料(40頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
1、word 文件系統(tǒng) 實(shí)驗(yàn)報(bào)告 一、 實(shí)驗(yàn)?zāi)康? 了解操作系統(tǒng)中文件系統(tǒng)的原理以與實(shí)現(xiàn)方法。 二、 實(shí)驗(yàn)方法 通過(guò)FAT12文件系統(tǒng)的解讀,了解文件系統(tǒng)的原理和實(shí)現(xiàn)。 三、 實(shí)驗(yàn)任務(wù) 通過(guò)對(duì)FAT12文件系統(tǒng)的了解,編寫(xiě)程序,讀取并列出一個(gè)虛擬軟盤(pán)中文件信息〔文件名、屬性、修改時(shí)間等〕,以與讀取其中的文件內(nèi)容 四、 實(shí)驗(yàn)要點(diǎn) FAT12文件系統(tǒng)的了解,Linux系統(tǒng)下文件讀寫(xiě)相關(guān)系統(tǒng)調(diào)用。 五、 實(shí)驗(yàn)過(guò)程 1. FAT12 文件系統(tǒng)分析 簇是操作系統(tǒng)分配文件空間的根本單位,簇由假設(shè)干個(gè)扇區(qū)組成。在FAT12文件系統(tǒng)中,簇號(hào)的有效位是12位,所以這種文件系統(tǒng)就被稱(chēng)為FAT1
2、2。FAT12文件系統(tǒng)中大致可以分成五個(gè)區(qū),這五個(gè)區(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ū)中儲(chǔ)存著一些根本的信息。例如,0x0000000B和0x0000000C兩個(gè)字節(jié)保存著每個(gè)扇區(qū)的大小,0x000000
3、0D保存著每個(gè)簇占用多少個(gè)扇區(qū)。 FAT區(qū)中儲(chǔ)存著簇號(hào)。在0x00000200開(kāi)始的三個(gè)字節(jié),分別儲(chǔ)存設(shè)備類(lèi)型標(biāo)記(0xF0為軟盤(pán));第二個(gè)第三個(gè)字節(jié)均為0xFF,是FAT標(biāo)識(shí)符。在FAT12文件系統(tǒng)中,每個(gè)簇占用12位,即1.5個(gè)字節(jié)。簇號(hào)與地址的對(duì)應(yīng)關(guān)系如下表: 地址偏移 000 001 002 003 004 005 簇序號(hào) 000 001 002 003 一個(gè)簇號(hào)跨越兩個(gè)字節(jié),每次讀取簇號(hào)時(shí)讀取兩個(gè)字節(jié),然后對(duì)讀出的兩個(gè)字節(jié)進(jìn)展位運(yùn)算處理,得到下一簇的簇序號(hào)。 注意,這里同樣需要對(duì)上下位進(jìn)展處理,即使用位計(jì)算的方式提取相應(yīng)的簇號(hào)信息。 根據(jù)上述的原理,可
4、以得出一個(gè)函數(shù),以一個(gè)簇號(hào)為參數(shù),返回值為文件下一個(gè)簇號(hào)。代碼如下: 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)前簇號(hào),返回值是下一個(gè)簇號(hào)。 函數(shù)體的第二句代碼,計(jì)算出當(dāng)前簇號(hào)對(duì)應(yīng)的地址,用于文件指針的定位。第三句代碼是根據(jù)第二句計(jì)算得到的地址對(duì)文件指針進(jìn)展定位,定位到當(dāng)前簇號(hào)所對(duì)應(yīng)的信息處。第四句代碼是從文件指針的位置為起始位置讀入兩個(gè)字節(jié)的內(nèi)容〔fread會(huì)自動(dòng)對(duì)上下字節(jié)位進(jìn)展處理〕。并把這兩個(gè)字節(jié)的信息儲(chǔ)存到tmp變量之中。例如,讀取002簇號(hào)的下一個(gè)簇號(hào),根據(jù)公式,計(jì)算得到的address是0x00000203,
6、讀取到0x00000203和0x00000204兩個(gè)字節(jié)的內(nèi)容。我們需要的是0x00000203整個(gè)字節(jié)的內(nèi)容和0x00000204的高四位,所以需要跟0xFFF0進(jìn)展位與運(yùn)算,并向右移四位,得到下一個(gè)簇號(hào)。 同樣地,讀取003簇號(hào)的下一個(gè)簇號(hào),根據(jù)公式,計(jì)算得到的address是0x00000204,讀取到0x00000204和0x00000205兩個(gè)字節(jié)的內(nèi)容,我們需要的是0x00000205整個(gè)字節(jié)的內(nèi)容和0x00000204第四位的內(nèi)容,所以需要跟0x0FFF進(jìn)展位與運(yùn)算,得到下一個(gè)簇號(hào)。所以代碼中需要對(duì)簇號(hào)的奇偶性進(jìn)展判斷,跟根據(jù)奇偶性的不同返回不同的值。 在根目錄中,保存著
7、根目錄下面的文件或文件夾的信息。每個(gè)文件或者文件夾的信息使用32個(gè)字節(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)容 保存位 時(shí)間 日期 首簇號(hào) 文件大小 這里可以看出點(diǎn)問(wèn)題,F(xiàn)AT中采用4個(gè)字節(jié)保存文件的大小,也就是說(shuō),文件的大小不能超過(guò)232字節(jié),也就是4G;文件名和擴(kuò)展名采用了固定長(zhǎng)度,分別為8和3,太長(zhǎng)的文件名在FAT中是不允許的。
8、 其中,文件名的第一個(gè)字節(jié)還有其他的意義,例如,當(dāng)文件名的第一個(gè)字節(jié)為0x00時(shí),表示這一項(xiàng)沒(méi)有文件;為0xE5時(shí),如此表示這個(gè)文件已經(jīng)被刪除,在編碼時(shí)應(yīng)該忽略這個(gè)文件。 文件的屬性采用一個(gè)字節(jié),也就是8個(gè)位來(lái)表示文件的6種屬性,最高兩位是保存位,沒(méi)有實(shí)際意義。這個(gè)字節(jié)的定義為: 位 7 6 5 4 3 2 1 0 屬性 保存 保存 歸檔 目錄 卷標(biāo) 系統(tǒng) 隱藏 只讀 在列出文件列表時(shí),對(duì)各個(gè)位進(jìn)展位與運(yùn)算以后,對(duì)結(jié)果進(jìn)展判斷,從而得出相應(yīng)的屬性值,根據(jù)上表,可以得出一個(gè)函數(shù),參數(shù)是表示文件屬性的那個(gè)字節(jié),返回值是一個(gè)以字符方式顯示文件屬性的一個(gè)字符串
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個(gè)字符分別存放六種屬性,第7位如此用于儲(chǔ)存字符串的完畢標(biāo)記’\0’,確保輸出的時(shí)候不會(huì)產(chǎn)生亂碼。 這個(gè)函數(shù)代碼是通過(guò)位與運(yùn)算對(duì)文件的各個(gè)屬性進(jìn)展判斷,并在相應(yīng)的字符位用字符或者’-’填充,最后把字符串返回。 時(shí)間和日期都采用的是壓縮儲(chǔ)存,儲(chǔ)存時(shí)間兩個(gè)
11、字節(jié)的各位含義如下: 位 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 時(shí)〔0-23〕 分〔0-59〕 兩秒〔0-29〕 儲(chǔ)存日期兩個(gè)字節(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〕 注:日期和時(shí)間都需要對(duì)上下字節(jié)進(jìn)展交換然后再讀取。實(shí)驗(yàn)中使用fread方法會(huì)自動(dòng)進(jìn)展交換。 根據(jù)上面的原理,可以得出這樣的一個(gè)函數(shù),這個(gè)函數(shù)以表示日期和時(shí)間的兩個(gè)原始值作為
12、參數(shù)輸入,返回的是一個(gè)格式形如〞xxxx-xx-xx xx:xx:xx〞的字符串,這個(gè)函數(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)行過(guò)程中需要臨時(shí)儲(chǔ)存的數(shù)據(jù)分配儲(chǔ)存空間,隨后就是根據(jù)上述的原理,進(jìn)展位與運(yùn)算和移位操作,得到各項(xiàng)的時(shí)間屬性。最后通過(guò)sprintf函數(shù)對(duì)各個(gè)屬性按照固定的格式輸出到字符串之中并返回。 首簇號(hào),指的是這個(gè)文件儲(chǔ)存在磁盤(pán)的第一個(gè)簇的簇號(hào),也就是文件存放的具體地址。同樣地,需要對(duì)簇號(hào)的兩個(gè)字節(jié)進(jìn)展上下位交換。 最后一個(gè)是文件大小,需要對(duì)四個(gè)字節(jié)進(jìn)展上下字節(jié)交換,得到文件大小。 在實(shí)驗(yàn)中,會(huì)通過(guò)read函數(shù)每次讀入32個(gè)字節(jié),即讀取FAT表中的每一項(xiàng),在輸出文件信息時(shí)予以分析。 另外,每個(gè)目錄中都包含兩個(gè)虛擬目錄,文件名分別為’.’和’..’,分別表示當(dāng)前目錄和上一級(jí)目錄。在目錄的處理
15、時(shí)需要對(duì)其進(jìn)展判斷,防止在進(jìn)展子目錄迭代顯示時(shí)進(jìn)入死循環(huán)。綜上所述,可以得出從文件段中讀出文件信息的源碼。下面的是一些在讀取過(guò)程中所使用的一些數(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)體,每個(gè)成員變量對(duì)應(yīng)一個(gè)屬性。 struct file_info_node { int id; struct
16、file_info *info; struct file_info_node *next; }; 這個(gè)文件信息鏈表的結(jié)點(diǎn),相應(yīng)地,在實(shí)驗(yàn)中定義了file_list_new_info方法,將文件信息添加到鏈表之中。 同時(shí),為了防止遞歸調(diào)用,在實(shí)驗(yàn)中,通過(guò)一個(gè)隊(duì)列的方式實(shí)現(xiàn)列出所有子目錄文件的功能。 在下面代碼中,content_char是一個(gè)指向儲(chǔ)存上述文件結(jié)構(gòu)的指針,content->size是file_content中表示文件大小的一個(gè)整型變量,用于計(jì)算文件夾中最大文件數(shù)量,newInfo是一個(gè)file_info結(jié)構(gòu)體的指針,用于儲(chǔ)存讀取到的文件信息原始值。 先把一個(gè)文件信息的原
17、始信息從文件內(nèi)容中提取出來(lá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; } 通過(guò)這個(gè)函數(shù)把文件信息的原始信息復(fù)制到newInfo之中。 上述的文件夾結(jié)構(gòu)不僅僅適用于根目錄,所有的目錄的遵循這種格式,所以這里可以得出一個(gè)初
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); } 這是放在一個(gè)for循環(huán)中的代碼,先通過(guò)文件名判斷這個(gè)文件是否存在,如果存在,如此把文件信息添加到程序的文件信息鏈表之中。再如此判斷是否是目錄,如果是目錄,如此把這個(gè)目錄添加到隊(duì)列之中。 2. 文件儲(chǔ)存方式 FAT文件系統(tǒng)對(duì)空間的分配和管理是以簇為根本單位的
20、。所以,一個(gè)邏輯上連續(xù)的文件可能會(huì)被分散地儲(chǔ)存在磁盤(pán)的各個(gè)位置。操作系統(tǒng)輸出文件時(shí),遵循下面的步驟: 1. 會(huì)先通過(guò)文件夾信息找到文件首簇號(hào)。 2. 根據(jù)文件的首簇號(hào),定位到FAT區(qū)相應(yīng)位置;讀出下一個(gè)簇的簇號(hào)。 3. 如果下一個(gè)簇的簇號(hào)不是完畢標(biāo)記(0xFFF),如此會(huì)根據(jù)讀出的下一個(gè)簇號(hào)定位,讀出簇里面的內(nèi)容。如果讀出的是完畢標(biāo)記,如此表示文件已經(jīng)讀取完成。 假設(shè)一個(gè)文件被分散儲(chǔ)存在0x012,0x022,0x302三個(gè)簇里。從目錄的信息中讀出首簇號(hào)0x012,讀出0x012簇里的內(nèi)容;然后再通過(guò)0x012這個(gè)簇號(hào)在FAT區(qū)中找到下一個(gè)簇號(hào)0x022,讀出0x022的內(nèi)容;再通過(guò)0
21、x022這個(gè)簇號(hào)找到下一個(gè)簇號(hào)0x302,讀出0x302中的內(nèi)容;再通過(guò)0x302讀出下一個(gè)簇號(hào)的內(nèi)容,此時(shí),讀出的簇號(hào)為0xFFF,即表示這個(gè)文件已經(jīng)完畢。 本實(shí)驗(yàn)中,讀取文件的具體實(shí)現(xiàn)方法如下: 1. 通過(guò)一個(gè)鏈表,將這個(gè)文件的所有簇號(hào)儲(chǔ)存起來(lái)。 2. 遍歷儲(chǔ)存簇號(hào)的鏈表,逐個(gè)逐個(gè)簇讀取出來(lái)并儲(chǔ)存到內(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是一個(gè)儲(chǔ)存整型的鏈表,file_content是一個(gè)用于保存讀出文件內(nèi)容和文件信息的結(jié)構(gòu)體。 遍歷鏈表的過(guò)程中,通過(guò)一個(gè)while循環(huán)實(shí)現(xiàn),把讀取到簇號(hào)添加到鏈表之中。具體實(shí)現(xiàn)代碼如下,tail為保存簇號(hào)鏈表的末尾結(jié)點(diǎn)指針,fp是用于讀取文件的文件指針,curConnt是一個(gè)用于統(tǒng)計(jì)文件簇?cái)?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; } 把簇號(hào)讀取完畢以后,開(kāi)始對(duì)文件內(nèi)容進(jìn)展讀取,下面是文件內(nèi)容讀取的具體實(shí)現(xiàn)代碼,下面代碼中的content是一個(gè)指向用于存放文件內(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)的第一句代碼之中,通過(guò)簇號(hào)對(duì)簇所在的地址進(jìn)展計(jì)算,把地址值儲(chǔ)存到address變量之中;第二句代碼如此是通過(guò)上一步計(jì)算得到的address變量對(duì)文件指針進(jìn)展定位,第三句是通過(guò)fread方法把文件內(nèi)容讀入到內(nèi)存之中。 六、 實(shí)驗(yàn)結(jié)論 1. FAT12文件系統(tǒng)中,把磁盤(pán)劃分成引導(dǎo)區(qū)、FAT區(qū)、FAT備份區(qū)、根目錄區(qū)和文件數(shù)據(jù)區(qū)。 2. 除了根目錄以外,文件系統(tǒng)把每個(gè)文件夾都當(dāng)成是一個(gè)特殊的文件進(jìn)展處理。 3. FAT12文件系統(tǒng)通過(guò)簇進(jìn)展空間的管理和分配。 七、 完整實(shí)驗(yàn)代碼 /* * 操作系統(tǒng)課程 實(shí)驗(yàn) *
26、 FAT12 文件系統(tǒng) 實(shí)驗(yàn)代碼 * * 雖然這個(gè)程序在 Windows 和 Linux 環(huán)境下都能運(yùn)行。 * 不過(guò),在 Windows 環(huán)境下運(yùn)行的話,顯示文件內(nèi)容的時(shí)候,內(nèi)容的末尾會(huì)有幾個(gè)奇怪的字符。 * Linux 環(huán)境下完全沒(méi)問(wèn)題 * 暫時(shí)推測(cè)是 Windows 控制臺(tái)的原因,Windows 控制臺(tái)會(huì)把一些非字符的 ASCII 顯示為奇怪的字符, * 例如,0x0A 會(huì)顯示成一個(gè)笑臉,Linux 的控制臺(tái)下不會(huì)對(duì)這些非字符的 ASCII 進(jìn)展處理 * * 我是今天早上才發(fā)現(xiàn)這個(gè)問(wèn)題的阿 (╯‵□′)╯︵┻━┻ * * 注意:編
27、譯前,需要把 IMAGE_FILE 那個(gè)宏定義改成公郵上面的那個(gè) IMG 文件;
* Linux 下打開(kāi)這個(gè)源碼文件注釋會(huì)變成亂碼
*
*/
// 這個(gè)定義只是為了程序能在 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; }; // 這里是儲(chǔ)存文件夾信息 struct folder_inf
30、o { char *filename; int fileBeginIndex, fileEndIndex; struct file_info_node *beginFile, *endFile; struct folder_info *next; }; // 這里是一個(gè)隊(duì)列,用于迭代方式遍歷文件系統(tǒng)的一個(gè)中間變量 struct queue_info { char *filename; int offset, size, cluster; struct queue_info *next; }; // 一個(gè)整數(shù)鏈表結(jié)構(gòu) struct int_linked_list
31、 { int data; struct int_linked_list *next; }; // 這里是一個(gè)文件結(jié)構(gòu),表示內(nèi)容,可以讀取文件的其中一段,也可以通過(guò)簇的方式完整讀入整個(gè)文件 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; } // 判斷是否對(duì)根目錄進(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ù)大小計(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; } // 第一步:迭代尋找所有簇號(hào) 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; } // 第二步:開(kāi)始根據(jù)簇號(hào)讀取 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; } // 先遍歷目錄尋找這個(gè)文件 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)不同平臺(tái)下的變色操作 #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: 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 川渝旅游日記成都重慶城市介紹推薦景點(diǎn)美食推薦
- XX國(guó)有企業(yè)黨委書(shū)記個(gè)人述責(zé)述廉報(bào)告及2025年重點(diǎn)工作計(jì)劃
- 世界濕地日濕地的含義及價(jià)值
- 20XX年春節(jié)節(jié)后復(fù)工安全生產(chǎn)培訓(xùn)人到場(chǎng)心到崗
- 大唐女子圖鑒唐朝服飾之美器物之美繪畫(huà)之美生活之美
- 節(jié)后開(kāi)工第一課輕松掌握各要點(diǎn)節(jié)后常見(jiàn)的八大危險(xiǎn)
- 廈門(mén)城市旅游介紹廈門(mén)景點(diǎn)介紹廈門(mén)美食展示
- 節(jié)后開(kāi)工第一課復(fù)工復(fù)產(chǎn)十注意節(jié)后復(fù)工十檢查
- 傳統(tǒng)文化百善孝為先孝道培訓(xùn)
- 深圳城市旅游介紹景點(diǎn)推薦美食探索
- 節(jié)后復(fù)工安全生產(chǎn)培訓(xùn)勿忘安全本心人人講安全個(gè)個(gè)會(huì)應(yīng)急
- 預(yù)防性維修管理
- 常見(jiàn)閥門(mén)類(lèi)型及特點(diǎn)
- 設(shè)備預(yù)防性維修
- 2.乳化液泵工理論考試試題含答案