📄 fat16.c
字号:
struct Fat16_Read_CallBack_Arg arg;
while(1)
{
/* calculate new Cluster offset */
cluster_offset = fs->header.Cluster_Zero_Offset + (u32) (cluster_num - 2) * Cluster_Size;
/* seek to the n-th entry */
memset(&arg, 0, sizeof(arg));
arg.Entry_Num = Entry_Num;
if(!fs->partition->device_read_interval(cluster_offset,
buffer,
sizeof(buffer),
Cluster_Size,
Fat16_Dir_Entry_Seek_CallBack,
&arg)
)
return 0;
/* check if we found the entry */
if(arg.Entry_Offset)
break;
/* get number of next cluster */
if(!(cluster_num = Fat16_Get_Next_Cluster(fs, cluster_num)))
return 0; /* directory entry not found */
}
memset(dir_entry, 0, sizeof(*dir_entry));
/* read entry */
if(!fs->partition->device_read_interval(arg.Entry_Offset,
buffer,
sizeof(buffer),
arg.Byte_Count,
Fat16_Dir_Entry_Read_CallBack,
dir_entry))
return 0;
return dir_entry->Long_Name[0] != '\0' ? 1 : 0;
}
/**********************************************************************
* 回调函数 Fat16_Dir_Entry_Seek_CallBack --- 扫描下级子目录列表的
* 输入参数 buffer:缓存
* offset:偏移地址
* p:指针
* 输出参数 无
* 返回值 0 --- 失败
* 1 --- 成功
**********************************************************************/
u8
Fat16_Dir_Entry_Seek_CallBack(u8* buffer, u32 offset, void* p)
{
struct Fat16_Read_CallBack_Arg* arg = p;
/* skip deleted or empty entries */
if(buffer[0] == FAT16_DIRENTRY_DELETED || !buffer[0])
return True;
if(arg->Entry_Cur == arg->Entry_Num)
{
arg->Entry_Offset = offset;
arg->Byte_Count = buffer[11] == 0x0f ?
((buffer[0] & FAT16_DIRENTRY_LFNSEQMASK) + 1) * 32 :
32;
return False;
}
/* if we read a 8.3 entry, we reached a new directory entry */
if(buffer[11] != 0x0f)
++arg->Entry_Cur;
return True;
}
/**********************************************************************
* 回调函数 Fat16_Dir_Entry_Read_CallBack --- 读取目录
* 输入参数 buffer:缓存
* offset:偏移地址
* p:指针
* 输出参数 无
* 返回值 0 --- 失败
* 1 --- 成功
**********************************************************************/
u8
Fat16_Dir_Entry_Read_CallBack(u8* buffer, u32 offset, void* p)
{
struct Fat16_Dir_Entry_Struct* dir_entry = p;
/* there should not be any deleted or empty entries */
if(buffer[0] == FAT16_DIRENTRY_DELETED || !buffer[0])
return False;
if(!dir_entry->Entry_Offset)
dir_entry->Entry_Offset = offset;
switch(Fat16_Interpret_Dir_Entry(dir_entry, buffer))
{
case 0: /* failure */
return False;
case 1: /* buffer successfully parsed, continue */
return True;
case 2: /* directory entry complete, finish */
return False;
}
return False;
}
/**********************************************************************
* 函数 Fat16_Interpret_Dir_Entry ---
* Interprets a raw directory entry and puts the contained
* information into the directory entry.
*
* For a single file there may exist multiple directory
* entries. All except the last one are lfn entries, which
* contain parts of the long filename. The last directory
* entry is a traditional 8.3 style one. It contains all
* other information like size, cluster, date and time.
*
* 输入参数 raw_entry:A pointer to 32 bytes of raw data.
* 输出参数 dir_entry:The directory entry to fill
* 返回值 0 --- 失败
* 1 --- 成功
**********************************************************************/
u8
Fat16_Interpret_Dir_Entry(struct Fat16_Dir_Entry_Struct* dir_entry, const u8* raw_entry)
{
if(!dir_entry || !raw_entry || !raw_entry[0])
return 0;
char* Long_Name = dir_entry->Long_Name;
if(raw_entry[11] == 0x0f)
{
u16 char_offset = ((raw_entry[0] & 0x3f) - 1) * 13;
if(char_offset + 12 < sizeof(dir_entry->Long_Name))
{
/* Lfn supports unicode, but we do not, for now.
* So we assume pure ascii and read only every
* second byte.
*/
Long_Name[char_offset + 0] = raw_entry[1];
Long_Name[char_offset + 1] = raw_entry[3];
Long_Name[char_offset + 2] = raw_entry[5];
Long_Name[char_offset + 3] = raw_entry[7];
Long_Name[char_offset + 4] = raw_entry[9];
Long_Name[char_offset + 5] = raw_entry[14];
Long_Name[char_offset + 6] = raw_entry[16];
Long_Name[char_offset + 7] = raw_entry[18];
Long_Name[char_offset + 8] = raw_entry[20];
Long_Name[char_offset + 9] = raw_entry[22];
Long_Name[char_offset + 10] = raw_entry[24];
Long_Name[char_offset + 11] = raw_entry[28];
Long_Name[char_offset + 12] = raw_entry[30];
}
return 1;
}
else
{
/* if we do not have a long name, take the short one */
if(Long_Name[0] == '\0')
{
u8 i;
for(i = 0; i < 8; ++i)
{
if(raw_entry[i] == ' ')
break;
Long_Name[i] = raw_entry[i];
}
if(Long_Name[0] == 0x05)
Long_Name[0] = (char) FAT16_DIRENTRY_DELETED;
if(raw_entry[8] != ' ')
{
Long_Name[i++] = '.';
u8 j = 8;
for(; j < 11; ++j)
{
if(raw_entry[j] != ' ')
{
Long_Name[i++] = raw_entry[j];
}
else
{
break;
}
}
}
Long_Name[i] = '\0';
}
/* extract properties of file and store them within the structure */
dir_entry->Attributes = raw_entry[11];
dir_entry->Cluster = ((u16) raw_entry[26]) |
((u16) raw_entry[27] << 8);
dir_entry->File_Size = ((u32) raw_entry[28]) |
((u32) raw_entry[29] << 8) |
((u32) raw_entry[30] << 16) |
((u32) raw_entry[31] << 24);
#if FAT16_DATETIME_SUPPORT
dir_entry->modification_time = ((u16) raw_entry[22]) |
((u16) raw_entry[23] << 8);
dir_entry->modification_date = ((u16) raw_entry[24]) |
((u16) raw_entry[25] << 8);
#endif
return 2;
}
}
/**********************************************************************
* 函数 Fat16_Get_Dir_Entry_Of_Path --- 根据路径查找对应的目录项信息。
* The given path may both describe a file or a directory.
*
* 输入参数 fs: The FAT16 filesystem on which to search.
* path: The path of which to read the directory entry.
* 输出参数 dir_entry:The directory entry to fill
* 返回值 0 --- 失败
* 1 --- 成功
**********************************************************************/
u8
Fat16_Get_Dir_Entry_Of_Path(struct Fat16_FS_Struct* fs,
const char* path,
struct Fat16_Dir_Entry_Struct* dir_entry)
{
if(!fs || !path || path[0] == '\0' || !dir_entry)
return 0;
if(path[0] == '/')
++path;
/* begin with the root directory */
memset(dir_entry, 0, sizeof(*dir_entry));
dir_entry->Attributes = FAT16_ATTRIB_DIR;
if(path[0] == '\0')
return 1;
while(1)
{
struct Fat16_Dir_Struct* dd = Fat16_Open_Dir(fs, dir_entry);
if(!dd)
break;
/* extract the next hierarchy we will search for */
const char* sep_pos = strchr(path, '/');
if(!sep_pos)
sep_pos = path + strlen(path);
u8 length_to_sep = sep_pos - path;
/* read directory entries */
while(Fat16_Read_Dir(dd, dir_entry))
{
/* check if we have found the next hierarchy */
if((strlen(dir_entry->Long_Name) != length_to_sep ||
strncmp(path, dir_entry->Long_Name, length_to_sep) != 0))
continue;
Fat16_Close_Dir(dd);
dd = 0;
if(path[length_to_sep] == '\0')
/* we iterated through the whole path and have found the file */
return 1;
if(dir_entry->Attributes & FAT16_ATTRIB_DIR)
{
/* we found a parent directory of the file we are searching for */
path = sep_pos + 1;
break;
}
/* a parent of the file exists, but not the file itself */
return 0;
}
Fat16_Close_Dir(dd);
}
return 0;
}
/**********************************************************************
* 函数 Fat16_Get_Next_Cluster --- 查找下一个族。
* Using the filesystem file allocation table, this function returns
* the number of the cluster containing the data directly following
* the data within the cluster with the given number.
*
* 输入参数 fs: The filesystem for which to determine the next cluster
* cluster_num: The number of the cluster for which to determine its successor.
* 返回值 0 --- 失败
* 或者 --- The wanted cluster number
**********************************************************************/
u16
Fat16_Get_Next_Cluster(const struct Fat16_FS_Struct* fs, u16 cluster_num)
{
if(!fs || cluster_num < 2)
return 0;
/* read appropriate fat entry */
u8 fat_entry[2];
if(!fs->partition->device_read(fs->header.Fat_Offset + 2 * cluster_num, fat_entry, 2))
return 0;
/* determine next cluster from fat */
cluster_num = ((u16) fat_entry[0]) |
((u16) fat_entry[1] << 8);
if( cluster_num == FAT16_CLUSTER_FREE ||
cluster_num == FAT16_CLUSTER_BAD ||
(cluster_num >= FAT16_CLUSTER_RESERVED_MIN && cluster_num <= FAT16_CLUSTER_RESERVED_MAX) ||
(cluster_num >= FAT16_CLUSTER_LAST_MIN /* && cluster_num <= FAT16_CLUSTER_LAST_MAX */)
)
return 0;
return cluster_num;
}
/**********************************************************************
* 函数 Fat16_Append_Clusters --- 附加一个新族。
* Appends a new cluster chain to an existing one.
*
* Set cluster_num to zero to create a completely new one.
*
* \param[in] fs The file system on which to operate.
* \param[in] cluster_num The cluster to which to append the new chain.
* \param[in] count The number of clusters to allocate.
* \returns 0 on failure, the number of the first new cluster on success.
**********************************************************************/
u16
Fat16_Append_Clusters(const struct Fat16_FS_Struct* fs, u16 cluster_num, u16 count)
{
#if FAT16_WRITE_SUPPORT
if(!fs)
return 0;
device_read_t device_read = fs->partition->device_read;
device_write_t device_write = fs->partition->device_write;
u32 Fat_Offset = fs->header.Fat_Offset;
u16 cluster_max = fs->header.Fat_Size / 2;
u16 cluster_next = 0;
u16 count_left = count;
u8 buffer[2];
for(u16 cluster_new = 0; cluster_new < cluster_max; ++cluster_new)
{
if(!device_read(Fat_Offset + 2 * cluster_new, buffer, sizeof(buffer)))
return 0;
/* check if this is a free cluster */
if(buffer[0] == (FAT16_CLUSTER_FREE & 0xff) &&
buffer[1] == ((FAT16_CLUSTER_FREE >> 8) & 0xff))
{
/* allocate cluster */
if(count_left == count)
{
buffer[0] = FAT16_CLUSTER_LAST_MAX & 0xff;
buffer[1] = (FAT16_CLUSTER_LAST_MAX >> 8) & 0xff;
}
else
{
buffer[0] = cluster_next & 0xff;
buffer[1] = (cluster_next >> 8) & 0xff;
}
if(!device_write(Fat_Offset + 2 * cluster_new, buffer, sizeof(buffer)))
break;
cluster_next = cluster_new;
if(--count_left == 0)
break;
}
}
do
{
if(count_left > 0)
break;
/* We allocated a new cluster chain. Now join
* it with the existing one.
*/
if(cluster_num >= 2)
{
buffer[0] = cluster_next & 0xff;
buffer[1] = (cluster_next >> 8) & 0xff;
if(!device_write(Fat_Offset + 2 * cluster_num, buffer, sizeof(buffer)))
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -