实验四 文件系统 实验报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

文件系统实验报告
一、实验目的
了解操作系统中文件系统的原理以及实现方法。

二、实验方法
通过FAT12文件系统的解读,了解文件系统的原理和实现。

三、实验任务
通过对FAT12文件系统的了解,编写程序,读取并列出一个虚拟软盘中文件信息(文件名、属性、修改时间等),以及读取其中的文件内容
四、实验要点
FAT12文件系统的了解,Linux系统下文件读写相关系统调用。

五、实验过程
1. FAT12 文件系统分析
簇是操作系统分配文件空间的基本单位,簇由若干个扇区组成。

在FAT12文件系统中,簇号的有效位是12位,所以这种文件系统就被称为FAT12。

FAT12
其中,引导区中储存着一些基本的信息。

例如,0x0000000B和0x0000000C 两个字节保存着每个扇区的大小,0x0000000D保存着每个簇占用多少个扇区。

FAT区中储存着簇号。

在0x00000200开始的三个字节,分别储存设备类型标记(0xF0为软盘);第二个第三个字节均为0xFF,是FAT标识符。

在FAT12
文件系统中,每个簇占用12位,即1.5个字节。

簇号与地址的对应关系如下
表:
然后对读出的两个字节进行位运算处理,得到下一簇的簇序号。

注意,这里同样需要对高低位进行处理,即使用位计算的方式提取相应的簇号信息。

根据上述的原理,可以得出一个函数,以一个簇号为参数,返回值为文件下一个簇号。

代码如下:
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 = tmp & 0x0FFF;
return (clusterId % 2 == 0 ? high : low);
}
其中,fp 是用于读取文件系统的文件流,clusterID是当前簇号,返回值是下一个簇号。

函数体的第二句代码,计算出当前簇号对应的地址,用于文件指针的定位。

第三句代码是根据第二句计算得到的地址对文件指针进行定位,定位到当前簇号所对应的信息处。

第四句代码是从文件指针的位置为起始位置读入两个字节的内容(fread会自动对高低字节位进行处理)。

并把这两个字节的信息储存到tmp变量之中。

例如,读取002簇号的下一个簇号,根据公式,计算得到的address是0x00000203,读取到0x00000203和0x00000204两个字节的内容。

我们需要的是0x00000203整个字节的内容和0x00000204的高四位,所以需要跟0xFFF0进行位与运算,并向右移四位,得到下一个簇号。

同样地,读取003簇号的下一个簇号,根据公式,计算得到的address是0x00000204,读取到0x00000204和0x00000205两个字节的内容,我们需要的是0x00000205整个字节的内容和0x00000204第四位的内容,所以需要跟0x0FFF进行位与运算,得到下一个簇号。

所以代码中需要对簇号的奇偶性进行判断,跟根据奇偶性的不同返回不同的值。

在根目录中,保存着根目录下面的文件或文件夹的信息。

每个文件或者文件夹的信息使用32个字节保存。

这些内容的含义如下表:
文件的大小不能超过232字节,也就是4G;文件名和扩展名采用了固定长度,分别为8和3,太长的文件名在FAT中是不允许的。

其中,文件名的第一个字节还有其他的意义,例如,当文件名的第一个字节为0x00时,表示这一项没有文件;为0xE5时,则表示这个文件已经被删除,在编码时应该忽略这个文件。

文件的属性采用一个字节,也就是8个位来表示文件的6种属性,最高两
得出相应的属性值,根据上表,可以得出一个函数,参数是表示文件属性的那个字节,返回值是一个以字符方式显示文件属性的一个字符串
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) ? 'l' : '-';
result[4] = ((attribute & 0x10) == 0x10) ? 'd' : '-';
result[5] = ((attribute & 0x20) == 0x20) ? 'f' : '-';
result[6] = '\0';
return result;
}
因为文件属性有6种,需要6个字符分别存放六种属性,第7位则用于储存字符串的结束标记’\0’,确保输出的时候不会产生乱码。

这个函数代码是通过位与运算对文件的各个属性进行判断,并在相应的字符位用字符或者’-’填充,最后把字符串返回。

时间和日期都采用的是压缩储存,储存时间两个字节的各位含义如下:
注:日期和时间都需要对高低字节进行交换然后再读取。

实验中使用fread 方法会自动进行交换。

根据上面的原理,可以得出这样的一个函数,这个函数以表示日期和时间的两个原始值作为参数输入,返回的是一个格式形如”xxxx-xx-xx xx:xx:xx”的字符串,这个函数的代码如下:
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 = ((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;
}
函数的第一句,第二句是为函数运行过程中需要临时储存的数据分配储存空间,随后就是根据上述的原理,进行位与运算和移位操作,得到各项的时间
属性。

最后通过sprintf函数对各个属性按照固定的格式输出到字符串之中并返回。

首簇号,指的是这个文件储存在磁盘的第一个簇的簇号,也就是文件存放的具体地址。

同样地,需要对簇号的两个字节进行高低位交换。

最后一个是文件大小,需要对四个字节进行高低字节交换,得到文件大小。

在实验中,会通过read函数每次读入32个字节,即读取FAT表中的每一项,在输出文件信息时予以分析。

另外,每个目录中都包含两个虚拟目录,文件名分别为’.’和’..’,分别表示当前目录和上一级目录。

在目录的处理时需要对其进行判断,避免在进行子目录迭代显示时进入死循环。

综上所述,可以得出从文件段中读出文件信息的源码。

下面的是一些在读取过程中所使用的一些数据结构:
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;
};
这个文件信息链表的结点,相应地,在实验中定义了file_list_new_info方法,将文件信息添加到链表之中。

同时,为了避免递归调用,在实验中,通过一个队列的方式实现列出所有子目录文件的功能。

在下面代码中,content_char是一个指向储存上述文件结构的指针,content->size是file_content中表示文件大小的一个整型变量,用于计算文件夹中最大文件数量,newInfo是一个file_info结构体的指针,用于储存读取到的文件信息原始值。

先把一个文件信息的原始信息从文件内容中提取出来,为此,可以实现内存复制的函数,代码如下:
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;
}
通过这个函数把文件信息的原始信息复制到newInfo之中。

上述的文件夹结构不仅仅适用于根目录,所有的目录的遵循这种格式,所以这里可以得出一个初步的结论:文件夹是一种特殊的文件。

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;
for (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循环中的代码,先通过文件名判断这个文件是否存在,如果存在,则把文件信息添加到程序的文件信息链表之中。

再则判断是否是目录,如果是目录,则把这个目录添加到队列之中。

2.文件储存方式
FAT文件系统对空间的分配和管理是以簇为基本单位的。

所以,一个逻辑上连续的文件可能会被分散地储存在磁盘的各个位置。

操作系统输出文件时,遵循下面的步骤:
1. 会先通过文件夹信息找到文件首簇号。

2. 根据文件的首簇号,定位到FAT区相应位置;读出下一个簇的簇号。

3. 如果下一个簇的簇号不是结束标记(0xFFF),则会根据读出的下一个簇
号定位,读出簇里面的内容。

如果读出的是结束标记,则表示文件已经读
取完成。

假如一个文件被分散储存在0x012,0x022,0x302三个簇里。

从目录的信息中读出首簇号0x012,读出0x012簇里的内容;然后再通过0x012这个簇号在FAT区中找到下一个簇号0x022,读出0x022的内容;再通过0x022这个簇号找到下一个簇号0x302,读出0x302中的内容;再通过0x302读出下一个簇号的内容,此时,读出的簇号为0xFFF,即表示这个文件已经结束。

本实验中,读取文件的具体实现方法如下:
1. 通过一个链表,将这个文件的所有簇号储存起来。

2. 遍历储存簇号的链表,逐个逐个簇读取出来并储存到内存之中,返回之。

下面是读取文件的实现所需要的一些数据结构:
struct int_linked_list {
int data;
struct int_linked_list *next;
};
struct file_content {
struct int_linked_list *curList;
void *content;
int size;
char *filename;
};
其中,int_linked_list是一个储存整型的链表,file_content是一个用于保存读出文件内容和文件信息的结构体。

遍历链表的过程中,通过一个while循环实现,把读取到簇号添加到链表之中。

具体实现代码如下,tail为保存簇号链表的末尾结点指针,fp是用于读
取文件的文件指针,curConnt是一个用于统计文件簇数的变量,便于后续步骤
分配内存空间使用,下文同:
while ((clusterId = getNextClutserId(fp, clusterId)) != 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;
}
把簇号读取完毕以后,开始对文件内容进行读取,下面是文件内容读取的具体实现代码,下面代码中的content是一个指向用于存放文件内容的内存空
间的指针变量:
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, i++)
{
address = 0x00003E00 + (512 * ptr->data);
fseek(fp, address, SEEK_SET);
fread((void *)(((char *)(content->content)) + (512 * i)), 512, 1, fp);
}
在for循环的第一句代码之中,通过簇号对簇所在的地址进行计算,把地址值储存到address变量之中;第二句代码则是通过上一步计算得到的address
变量对文件指针进行定位,第三句是通过fread方法把文件内容读入到内存之
中。

六、实验结论
1. FAT12文件系统中,把磁盘划分成引导区、FAT区、FAT备份区、根目录
区和文件数据区。

2. 除了根目录以外,文件系统把每个文件夹都当成是一个特殊的文件进
行处理。

3. FAT12文件系统通过簇进行空间的管理和分配。

七、完整实验代码
/*
* 操作系统课程实验
* FAT12 文件系统实验代码
*
* 虽然这个程序在Windows 和Linux 环境下都能运行。

* 不过,在Windows 环境下运行的话,显示文件内容的时候,内容的末尾会有几个奇怪的字符。

* Linux 环境下完全没问题
* 暂时推测是Windows 控制台的原因,Windows 控制台会把一些非字符的ASCII 显示为奇怪的字符,
* 例如,0x0A 会显示成一个笑脸,Linux 的控制台下不会对这些非字符的ASCII 进行处理
*
* 我是今天早上才发现这个问题的阿(╯‵□′)╯︵┻━┻
*
* 注意:编译前,需要把IMAGE_FILE 那个宏定义改成公邮上面的那个IMG 文件;
* Linux 下打开这个源码文件注释会变成乱码
*
*/
// 这个定义只是为了程序能在VS2013 下面正常编译而已
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#endif
#define OK 0x00000000
#define MESSAGE_FILE_NOT_FOUND 0xE0000404
#define ERROR_MALLOC_FAILED 0xF0000001
#define ERROR_IO_ERROR 0xF0000002
// ↓这里改路径↓
#define IMAGE_FILE "/home/user/DOS622.IMG"
// ↑这里改路径↑
/******************** 这里是结构体的定义**************************/
// 这里是文件信息
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_info {
char *filename;
int fileBeginIndex, fileEndIndex;
struct file_info_node *beginFile, *endFile;
struct folder_info *next;
};
// 这里是一个队列,用于迭代方式遍历文件系统的一个中间变量
struct queue_info {
char *filename;
int offset, size, cluster;
struct queue_info *next;
};
// 一个整数链表结构
struct int_linked_list {
int data;
struct int_linked_list *next;
};
// 这里是一个文件结构,表示内容,可以读取文件的其中一段,也可以通过簇的方式完整读入整个文件
struct file_content {
struct int_linked_list *curList;
void *content;
int size;
char *filename;
};
/******************** 这里是全局变量的定义**************************/ struct file_info_node *file_list_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' };
/******************** 这里是函数的定义**************************/
int 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_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, 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 *formatIndex(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);
/******************** 主函数**************************/
int main(int argc, 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);
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)
{
printf("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 == NULL)
{
return ERROR_IO_ERROR;
}
// 判断是否对根目录进行读取
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);
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 = (char *)content->content;
int newId = -1, fileCount = 0;
if (node == NULL)
{
return ERROR_MALLOC_FAILED;
}
node->filename = info->filename;
// 根据大小计算目录中的文件数量
int maxFile = content->size / 32, i;
for (i = 0; i < maxFile; i++)
{
newInfo = (struct file_info *)malloc(sizeof(struct file_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);
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(buffer, 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 *src, 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_info *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)
{
newNode->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 = folder_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 = 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 == 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 = 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;
}
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;
retValue->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 isFolder, 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 == 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_list));
tail->next->data = clusterId;
tail->next->next = NULL;
tail = tail->next;
}
// 第二步:开始根据簇号读取
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, 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 *errCode)
{
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->fileEndIndex)
{
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(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("");
}
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);
}
void 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("--------------------------------------------------------------------------\n");
printf(" Folder : %s\n", ptr->filename);
printf("--------------------------------------------------------------------------\n");
printf(" Num | File Name | Type | CLUSTNO | File Change Time | Size \n");
printf("--------------------------------------------------------------------------\n");
index = ptr->fileBeginIndex;
node = ptr->beginFile;
while (node != NULL && node->id <= ptr->fileEndIndex)
{
// 只是实现不同平台下的变色操作
#ifdef _WIN32
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,
((node->info->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) ? " <DIR>" : formatSize(node->info->size, 1));
totalSize += node->info->size;
count++;
node = node->next;
}
printf("--------------------------------------------------------------------------\n");
printf(" %d Files, %s\n", count, formatSize(totalSize, 0));
}
}
void print_file_content(struct file_content *content)
{
if (content == NULL)
{
return;
}
printf("--------------------------------------------------------------------------\n");
printf(" File Content : %s\n", content->filename);
printf("--------------------------------------------------------------------------\n");
int i;
for (i = 0; i < content->size; i++)
{
printf("%c", *((char *)(((char *)content->content) + i)));
}
printf("--------------------------------------------------------------------------\n"); }
char *formatIndex(int i)
{
char *result = (char *)malloc(sizeof(char)* 4);
result[0] = '0' + (i / 100);
result[1] = '0' + ((i / 10) % 10);
result[2] = '0' + (i % 10);
result[3] = '\0';
return result;
}
char *formatClustNo(int i)
{
char *result = (char *)malloc(sizeof(char)* 7);
result[0] = '0';
result[1] = 'x';
result[2] = decToHex[(i & 0x0000F000) >> 12];
result[3] = decToHex[(i & 0x00000F00) >> 8];
result[4] = decToHex[(i & 0x000000F0) >> 4];
result[5] = decToHex[(i & 0x0000000F) >> 0];
result[6] = '\0';
return result;
}
char *formatFileName(char *filename, char *ext)
{
int i = 0, fni = 0, exti = 0;
char *result = (char *)malloc(sizeof(char)* 13);
while (fni < 8 && filename[fni] != 0x20) {
result[i++] = filename[fni++];
}
result[i++] = '.';
while (exti < 3 && ext[exti] != 0x20) {
result[i++] = ext[exti++];
}
while (i < 12) {
result[i++] = 0x20;
}
result[i] = '\0';
return result;
}
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) ? 'l' : '-';
result[4] = ((attribute & 0x10) == 0x10) ? 'd' : '-';
result[5] = ((attribute & 0x20) == 0x20) ? 'f' : '-';
result[6] = '\0';
return result;
}
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 = ((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;
}
char *formatSize(int size, int rightAlign)
{
char *buffer = (char *)malloc(sizeof(char)* 11);
char *desc = NULL;
int len, i;
if (size == 0)
{
sprintf(buffer, "0");
}
else if (size > 0 && size < 1024)
{
sprintf(buffer, "%d B", size);
}
else if (size >= 1024 && size < 1048576)
{
sprintf(buffer, "%.2f KB", size / 1024.0);
}
else if (size >= 1048576 && size < 1073741824)
{
sprintf(buffer, "%.2f MB", size / 1048576.0);
}
else if (size >= 1073741824)
{
sprintf(buffer, "%.2f GB", size / 1073741824.0);
}
if (rightAlign) {
desc = (char *)malloc(sizeof(char)* 11);
len = strlen(buffer);
desc[10] = '\0';
for (i = 9; i >= 0; i--, len--)
{
desc[i] = len - 1 >= 0 ? buffer[len - 1] : ' ';
}
free(buffer);
return desc;
}
else
{
return buffer;
}
}。

相关文档
最新文档