📄 fat16.c
字号:
fd->pos += write_length;
if(first_cluster_offset + write_length >= Cluster_Size)
{
/* we are on a cluster boundary, so get the next cluster */
u16 cluster_num_next = Fat16_Get_Next_Cluster(fd->fs, cluster_num);
if(!cluster_num_next && buffer_left > 0)
/* we reached the last cluster, append a new one */
cluster_num_next = Fat16_Append_Clusters(fd->fs, cluster_num, 1);
if(!cluster_num_next)
{
fd->pos_cluster = 0;
break;
}
cluster_num = cluster_num_next;
first_cluster_offset = 0;
}
fd->pos_cluster = cluster_num;
} while(buffer_left > 0); /* check if we are done */
/* update directory entry */
if(fd->pos > fd->dir_entry.File_Size)
{
u32 size_old = fd->dir_entry.File_Size;
/* update file size */
fd->dir_entry.File_Size = fd->pos;
/* write directory entry */
if(!Fat16_Write_Dir_Entry(fd->fs, &fd->dir_entry))
{
/* We do not return an error here since we actually wrote
* some data to disk. So we calculate the amount of data
* we wrote to disk and which lies within the old file size.
*/
buffer_left = fd->pos - size_old;
fd->pos = size_old;
}
}
return buffer_len - buffer_left;
#else
return -1;
#endif
}
/**********************************************************************
* 函数 Fat16_Seek_File --- 从新定位文件游标。
* Repositions the read/write file offset.
*
* Changes the file offset where the next call to fat16_read_file()
* or fat16_write_file() starts reading/writing.
*
* If the new offset is beyond the end of the file, Fat16_Resize_File()
* is implicitly called, i.e. the file is expanded.
*
* The new offset can be given in different ways determined by
* the \c whence parameter:
* - \b FAT16_SEEK_SET: \c *offset is relative to the beginning of the file.
* - \b FAT16_SEEK_CUR: \c *offset is relative to the current file position.
* - \b FAT16_SEEK_END: \c *offset is relative to the end of the file.
*
* The resulting absolute offset is written to the location the \c offset
* parameter points to.
*
* \param[in] fd The file decriptor of the file on which to seek.
* \param[in,out] offset A pointer to the new offset, as affected by the \c whence
* parameter. The function writes the new absolute offset
* to this location before it returns.
* \param[in] whence Affects the way \c offset is interpreted, see above.
* \returns 0 on failure, 1 on success.
**********************************************************************/
u8
Fat16_Seek_File(struct Fat16_File_Struct* fd, s32* offset, u8 whence)
{
if(!fd || !offset)
return 0;
u32 new_pos = fd->pos;
switch(whence)
{
case FAT16_SEEK_SET:
new_pos = *offset;
break;
case FAT16_SEEK_CUR:
new_pos += *offset;
break;
case FAT16_SEEK_END:
new_pos = fd->dir_entry.File_Size + *offset;
break;
default:
return 0;
}
if(new_pos > fd->dir_entry.File_Size && !Fat16_Resize_File(fd, new_pos))
return 0;
fd->pos = new_pos;
fd->pos_cluster = 0;
*offset = new_pos;
return 1;
}
/**********************************************************************
* 函数 Fat16_Resize_File --- 调整文件大小。
* 仅分配文件磁盘空间,不清除数据,如需清楚,请手动清楚数据
* 输入参数 fd:The file decriptor of the file which to resize
* size:The new size of the file
* 返回值 0 --- 失败
* 1 --- 成功
**********************************************************************/
u8
Fat16_Resize_File(struct Fat16_File_Struct* fd, u32 size)
{
#if FAT16_WRITE_SUPPORT
if(!fd)
return 0;
u16 cluster_num = fd->dir_entry.Cluster;
u16 Cluster_Size = fd->fs->header.Cluster_Size;
u32 size_new = size;
do
{
if(cluster_num == 0 && size_new == 0)
/* the file stays empty */
break;
/* seek to the next cluster as long as we need the space */
while(size_new > Cluster_Size)
{
/* get next cluster of file */
u16 cluster_num_next = Fat16_Get_Next_Cluster(fd->fs, cluster_num);
if(cluster_num_next)
{
cluster_num = cluster_num_next;
size_new -= Cluster_Size;
}
else
{
break;
}
}
if(size_new > Cluster_Size || cluster_num == 0)
{
/* Allocate new cluster chain and append
* it to the existing one, if available.
*/
u16 cluster_count = size_new / Cluster_Size;
if((u32) cluster_count * Cluster_Size < size_new)
++cluster_count;
u16 cluster_new_chain = Fat16_Append_Clusters(fd->fs, cluster_num, cluster_count);
if(!cluster_new_chain)
return 0;
if(!cluster_num)
{
cluster_num = cluster_new_chain;
fd->dir_entry.Cluster = cluster_num;
}
}
/* write new directory entry */
fd->dir_entry.File_Size = size;
if(size == 0)
fd->dir_entry.Cluster = 0;
if(!Fat16_Write_Dir_Entry(fd->fs, &fd->dir_entry))
return 0;
if(size == 0)
{
/* free all clusters of file */
Fat16_Free_Clusters(fd->fs, cluster_num);
}
else if(size_new <= Cluster_Size)
{
/* free all clusters no longer needed */
Fat16_Terminate_Clusters(fd->fs, cluster_num);
}
} while(0);
/* correct file position */
if(size < fd->pos)
{
fd->pos = size;
fd->pos_cluster = 0;
}
return 1;
#else
return 0;
#endif
}
/**********************************************************************
* 函数 Fat16_Open_Dir --- 打开路径。
*
* 输入参数 fd:The filesystem on which the directory to open resides
* dir_entry:The directory entry which stands for the directory to open
* 返回值 0 --- 失败
* 或者打开路径信息
**********************************************************************/
struct Fat16_Dir_Struct*
Fat16_Open_Dir(struct Fat16_FS_Struct* fs, const struct Fat16_Dir_Entry_Struct* dir_entry)
{
if(!fs || !dir_entry || !(dir_entry->Attributes & FAT16_ATTRIB_DIR))
return 0;
#if USE_DYNAMIC_MEMORY
struct Fat16_Dir_Struct* dd = malloc(sizeof(*dd));
if(!dd)
return 0;
#else
struct Fat16_Dir_Struct* dd = fat16_dir_handlers;
u8 i;
for(i = 0; i < FAT16_DIR_COUNT; ++i)
{
if(!dd->fs)
break;
++dd;
}
if(i >= FAT16_DIR_COUNT)
return 0;
#endif
memcpy(&dd->dir_entry, dir_entry, sizeof(*dir_entry));
dd->fs = fs;
dd->entry_next = 0;
return dd;
}
/**********************************************************************
* 函数 Fat16_Close_Dir --- 关闭已打开的路径
*
* 输入参数 dd:The directory descriptor to close.
* 返回值 无
**********************************************************************/
void
Fat16_Close_Dir(struct Fat16_Dir_Struct* dd)
{
if(dd)
#if USE_DYNAMIC_MEMORY
free(dd);
#else
dd->fs = 0;
#endif
}
/**********************************************************************
* 函数 Fat16_Read_Dir --- 读取下一个路径。
*
* 输入参数 dd:父路径
* 输出参数 dir_entry:读取的下一个路径
* 返回值 0 --- 失败
* 1 --- 成功
**********************************************************************/
u8
Fat16_Read_Dir(struct Fat16_Dir_Struct* dd, struct Fat16_Dir_Entry_Struct* dir_entry)
{
if(!dd || !dir_entry)
return 0;
if(dd->dir_entry.Cluster == 0)
{
/* read entry from root directory */
if(Fat16_Read_Root_Dir_Entry(dd->fs, dd->entry_next, dir_entry))
{
++dd->entry_next;
return 1;
}
}
else
{
/* read entry from a subdirectory */
if(Fat16_Read_Sub_Dir_Entry(dd->fs, dd->entry_next, &dd->dir_entry, dir_entry))
{
++dd->entry_next;
return 1;
}
}
/* restart reading */
dd->entry_next = 0;
return 0;
}
/**********************************************************************
* 函数 Fat16_Reset_Dir --- 重置目录句柄。
* Resets the directory handle such that reading restarts
* with the first directory entry.
*
* 输入参数 dd:The directory handle to reset
* 返回值 0 --- 失败
* 1 --- 成功
**********************************************************************/
u8
Fat16_Reset_Dir(struct Fat16_Dir_Struct* dd)
{
if(!dd)
return 0;
dd->entry_next = 0;
return 1;
}
/**********************************************************************
* 函数 Fat16_Find_Offset_For_Dir_Entry --- 寻找新路径的储存空间
* Searches for space where to store a directory entry.
*
* 输入参数 fs:The filesystem on which to operate
* dir_entry:The directory entry for which to search space
* 返回值 0 --- 失败
* 或者 a device offset on success
**********************************************************************/
u32
Fat16_Find_Offset_For_Dir_Entry(const struct Fat16_FS_Struct* fs,
const struct Fat16_Dir_Struct* parent,
const struct Fat16_Dir_Entry_Struct* dir_entry)
{
#if FAT16_WRITE_SUPPORT
if(!fs || !dir_entry)
return 0;
/* search for a place where to write the directory entry to disk */
u8 free_dir_entries_needed = (strlen(dir_entry->Long_Name) + 12) / 13 + 1;
u8 free_dir_entries_found = 0;
u16 cluster_num = parent->dir_entry.Cluster;
u32 Dir_Entry_Offset = 0;
u32 offset = 0;
u32 offset_to = 0;
if(cluster_num == 0)
{
/* we read/write from the root directory entry */
offset = fs->header.Root_Dir_Offset;
offset_to = fs->header.Cluster_Zero_Offset;
Dir_Entry_Offset = offset;
}
while(1)
{
if(offset == offset_to)
{
if(cluster_num == 0)
/* We iterated through the whole root directory entry
* and could not find enough space for the directory entry.
*/
return 0;
if(offset)
{
/* We reached a cluster boundary and have to
* switch to the next cluster.
*/
u16 cluster_next = Fat16_Get_Next_Cluster(fs, cluster_num);
if(!cluster_next)
{
cluster_next = Fat16_Append_Clusters(fs, cluster_num, 1);
if(!cluster_next)
return 0;
/* we appended a new cluster and know it is free */
Dir_Entry_Offset = fs->header.Cluster_Zero_Offset +
(u32) (cluster_next - 2) * fs->header.Cluster_Size;
/* clear cluster to avoid garbage directory entries */
Fat16_Clear_Cluster(fs, cluster_next);
break;
}
cluster_num = cluster_next;
}
offset = fs->header.Cluster_Zero_Offset +
(u32) (cluster_num - 2) * fs->header.Cluster_Size;
offset_to = offset + fs->header.Cluster_Size;
Dir_Entry_Offset = offset;
free_dir_entries_found = 0;
}
/* read next lfn or 8.3 entry */
u8 first_char;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -