📄 fat_open.c
字号:
S8 *ext;
S8 *s;
S32 i;
s = (S8 *)pOrgName;
ext = (S8 *) FS__CLIB_strchr(s, '.');//ext指向'.'
if (!ext) {
ext = &s[FS__CLIB_strlen(s)];//如果没有'.' ext->'\0'
}
i=0;
while (1) {
if (s >= ext) {
break; /* '.' reached */
}
if (i >= 8) {
break; /* If there is no '.', this is the end of the name */
}
if (*s == (char)0xe5) {
pEntryName[i] = 0x05;
}
else {
pEntryName[i] = (char)FS__CLIB_toupper(*s);
}
i++;
s++;
}
while (i < 8) {
/* Fill name with spaces*/
pEntryName[i] = ' ';
i++;
}
if (*s == '.') {
s++;
}
while (i < 11) {
if (*s != '\0') {
if (*s == (char)0xe5) {
pEntryName[i] = 0x05;
}
else {
pEntryName[i] = (char)FS__CLIB_toupper(*s);
}
s++;
}
else {
pEntryName[i] = ' ';
}
i++;
}
pEntryName[11]='\0';
}
/*********************************************************************
*
* FS__fat_dirsize
*
Description:
FS internal function. Return the sector size of the directory
starting at DirStart.
Parameters:
Idx - Index of device in the device information table
referred by FS__pDevInfo.
Unit - Unit number.
DirStart - 1st cluster of the directory. This is zero to address
the root directory.
Return value:
>0 - Sector (not cluster) size of the directory.
==0 - An error has occured.
*/
//找出一层目录包含的扇区数
U32 FS__fat_dir_size( U32 DirStart) {
U32 dsize;
S32 value;
if (DirStart == 0) {
/* For FAT12/FAT16 root directory, the size can be found in BPB */
dsize = FS__pDiskInfo[0].RootSecCnt;
}
else {
/* Calc size of a sub-dir */
value = FS__fat_FAT_find_eof( DirStart, &dsize);
if (value < 0) {
dsize = 0;
}
else {
dsize *= FS__pDiskInfo[0].SecPerClus;
}
}
return dsize;
}
/*********************************************************************
*
* FS__fat_dir_realsec
*
Description:
FS internal function. Translate a directory relative sector number
to a real sector number on the media.
Parameters:
DirStart - 1st cluster of the directory. This is zero to address
the root directory.
DirSec - Sector in the directory.
Return value:
>0 - Directory found. Value is the sector number on the media.
==0 - An error has occured.
*/
//返回相对于DirStart簇的扇区的真实扇区号
U32 FS__fat_dir_realsec( U32 DirStart, U32 DirSec) {
U32 rootdir;
U32 rsec;
U32 dclust;
U32 fatsize;
S32 fattype;
S32 lexp;
U8 secperclus;
fattype = FS__fat_which_type();
lexp = (0 == DirStart);
lexp = lexp && (fattype==FAT16);
if (lexp) {
/* Sector in FAT12/FAT16 root directory */
rootdir =FS__pDiskInfo[0].RootDirTable;
rsec = rootdir + DirSec;
}
else {
fatsize = FS__pDiskInfo[0].FATSecCnt;
secperclus = FS__pDiskInfo[0].SecPerClus;
dclust = DirSec / secperclus;
rsec = FS__fat_diskclust( DirStart, dclust);
if (rsec == 0) {
return 0;
}
rsec -= 2;
rsec *= secperclus;
rsec+=FS__pDiskInfo[0].DataStartSec;
rsec += (DirSec % secperclus);
}
return rsec;
}
/*********************************************************************
*
* FS__fat_find_dir
*
Description:
FS internal function. Find the directory with name pDirName in directory
DirStart.
Parameters:
Idx - Index of device in the device information table
referred by FS__pDevInfo.
Unit - Unit number.
pDirName - Directory name; if zero, return the root directory.
DirStart - 1st cluster of the directory.
DirSize - Sector (not cluster) size of the directory.
Return value:
>0 - Directory found. Value is the first cluster of the file.
==0 - An error has occured.
*/
//在一层目录树中寻找目录返回一个目录的开始簇号
U32 FS__fat_find_dir( S8 *pDirName, U32 DirStart,U32 DirSize) {
FS__fat_dentry_type *s;
U32 dstart;
U32 i;
U32 dsec;
S32 len;
S32 err;
S32 c;
S8 *buffer;
if (pDirName == 0) {
/* Return root directory */
dstart=FS__pDiskInfo[0].RootDirTable;
}
else {
/* Find directory */
buffer = (S8 *)FS__fat_malloc(FAT_SEC_SIZE);
if (BUFFER_ERR==(S32)buffer) {
return 0;
}
len = FS__CLIB_strlen(pDirName);
if (len > 11) {
len = 11;
}
/* Read directory */
for (i = 0; i < DirSize; i++) {
dsec = FS__fat_dir_realsec(DirStart, i);
if (dsec == 0) {
FS__fat_free(buffer);
return 0;
}
err = FS__lb_read(FS__pDevInfo[0].harddisk_driver, 0, dsec, (void*)buffer);
if (err!=SD_NO_ERR) {
FS__fat_free(buffer);
return 0;
}
s = (FS__fat_dentry_type*)buffer;
while (1) {
if (s >= (FS__fat_dentry_type*)(buffer + FAT_SEC_SIZE)) {
break; /* End of sector reached */
}
c = FS__CLIB_strncmp((char*)s->data, pDirName, len);
if (c == 0) { /* Name does match */
if (s->data[11] & FS_FAT_ATTR_DIRECTORY) {
break; /* Entry found */
}
}
s++;
}
if (s < (FS__fat_dentry_type*)(buffer + FAT_SEC_SIZE)) {
/* Entry found. Return number of 1st block of the directory */
FS__fat_free(buffer);
dstart = (U32)s->data[26];
dstart += (U32)0x100UL * s->data[27];
dstart += (U32)0x10000UL * s->data[20];
dstart += (U32)0x1000000UL * s->data[21];
return dstart;
}
}
dstart = 0;
FS__fat_free(buffer);
}
return dstart;
}
/*********************************************************************
*
* FS__fat_findpath
*
Description:
FS internal function. Return start cluster and size of the directory
of the file name in pFileName.
Parameters:
pFullName - Fully qualified file name w/o device name.
pFileName - Pointer to a pointer, which is modified to point to the
file name part of pFullName.
pUnit - Pointer to an FS_u32 for returning the unit number.
pDirStart - Pointer to an FS_u32 for returning the start cluster of
the directory.
Return value:
>0 - Sector (not cluster) size of the directory.
==0 - An error has occured.
*/
//根据路径寻找一个目录文件,返回目录文件的开始簇号,目录文件的路径必须是 \\***\\****\\*****\\
U32 FS__fat_findpath( const S8 *pFullName, S8 **pFileName,U32 *pDirStart) {
U32 dsize;
S32 i;
S32 j;
S8 *dname_start;
S8 *dname_stop;
S8 *chprt;
S32 x;
S8 dname[12];
S8 realname[12];
/* Use 1st unit as default */
*pFileName = (S8 *) pFullName;
/* Check volume */
x = FS__fat_checkunit();
if (x!=FS_NO_ERR) {
return 0;
}
/* Setup pDirStart/dsize for root directory */
*pDirStart = 0;
dsize = FS__fat_dir_size(0);
/* Find correct directory */
do {
dname_start = (S8 *)FS__CLIB_strchr(*pFileName, '\\');
if (dname_start) {
dname_start++;
*pFileName = dname_start;
dname_stop = (S8 *)FS__CLIB_strchr(dname_start, '\\');
}
else {
dname_stop = 0;
}
if (dname_stop) {
i = dname_stop-dname_start;
if (i >= 12) {
j = 0;
for (chprt = dname_start; chprt < dname_stop; chprt++) {
if (*chprt == '.') {
i--;
}
else if (j < 12) {
realname[j] = *chprt;
j++;
}
}
if (i >= 12) {
return 0;
}
}
else {
FS__CLIB_strncpy(realname, dname_start, i);
}
realname[i] = '\0';
FS__fat_make_realname(dname, realname);
*pDirStart = FS__fat_find_dir(dname, *pDirStart, dsize);
if (*pDirStart) {
dsize = FS__fat_dir_size(*pDirStart);
}
else {
dsize = 0; /* Directory NOT found */
}
}
} while (dname_start);
return dsize;
}
/*********************************************************************
*
* Global functions section 2
*
**********************************************************************
These are real global functions, which are used by the API Layer
of the file system.
*/
/*********************************************************************
*
* FS__fat_fopen
*
Description:
FS internal function. Open an existing file or create a new one.
Parameters:
pFileName - File name.
pMode - Mode for opening the file.
pFile - Pointer to an FS_FILE data structure.
Return value:
==0 - Unable to open the file.
!=0 - Address of the FS_FILE data structure.
*/
FS_FILE *FS__fat_fopen(S8 *pFileName,const S8 *pMode, FS_FILE *pFile) {
U32 dstart;
U32 dsize;
S32 i;
S8 * fname;
FS__fat_dentry_type s;
S8 realname[12];
S32 lexp_a;
S32 lexp_b;
S32 lexp_c;
if (!pFile) {
return 0; /* Not a valid pointer to an FS_FILE structure*/
}
dsize = FS__fat_findpath( pFileName, &fname, &dstart);
if (dsize == 0) {
return 0; /* Directory not found */
}
FS__fat_make_realname(realname, fname); /* Convert name to FAT real name */
/* FileSize = 0 */
s.data[28] = 0x00;
s.data[29] = 0x00;
s.data[30] = 0x00;
s.data[31] = 0x00;
i = _FS_fat_find_file( realname, &s, dstart, dsize);
if(i==0){
FS__fat_DeleteFileOrDir(realname,dstart,dsize,1);
i=_FS_fat_create_file(realname,dstart,dsize);
}
lexp_c=(i>0);
/* Delete file */
lexp_b = (FS__CLIB_strcmp(pMode, "del") == 0); /* Delete file request */
lexp_a = lexp_b && (i >= 0); /* File does exist */
if (lexp_a) {
i = FS__fat_DeleteFileOrDir( realname, dstart, dsize, 1);
if (i < 0) {
return (FS_FILE *)FS_ERR;
}
return 0;
}
else if (lexp_b) {
return 0;
}
/* Check read only */
lexp_a = ((i >= 0) && ((s.data[11] & FS_FAT_ATTR_READ_ONLY) != 0)) &&((pFile->mode_w) || (pFile->mode_a) || (pFile->mode_c));
if (lexp_a) {
/* Files is RO and we try to create, write or append */
return 0;
}
lexp_a = (( i>= 0) && (!pFile->mode_a) && (((pFile->mode_w) && (!pFile->mode_r)) || ((pFile->mode_w) && (pFile->mode_c) && (pFile->mode_r)) ));
if (lexp_a) {
/* Delete old file */
i = FS__fat_DeleteFileOrDir( realname, dstart, dsize, 1);
/* FileSize = 0 */
s.data[28] = 0x00;
s.data[29] = 0x00;
s.data[30] = 0x00;
s.data[31] = 0x00;
i=-1;
}
if ((!pFile->mode_c) && (i < 0)) {
/* File does not exist and we must not create */
return 0;
}
else if ((pFile->mode_c) && (i < 0)) {
/* Create new file */
i = _FS_fat_create_file(realname, dstart, dsize);
if (i < 0) {
/* Could not create file */
if (i == DIR_FULL) {
/* Directory is full, try to increase */
i = _FS_fat_IncDir( dstart, &dsize);
if (i ==FS_NO_ERR) {
i = _FS_fat_create_file(realname, dstart, dsize);
}
}
if (i != FS_NO_ERR) {
return 0;
}
}
}
pFile->CurClust = 0;
pFile->FstClus = i;
pFile->DirClus =dstart;
pFile->EOFClust = -1;
pFile->CacheId =-1;
pFile->dirty =0;
pFile->FileSize = (U32)s.data[28]; /* FileSize */
pFile->FileSize += (U32)0x100UL * s.data[29];
pFile->FileSize += (U32)0x10000UL * s.data[30];
pFile->FileSize += (U32)0x1000000UL * s.data[31];
if (pFile->mode_a) {
pFile->Offset = pFile->FileSize;
}
else {
pFile->Offset = 0;
}
pFile->inuse = 1;
return pFile;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -