📄 smf_fat.c
字号:
cluster = h_file & 0xffff;
id = (h_file >> 16) & 0xff;
s_smErr = sm_PreFAT(drv_no);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
s_smErr = sm_GetOpenedList(drv_no, cluster, id, &p_list);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
*p_read_count = 0;
/*
* head_count: read size before the cache area
* cache_count: read size in the cache area
* tail_count: read size after the cache area
*/
head_count = tail_count = 0;
#ifndef WRITE_CACHE_DISABLE
cache_count = 0;
#endif
remaining_count = count;
#ifndef WRITE_CACHE_DISABLE
if (p_list->cache.count)
{
/* p_list->f_ptr is before the cache area */
if (p_list->f_ptr < p_list->cache.f_ptr)
{
head_count = (p_list->cache.f_ptr - p_list->f_ptr > remaining_count)
? remaining_count : (p_list->cache.f_ptr - p_list->f_ptr);
remaining_count -= head_count;
if (remaining_count > 0)
{
cache_count = (p_list->cache.count > remaining_count) ? remaining_count : p_list->cache.count;
remaining_count -= cache_count;
tail_count = remaining_count;
}
}
/* p_list->f_ptr is in the cache area */
else if (p_list->f_ptr < p_list->cache.f_ptr + p_list->cache.count)
{
cache_count = (p_list->cache.count - (p_list->f_ptr - p_list->cache.f_ptr) > remaining_count)
? remaining_count : (p_list->cache.count - (p_list->f_ptr - p_list->cache.f_ptr));
remaining_count -= cache_count;
tail_count = remaining_count;
}
/* p_list->f_ptr is after the cache area */
else
{
tail_count = remaining_count;
}
}
else
{
head_count = remaining_count;
}
#else
head_count = remaining_count;
#endif
read_sum = 0;
if (head_count)
{
s_smErr = sm_ReadFromDisk(drv_no, p_list, p_buf, head_count, &read_result);
if ((s_smErr != SM_OK) && (s_smErr != ERR_EOF))
FAT_RETURN(drv_no, s_smErr);
read_sum += read_result;
}
#ifndef WRITE_CACHE_DISABLE
if (cache_count)
{
udword cluster_size;
udword walked_cluster_count;
offset = p_list->f_ptr - p_list->cache.f_ptr;
SM_MEMCPY((char*)p_buf + head_count, p_list->cache.p_buf + offset, cache_count);
/* update current cluster */
cluster_size = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster * SECTOR_SIZE;
walked_cluster_count = (p_list->f_ptr % cluster_size + cache_count) / cluster_size;
if (walked_cluster_count > 0)
{
while (walked_cluster_count-- > 0)
{
p_list->old_cur_cluster = p_list->cur_cluster;
p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
if (p_list->cur_cluster == LAST_CLUSTER)
FAT_RETURN(drv_no, ERR_INTERNAL);
}
}
p_list->f_ptr += cache_count;
read_sum += cache_count;
}
#endif
if (tail_count)
{
#ifndef WRITE_CACHE_DISABLE
s_smErr = sm_ReadFromDisk(drv_no, p_list, (ubyte*)p_buf + head_count + cache_count, tail_count, &read_result);
#else
s_smErr = sm_ReadFromDisk(drv_no, p_list, (ubyte*)p_buf + head_count, tail_count, &read_result);
#endif
if ((s_smErr != SM_OK) && (s_smErr != ERR_EOF))
FAT_RETURN(drv_no, s_smErr);
read_sum += read_result;
}
*p_read_count = read_sum;
if (count > read_sum)
FAT_RETURN(drv_no, ERR_EOF);
FAT_RETURN(drv_no, s_smErr);
}
/**********
* Function: smWriteFile
* Remarks:
* - write the contents of the p_buf to the file
* Parameters
* . h_file: handle of opened file
* . p_buf: writing contents
* . count: amount of writing contents
**********/
SM_EXPORT ERR_CODE smWriteFile(F_HANDLE h_file, const void* p_buf, udword count)
{
udword drv_no;
udword cluster;
const ubyte* p_write;
udword write_count;
sOPENED_LIST* p_list;
udword id;
drv_no = (h_file >> 24) & 0x7f;
if (drv_no >= MAX_DRIVE)
return ERR_INVALID_PARAM;
cluster = h_file & 0xffff;
id = (h_file >> 16) & 0xff;
p_write = (const ubyte*)p_buf;
write_count = count;
s_smErr = sm_PreFAT(drv_no);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
s_smErr = sm_GetOpenedList(drv_no, cluster, id, &p_list);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
if (!(p_list->mode & OPEN_W))
FAT_RETURN(drv_no, ERR_NOT_PERMITTED);
#ifndef WRITE_CACHE_DISABLE
if ((p_list->cache.count != 0) && (p_list->f_ptr != p_list->cache.f_ptr + p_list->cache.count))
{
sm_WriteCacheToDisk(drv_no, p_list);
}
if (p_list->cache.count + write_count < s_cacheSize[drv_no])
{
udword cluster_size;
udword walked_cluster_count;
SM_MEMCPY(p_list->cache.p_buf + p_list->cache.count, p_write, write_count);
p_list->cache.count += write_count;
/* update current cluster */
cluster_size = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster * SECTOR_SIZE;
walked_cluster_count = (p_list->f_ptr % cluster_size + write_count) / cluster_size;
if (walked_cluster_count > 0)
{
while (walked_cluster_count-- > 0)
{
p_list->old_cur_cluster = p_list->cur_cluster;
p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
}
}
p_list->f_ptr += write_count;
if (p_list->size < p_list->f_ptr)
p_list->size = p_list->f_ptr;
}
else
{
s_smErr = sm_WriteCacheToDisk(drv_no, p_list);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
s_smErr = sm_WriteToDisk(drv_no, p_list, p_write, write_count);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
p_list->cache.f_ptr = p_list->f_ptr;
}
FAT_RETURN(drv_no, SM_OK);
#else
s_smErr = sm_WriteToDisk(drv_no, p_list, p_write, write_count);
FAT_RETURN(drv_no, s_smErr);
#endif
}
/**********
* Function: smSeekFile
* Remarks:
* - moves the file pointer
* Parameters
* . h_file: handle of opened file
* . seek_mode: FROM_CURRENT, FROM_BEGIN, FROM_END
* . offset: amount of movement
* . p_old_offset (result): file pointer before it is moved
**********/
SM_EXPORT ERR_CODE smSeekFile(F_HANDLE h_file, udword seek_mode, dword offset, dword* p_old_offset)
{
udword drv_no;
udword cluster;
sOPENED_LIST* p_list;
udword id;
udword cluster_size;
drv_no = (h_file >> 24) & 0x7f;
if (drv_no >= MAX_DRIVE)
return ERR_INVALID_PARAM;
cluster_size = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster * SECTOR_SIZE;
cluster = h_file & 0xffff;
id = (h_file >> 16) & 0xff;
s_smErr = sm_PreFAT(drv_no);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
s_smErr = sm_GetOpenedList(drv_no, cluster, id, &p_list);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
*p_old_offset = p_list->f_ptr;
if (seek_mode == FROM_CURRENT)
{
if (offset >= 0)
{
udword walked_cluster_count;
/* update current cluster */
walked_cluster_count = (p_list->f_ptr % cluster_size + offset) / cluster_size;
if (walked_cluster_count > 0)
{
while (walked_cluster_count-- > 0)
{
p_list->old_cur_cluster = p_list->cur_cluster;
p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
}
}
p_list->f_ptr += offset;
if (p_list->f_ptr > p_list->size)
p_list->f_ptr = p_list->size;
}
else
{
udword i;
if (p_list->f_ptr > (udword)(-offset))
p_list->f_ptr += offset;
else
p_list->f_ptr= 0;
/* update current cluster */
p_list->cur_cluster = p_list->cluster;
p_list->old_cur_cluster = 0;
for (i = cluster_size; i <= p_list->f_ptr; i += cluster_size)
{
p_list->old_cur_cluster = p_list->cur_cluster;
p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
}
}
}
else if (seek_mode == FROM_BEGIN)
{
udword i;
if (offset >= 0)
{
p_list->f_ptr = offset;
if (p_list->f_ptr > p_list->size)
p_list->f_ptr = p_list->size;
}
else
p_list->f_ptr = 0;
/* update current cluster */
p_list->cur_cluster = p_list->cluster;
p_list->old_cur_cluster = 0;
for (i = cluster_size; i <= p_list->f_ptr; i += cluster_size)
{
p_list->old_cur_cluster = p_list->cur_cluster;
p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
}
}
else if (seek_mode == FROM_END)
{
udword i;
if (offset >= 0)
p_list->f_ptr = p_list->size;
else
{
if (p_list->size < (udword)(-offset))
p_list->f_ptr = 0;
else
p_list->f_ptr = p_list->size + offset;
}
/* update current cluster */
p_list->cur_cluster = p_list->cluster;
p_list->old_cur_cluster = 0;
for (i = cluster_size; i <= p_list->f_ptr; i += cluster_size)
{
p_list->old_cur_cluster = p_list->cur_cluster;
p_list->cur_cluster = GET_FAT_TBL(drv_no, p_list->cur_cluster);
}
}
else
FAT_RETURN(drv_no, ERR_INVALID_PARAM);
FAT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smCloseFile
* Remarks:
* - close the opened file
* - updates file modified time, date, and the size
* Parameters
* . h_file: opened file handle that should be closed
* Notes:
* - if FAT_UPDATE_WHEN_CLOSE is defined, the FAT table must be updated.
* if not defined, it is updated everytime the file handle chain
* structure is changed
**********/
SM_EXPORT ERR_CODE smCloseFile(F_HANDLE h_file)
{
udword drv_no;
udword cluster;
sOPENED_LIST* p_list;
sTIME time_val;
ubyte file_info[32];
udword cluster_no;
udword offset;
udword id;
drv_no = (h_file >> 24) & 0x7f;
if (drv_no >= MAX_DRIVE)
return ERR_INVALID_PARAM;
cluster = h_file & 0xffff;
id = (h_file >> 16) & 0xff;
s_smErr = sm_PreFAT(drv_no);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
s_smErr = sm_GetOpenedList(drv_no, cluster, id, &p_list);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
if (p_list->mode & OPEN_W)
{
#ifndef WRITE_CACHE_DISABLE
if (p_list->cache.count != 0)
sm_WriteCacheToDisk(drv_no, p_list);
#endif
s_smErr = sm_FindEntryInDirectory(drv_no, FIND_CLUSTER, p_list->h_parent, cluster, file_info, &cluster_no, &offset);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
sm_GetTime(&time_val);
if (time_val.year > 1980)
time_val.year -= 1980;
else
time_val.year = 0;
/* file_info[22-23] <= time */
/* Hour | Min | Sec => 5bit | 6bit | 5bit(half value) */
file_info[22] = ((time_val.sec >> 1) & 0x1f) | ((time_val.min << 5) & 0xe0);
file_info[23] = ((time_val.min >> 3) & 0x07) | ((time_val.hour << 3) & 0xf8);
/* file_info[24-25] <= date */
/* Year | Month | Day => 7bit | 4bit | 5bit */
file_info[24] = (time_val.day & 0x1f) | ((time_val.month << 5) & 0xe0);
file_info[25] = ((time_val.month >> 3) & 0x01) | ((time_val.year << 1) & 0xfe);
/* file_info[28-31] <= file size */
file_info[28] = (ubyte)(p_list->size & 0xff);
file_info[29] = (ubyte)((p_list->size >> 8) & 0xff);
file_info[30] = (ubyte)((p_list->size >> 16) & 0xff);
file_info[31] = (ubyte)((p_list->size >> 24) & 0xff);
s_smErr = smcWriteCluster(drv_no, cluster_no, offset, file_info, 32);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
sm_prepareFileClose(drv_no, p_list);
#ifdef FAT_UPDATE_WHEN_FILE_CLOSE
sm_FATUpdate(drv_no);
#endif
}
sm_DeleteFromOpenedFileList(drv_no, cluster);
FAT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smRemoveFile
* Remarks:
* - remove file and update FAT table
* Parameters
* . p_file_name: file name that should be removed
**********/
SM_EXPORT ERR_CODE smRemoveFile(const smchar* p_filename)
{
udword drv_no;
F_HANDLE h_dir;
ubyte *p_file_name = (ubyte *)p_filename;
ubyte long_name[MAX_FILE_NAME_LEN + 1];
drv_no = sm_GetDrvNo(p_file_name);
if (drv_no >= MAX_DRIVE)
return ERR_INVALID_PARAM;
s_smErr = sm_PreFAT(drv_no);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
s_smErr = sm_CheckPath(drv_no, p_file_name, PATH_EXCEPT_LAST, &h_dir);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
sm_ExtractLastName(p_file_name, long_name);
s_smErr = sm_RemoveFile(drv_no, h_dir, long_name);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -