📄 smf_fat.c
字号:
FAT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smGetSizeFile
* Remarks:
* - retrieves file size
* Parameters
* . p_file_name: file name string with full path
* . p_size (result): buffer that saves the file size
**********/
SM_EXPORT ERR_CODE smGetSizeFile(const smchar* p_filename, udword* p_size)
{
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_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);
*p_size = 0;
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);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
*p_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: smFileExtend
* Remarks:
* - expands the file size of the opened file
* Parameters
* . h_file: file handle
* . size : amount of expand size
**********/
SM_EXPORT ERR_CODE smFileExtend(F_HANDLE h_file, udword size)
{
udword drv_no;
udword cluster;
sOPENED_LIST* p_list;
udword id;
udword addedClusterCount;
udword sectorsPerCluster;
udword clusterSize;
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);
size += p_list->size;
sectorsPerCluster = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster;
clusterSize = sectorsPerCluster * SECTOR_SIZE;
/* check if extended size needs more cluster */
addedClusterCount = (size + clusterSize - 1) / clusterSize - (p_list->size + clusterSize - 1) / clusterSize;
if (addedClusterCount)
{
udword curEndSector;
udword nextEndSector;
s_smErr = sm_addClusters(drv_no, cluster, addedClusterCount);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
#if 0 /* file may not have its clusters continously (dalma, 2000.3.15) */
curEndSector = s_clusterStartSector[drv_no] + (cluster - 2) * sectorsPerCluster
+ (p_list->size - p_list->size / clusterSize * clusterSize) / SECTOR_SIZE;
nextEndSector = s_clusterStartSector[drv_no] + (cluster + 1 - 2) * sectorsPerCluster - 1;
if (curEndSector != nextEndSector)
{
s_smErr = sm_eraseSectors(drv_no, curEndSector + 1, nextEndSector - curEndSector);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
}
#endif
}
else
{
udword curEndSector;
udword nextEndSector;
#if 0 /* file may not have its clusters continously (dalma, 2000.3.15) */
curEndSector = s_clusterStartSector[drv_no] + (cluster - 2) * sectorsPerCluster
+ (p_list->size - p_list->size / clusterSize * clusterSize) / SECTOR_SIZE;
nextEndSector = s_clusterStartSector[drv_no] + (cluster - 2) * sectorsPerCluster
+ (size - size / clusterSize * clusterSize) / SECTOR_SIZE;
if (curEndSector != nextEndSector)
{
s_smErr = sm_eraseSectors(drv_no, curEndSector + 1, nextEndSector - curEndSector);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
}
#endif
}
FAT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smCreateDir
* Remarks:
* - creates directory and writes its default sub directory information
* Parameters
* . p_dir_name: directory name that should be created
* (ex. dev0:\temp\readme)
* . dcreate_mode: reserved
**********/
SM_EXPORT ERR_CODE smCreateDir(const smchar* p_dirname, udword dcreate_mode)
{
udword drv_no;
udword cluster;
F_HANDLE h_dir;
ubyte long_name[MAX_FILE_NAME_LEN + 1];
ubyte dummy_info[32];
udword offset;
sFILE_STAT sStat;
ubyte *p_dir_name = (ubyte *)p_dirname;
#ifdef LONG_FILE_NAME_ENABLE
uword* p_unicode;
ubyte fat_name[13];
#endif
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_EXCEPT_LAST, &h_dir);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
sm_ExtractLastName(p_dir_name, long_name);
/* check if the same name exists already */
s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_NAME, h_dir, (udword)long_name, dummy_info, &cluster, &offset);
if (s_smErr != ERR_NOT_FOUND)
FAT_RETURN(drv_no, ERR_FILE_EXIST);
s_smErr = smcAllocCluster(drv_no, &cluster);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
/* directory contents initialize */
s_smErr = smcSetCluster(drv_no, cluster, 0);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
/* FAT table update */
/* This must be done before another smcAllocCluster() is called */
SET_FAT_TBL(drv_no, cluster, LAST_CLUSTER);
/*
* new directory contents write
* (current dir, parent dir information write)
*/
sStat.attr = ATTRIB_DIR;
sStat.cluster = cluster;
sStat.size = 0;
sm_GetTime(&sStat.time);
s_smErr = sm_AddToDirEntry(drv_no, cluster, (ubyte*)".", NULL, &sStat, 0, 0, 0);
if (s_smErr != SM_OK)
{
SET_FAT_TBL(drv_no, cluster, UNUSED_CLUSTER);
FAT_RETURN(drv_no, s_smErr);
}
sStat.cluster = h_dir;
s_smErr = sm_AddToDirEntry(drv_no, cluster, (ubyte*)"..", NULL, &sStat, 0, 0, 0);
if (s_smErr != SM_OK)
{
SET_FAT_TBL(drv_no, cluster, UNUSED_CLUSTER);
FAT_RETURN(drv_no, s_smErr);
}
/* parent directory contents update */
#ifdef LONG_FILE_NAME_ENABLE
p_unicode = (uword*)SM_MALLOC(MAX_FILE_NAME_LEN+2);
if(p_unicode == NULL)
{
SET_FAT_TBL(drv_no, cluster, UNUSED_CLUSTER);
FAT_RETURN(drv_no, ERR_OUT_OF_MEMORY);
}
sStat.cluster = cluster;
if(sm_ConvertToFATName(long_name, fat_name))
{
SM_MBS_TO_UNICODE(p_unicode, long_name, 0);
s_smErr = sm_AddToDirEntry(drv_no, h_dir, long_name, p_unicode, &sStat, 0, 0, 0);
}
else
s_smErr = sm_AddToDirEntry(drv_no, h_dir, long_name, NULL, &sStat, 0, 0, 0);
SM_FREE(p_unicode);
#else
sStat.cluster = cluster;
s_smErr = sm_AddToDirEntry(drv_no, h_dir, long_name, NULL, &sStat, 0, 0, 0);
#endif
if (s_smErr != SM_OK)
{
SET_FAT_TBL(drv_no, cluster, UNUSED_CLUSTER);
FAT_RETURN(drv_no, s_smErr);
}
sm_FATUpdate(drv_no);
FAT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smRemoveDir
* Remarks:
* - remove directory
* Parameters
* . p_dir_name: directory name that should be removed
* . ddel_mode: ALWAYS_DELETE, NOT_IF_NOT_EMPTY
**********/
SM_EXPORT ERR_CODE smRemoveDir(const smchar* p_dirname, udword ddel_mode)
{
udword drv_no;
F_HANDLE h_dir;
F_HANDLE handle;
ubyte long_name[MAX_FILE_NAME_LEN + 1];
ubyte file_info[32];
udword cluster;
udword offset;
udword i;
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);
/* if the given name is root directory, it returns error here */
s_smErr = sm_CheckPath(drv_no, p_dir_name, PATH_EXCEPT_LAST, &h_dir);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
sm_ExtractLastName(p_dir_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, SM_OK);
/* check if the parameter is directory */
if (!(file_info[11] & 0x10))
FAT_RETURN(drv_no, ERR_INVALID_PARAM);
handle = file_info[26] | ((udword)file_info[27] << 8);
if (ddel_mode == ALWAYS_DELETE)
{
/*
* It deletes the first bottommost directory and its files
* again and again, and at last there is no more subdirectory.
* Then sm_RemoveFirstBottommostDir() deletes all the files in
* the "p_dir_name" directory, and returns ERR_NO_MORE_ENTRY.
*
* *** It is implemented not to use recursive call to save
* stack size.
* Instead, it takes more time.
*/
s_smErr = SM_OK;
while (s_smErr == SM_OK)
{
s_smErr = sm_RemoveFirstBottommostDir(drv_no, handle);
}
if (s_smErr != ERR_NO_MORE_ENTRY)
FAT_RETURN(drv_no, s_smErr);
}
else
{
/* check if the directory has any entry */
for (i = 0; i < 3; ++i)
{
s_smErr = sm_FindEntryInDirectory(drv_no, FIND_FILE_INDEX, handle, i, file_info, &cluster, &offset);
if (s_smErr != SM_OK)
{
if (s_smErr == ERR_NOT_FOUND)
{
/*
* this is the only case that the remove should be
* continued
*/
break;
}
else
FAT_RETURN(drv_no, s_smErr);
}
if (file_info[0] == '.') /* skip ".", ".." */
continue;
else
FAT_RETURN(drv_no, ERR_DIR_NOT_EMPTY);
}
}
/* deletes the directory itself from its parent entries */
s_smErr = sm_RemoveFile(drv_no, h_dir, long_name);
if (s_smErr != SM_OK)
FAT_RETURN(drv_no, s_smErr);
FAT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smGetListNumber
* Remarks:
* - retrieves the number of entry in the directory "p_dir_name"
* Parameters
* . p_dir_name: directory name string with full path
* . p_num (result): the number of entry in the directory
**********/
SM_EXPORT ERR_CODE smGetListNumDir(const smchar* p_dirname, udword* p_num)
{
udword drv_no;
F_HANDLE h_dir;
udword cluster;
udword offset;
udword cluster_size;
udword i, j;
udword entry_count;
udword sector_count;
ubyte* buf;
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_num = 0;
cluster_size = s_smInfo[drv_no].pbr.bpb.sectors_per_cluster * SECTOR_SIZE;
entry_count = 0;
buf = SMB_ALLOC_BUF();
if (!buf)
FAT_RETURN(drv_no, ERR_OUT_OF_MEMORY);
if (h_dir == ROOT_HANDLE)
{
for (i = s_rootStartSector[drv_no]; i < s_rootStartSector[drv_no] + s_rootSectors[drv_no]; ++i)
{
s_smErr = smlReadSector(drv_no, i, 0, buf, SECTOR_SIZE);
if (s_smErr != SM_OK)
{
SMB_FREE_BUF(buf);
FAT_RETURN(drv_no, s_smErr);
}
for (j = 0; j < SECTOR_SIZE; j += 32)
{
/*
* exclude no file, deleted file, entry for long file
* name
*/
if(buf[j] == 0)
break;
if ((buf[j] != 0xe5) && ((buf[j + 11] & 0xf) != 0xf))
++entry_count;
}
if(j < SECTOR_SIZE)
break;
}
}
else
{
cluster = h_dir & 0xffff;
while (cluster != LAST_CLUSTER)
{
for (offset = 0; offset < cluster_size; offset += SECTOR_SIZE)
{
s_smErr = smcReadCluster(drv_no, cluster, offset, buf, SECTOR_SIZE);
if (s_smErr != SM_OK)
{
SMB_FREE_BUF(buf);
FAT_RETURN(drv_no, s_smErr);
}
for (j = 0; j < SECTOR_SIZE; j += 32)
{
/*
* exclude no file, deleted file, entry for long
* file name
*/
if(buf[j] == 0)
break;
if ((buf[j] != 0xe5) && ((buf[j + 11] & 0xf) != 0xf))
++entry_count;
}
if(j < SECTOR_SIZE)
break;
}
cluster = GET_FAT_TBL(drv_no, cluster);
/*
* this is the case that FAT table is not updated correctly
*/
if (cluster == UNUSED_CLUSTER)
{
SMB_FREE_BUF(buf);
FAT_RETURN(drv_no, ERR_INCORRECT_FAT);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -