📄 smf_fat.c
字号:
*p_num = entry_count;
SMB_FREE_BUF(buf);
FAT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smReadDir
* Remarks:
* - retrieves entries' simple information in the directory
* "p_dir_name"
* Parameters
* . p_dir_name: directory name string with full path
* . entry_start: start index of the entry
* . entry_count: number of entries that should be retrieved
* . p_buf (result): buffer that saves the entries' information
* . p_read_count (result): number of entries that was saved
* Notes:
* - "p_buf" must be prepared for space of
* "entry_count * sizeof(sDIR_ENTRY)"
**********/
SM_EXPORT ERR_CODE smReadDir(const smchar* p_dirname, udword entry_start, udword entry_count, sDIR_ENTRY p_buf[], udword* p_read_count)
{
udword drv_no;
F_HANDLE h_dir;
ubyte file_info[32];
udword cluster;
udword offset;
udword i, j, k;
ubyte *p_dir_name = (ubyte *)p_dirname;
drv_no = sm_GetDrvNo(p_dir_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_dir_name, PATH_FULL, &h_dir);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
*p_read_count = 0;
for (i = 0; i < entry_count; ++i)
{
s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_INDEX, h_dir, entry_start + i, file_info, &cluster, &offset);
if (s_smErr != SM_OK)
{
if (s_smErr == ERR_NOT_FOUND)
{
*p_read_count = i;
FAT_RETURN(drv_no, ERR_EOF);
}
else
FAT_RETURN(drv_no, s_smErr);
}
for (j = 0, k = 0; j < 11; ++j)
{
if (file_info[j] != ' ')
{
if (j == 8)
{
p_buf[i].name[k] = '.';
++k;
}
p_buf[i].name[k] = file_info[j];
++k;
}
}
p_buf[i].name[k] = 0;
}
*p_read_count = entry_count;
FAT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smReadDirEx
* Remarks:
* - retrieves entries' full information in the directory "p_dir_name"
* Parameters
* . p_dir_name: directory name string with full path
* . entry_start: start index of the entry
* . entry_count: number of entries that should be retrieved
* . p_buf (result): buffer that saves the entries' information
* . p_read_count (result): number of entries that was saved
* Notes:
* - "p_buf" must be prepared for space of
* "entry_count * sizeof(sDIR_ENTRY_EX)"
**********/
SM_EXPORT ERR_CODE smReadDirEx(const smchar* p_dirname, udword entry_start, udword entry_count, sDIR_ENTRY_EX p_buf[], udword* p_read_count)
{
udword drv_no;
F_HANDLE h_dir;
ubyte file_info[32];
udword cluster;
udword offset;
udword i, j, k;
ubyte *p_dir_name = (ubyte *)p_dirname;
drv_no = sm_GetDrvNo(p_dir_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_dir_name, PATH_FULL, &h_dir);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
*p_read_count = 0;
for (i = 0; i < entry_count; ++i)
{
s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_INDEX, h_dir, entry_start + i, file_info, &cluster, &offset);
if (s_smErr != SM_OK)
{
if (s_smErr == ERR_NOT_FOUND)
{
*p_read_count = i;
FAT_RETURN(drv_no, ERR_EOF);
}
else
FAT_RETURN(drv_no, s_smErr);
}
for (j = 0, k = 0; j < 11; ++j)
{
if (file_info[j] != ' ')
{
if (j == 8)
{
p_buf[i].name[k] = '.';
++k;
}
p_buf[i].name[k] = file_info[j];
++k;
}
}
p_buf[i].name[k] = 0;
#ifdef LONG_FILE_NAME_ENABLE
s_smErr = sm_GetLongName(drv_no, h_dir, cluster, offset, p_buf[i].long_name);
if ((s_smErr != SM_OK) && (s_smErr != ERR_FILE_NAME_LEN_TOO_LONG))
p_buf[i].long_name[0] = 0;
#else
p_buf[i].long_name[0] = 0;
#endif
p_buf[i].stat.attr = file_info[11];
p_buf[i].stat.time.year = 1980 + ((file_info[25] >> 1) & 0x7f);
p_buf[i].stat.time.month = ((file_info[25] << 3) & 0x08) | ((file_info[24] >> 5) & 0x07);
p_buf[i].stat.time.day = file_info[24] & 0x1f;
p_buf[i].stat.time.hour = (file_info[23] >> 3) & 0x1f;
p_buf[i].stat.time.min = ((file_info[23] << 3) & 0x38) | ((file_info[22] >> 5) & 0x07);
p_buf[i].stat.time.sec = file_info[22] & 0x1f;
p_buf[i].stat.time.msec = 0;
p_buf[i].stat.cluster = (uword)file_info[26] | ((uword)file_info[27] << 8);
p_buf[i].stat.size = (udword)file_info[28] | ((udword)file_info[29] << 8)
| ((udword)file_info[30] << 16) | ((udword)file_info[31] << 24);
}
*p_read_count = entry_count;
FAT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smReadStat
* Remarks:
* - retrieves file(directory) information
* Parameters
* . p_name: file(directory) name string with full path
* . p_stat (result): buffer that saves the file(directory) information
* Notes:
* - "p_stat" must be prepared for space of "sizeof(sFILE_STAT)"
* - if "p_name" indicates root directory, it returns ERR_ROOT_DIR
**********/
SM_EXPORT ERR_CODE smReadStat(const smchar* p_entry_name, sFILE_STAT* p_stat)
{
udword drv_no;
F_HANDLE h_dir;
ubyte long_name[MAX_FILE_NAME_LEN + 1];
ubyte file_info[32];
udword cluster;
udword offset;
ubyte *p_name = (ubyte *)p_entry_name;
drv_no = sm_GetDrvNo(p_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_name, PATH_EXCEPT_LAST, &h_dir);
if (s_smErr != SM_OK)
{
s_smErr = sm_CheckPath(drv_no, p_name, PATH_FULL, &h_dir);
if (s_smErr == SM_OK)
{
if (h_dir == ROOT_HANDLE)
FAT_RETURN(drv_no, ERR_ROOT_DIR);
else
FAT_RETURN(drv_no, ERR_INVALID_PARAM);
}
else
FAT_RETURN(drv_no, s_smErr);
}
sm_ExtractLastName(p_name, long_name);
s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_NAME, h_dir, (udword)long_name, file_info, &cluster, &offset);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
p_stat->attr = file_info[11];
p_stat->time.year = 1980 + ((file_info[25] >> 1) & 0x7f);
p_stat->time.month = ((file_info[25] << 3) & 0x08) | ((file_info[24] >> 5) & 0x07);
p_stat->time.day = file_info[24] & 0x1f;
p_stat->time.hour = (file_info[23] >> 3) & 0x1f;
p_stat->time.min = ((file_info[23] << 3) & 0x38) | ((file_info[22] >> 5) & 0x07);
p_stat->time.sec = file_info[22] & 0x1f;
p_stat->time.msec = 0;
p_stat->cluster = (udword)file_info[26] | ((udword)file_info[27] << 8);
p_stat->size = (udword)file_info[28] | ((udword)file_info[29] << 8)
| ((udword)file_info[30] << 16) | ((udword)file_info[31] << 24);
FAT_RETURN(drv_no, s_smErr);
}
/**********
* Function: smWriteStat
* Remarks:
* - updates the file(directory) information
* Parameters
* . p_name: file(directory) name string with full path
* . p_stat (result): file(directory) information pointer
* Notes:
* - p_stat->cluster, p_stat->size is not adapted. these are not the
* values user can change
* - if "p_name" indicates root directory, it returns ERR_ROOT_DIR
**********/
SM_EXPORT ERR_CODE smWriteStat(const smchar* p_entry_name, const sFILE_STAT* p_stat)
{
udword drv_no;
F_HANDLE h_dir;
ubyte long_name[MAX_FILE_NAME_LEN + 1];
ubyte file_info[32];
udword cluster;
udword offset;
ubyte year;
ubyte *p_name = (ubyte *)p_entry_name;
drv_no = sm_GetDrvNo(p_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_name, PATH_EXCEPT_LAST, &h_dir);
if (s_smErr != SM_OK)
{
s_smErr = sm_CheckPath(drv_no, p_name, PATH_FULL, &h_dir);
if (s_smErr == SM_OK)
{
if (h_dir == ROOT_HANDLE)
FAT_RETURN(drv_no, ERR_ROOT_DIR);
else
FAT_RETURN(drv_no, ERR_INVALID_PARAM);
}
else
FAT_RETURN(drv_no, s_smErr);
}
sm_ExtractLastName(p_name, long_name);
s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_NAME, h_dir, (udword)long_name, file_info, &cluster, &offset);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
file_info[11] = (ubyte)(p_stat->attr & 0xff);
/* file_info[22-23] <= time */
/* Hour | Min | Sec => 5bit | 6bit | 5bit(half value) */
file_info[22] = ((p_stat->time.sec >> 1) & 0x1f) | ((p_stat->time.min << 5) & 0xe0);
file_info[23] = ((p_stat->time.min >> 3) & 0x07) | ((p_stat->time.hour << 3) & 0xf8);
/* file_info[24-25] <= date */
/* Year | Month | Day => 7bit | 4bit | 5bit */
file_info[24] = ((p_stat->time.day) & 0x1f) | ((p_stat->time.month << 5) & 0xe0);
if (p_stat->time.year > 1980)
year = p_stat->time.year - 1980;
else
year = 0;
file_info[25] = ((p_stat->time.month >> 3) & 0x01) | ((year << 1) & 0xfe);
s_smErr = smcWriteCluster(drv_no, cluster, offset, file_info, 32);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
FAT_RETURN(drv_no, SM_OK);
}
#ifdef LONG_FILE_NAME_ENABLE
/**********
* Function: smSetLongName
* Remarks:
* - set the long name
* Parameters
* . p_file_name: file name that exists (ex. dev0:\temp\readme.txt)
* . p_long_name: long name(without directory path) that is in Unicode
* Notes:
* - SMFS does not support creation of file with its long name becuase
* it needs very large Unicode table. Instead, it is possible to
* set its long name using this function in the environment that
* has methods for Unicode translation
**********/
SM_EXPORT ERR_CODE smSetLongName(const smchar* p_filename, const uword* p_long_name)
{
udword drv_no;
F_HANDLE h_dir;
ubyte long_name[MAX_FILE_NAME_LEN + 1];
ubyte file_info[32];
udword cluster;
udword offset;
sFILE_STAT sStat;
ubyte *p_file_name = (ubyte *)p_filename;
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);
/* search existing file for use of the 32 byte file_info */
s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_NAME, h_dir, (udword)long_name, file_info, &cluster, &offset);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
sStat.attr = file_info[11];
sStat.cluster = file_info[26] | ((udword)file_info[27] << 8);
sStat.size = file_info[28] | ((udword)file_info[29] << 8) | ((udword)file_info[30] << 16) | ((udword)file_info[31] << 24);
sStat.time.year = 1980 + ((file_info[25] >> 1) & 0x7f);
sStat.time.month = ((file_info[25] << 3) & 0x08) | ((file_info[24] >> 5) & 0x07);
sStat.time.day = file_info[24] & 0x1f;
sStat.time.hour = (file_info[23] >> 3) & 0x1f;
sStat.time.min = ((file_info[23] << 3) & 0x38) | ((file_info[22] >> 5) & 0x07);
sStat.time.sec = file_info[22] & 0x1f;
sStat.time.msec = 0;
/* delete existing entry */
s_smErr = sm_DeleteFromDirEntry(drv_no, h_dir, long_name);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
/* set new entry with long file name */
s_smErr = sm_AddToDirEntry(drv_no, h_dir, (const ubyte*)long_name, p_long_name, &sStat, 0, 0, 0);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
FAT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smGetLongName
* Remarks:
* - get the long name
* Parameters
* . p_file_name: file name that exists (ex. dev0:\temp\readme.txt)
* . p_long_name: long name(without directory path) that is in Unicode
* Notes:
* - p_long_name is returned with Unicode
**********/
SM_EXPORT ERR_CODE smGetLongName(const smchar* p_filename, uword* p_long_name)
{
udword drv_no;
F_HANDLE h_dir;
ubyte file_info[32];
udword cluster;
udword offset;
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_FindEntryInDirectory(drv_no, FIND_FILE_NAME, h_dir, (udword)long_name, file_info, &cluster, &offset);
s_smErr = sm_GetLongName(drv_no, h_dir, cluster, offset, p_long_name);
if (s_smErr != SM_OK)
{
if(s_smErr != ERR_FILE_NAME_LEN_TOO_LONG)
p_long_name[0] = 0;
FAT_RETURN(drv_no, s_smErr);
}
FAT_RETURN(drv_no, SM_OK);
}
#endif /* LONG_FILE_NAME_ENABLE */
/**********
* Function: smGetVolInfo
* Remarks:
* - get volumn information
* Parameters
* . p_vol_name: volumn name that is mounted (ex. "dev0:")
* . p_info (result): pointer of volumn info structure
**********/
SM_EXPORT ERR_CODE smGetVolInfo(const smchar* p_volumn_name, sVOL_INFO* p_info)
{
udword drv_no;
udword total_clusters;
udword cluster_size;
udword fat_val;
udword i;
ubyte *p_vol_name = (ubyte *)p_volumn_name;
drv_no = sm_GetDrvNo(p_vol_name);
if (drv_no >= MAX_DRIVE)
return ERR_INVALID_PARAM;
s_smErr = sm_PreFAT(drv_no);
if (s_smErr != SM_OK)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -