📄 rtfiles.c
字号:
#define SUBMARK_MASK (0x0000FFFF)
#define SUBMARK_LASTNUM (119)
/* Directory Associated Cache Value, store run-time cache
* Design to get faster respone for browsing application, especially on Large Directory case
*/
typedef struct MTDirAssociatedCache {
RTFDrive * Drive;
RTFCluster Cluster;
UINT Value;
} DirAssocatedCacheStruct;
#define DIRCACHE_NUM (8)
#define DIRCACHE_MASK (0x00000007)
#ifndef _LOW_COST_SINGLE_BANK_FLASH_
DirAssocatedCacheStruct g_DirCacheArray[DIRCACHE_NUM];
#endif /* _LOW_COST_SINGLE_BANK_FLASH_ */
//---------------------- MT Global Static Func --------------------------
#ifdef __FS_QM_SUPPORT__
static void GetQuotaEntry(int * Index, RTFile * f);
static int QMPermitAllocate(UINT DriveFree, int Index, UINT NeedCluster);
#endif
#if (defined(__FS_SHADOW_NAND__) || defined(__FS_SHADOW_CARD__))
static void InitShadowFAT(RTFDrive *Drive);
static void FlushShadowFAT(void);
#endif
static void INTERN SetupFMapF_FileHandle(RTFile *f);
static int INTERN MTChkMapedFH(RTFHANDLE File);
static RTFCluster INTERN FATSearchZeroInBuffer(RTFDrive *Drive, RTFCluster Cluster);
static void INTERN FATHoistSubMark(RTFDrive *Drive, RTFCluster Begin, RTFCluster End);
static void INTERN FATLowerSubMark(RTFDrive *Drive, RTFCluster Begin, RTFCluster End);
static void INTERN FATInitInfoSectorSubMark(RTFDrive *Drive);
static RTFCluster INTERN FATHintSearchBySubMark(RTFDrive * Drive, RTFCluster Cluster, int MarkFlag);
//---------------------- MT Global Extern Func --------------------------
#ifdef __FS_TRACE_SUPPORT__
#include <stdio.h>
extern void tst_sys_trace(kal_uint8 *);
#endif
extern kal_bool INT_QueryExceptionStatus(void);
/***********************************************************************/
/* MTK Enhancement, Karen Hsu, ADD END */
static RTFCriticalErrorHandler CriticalError = RTFDefaultCriticalErrorHandler;
static UINT Unique = 0;
//static fs_block_type_enum fs_block_type = FS_BLOCK_ENUM; /* Fix multi-access bug, Karen Hsu, 2004/07/08, REM */
static int TLSBlockIndex = -1;
extern void WDT_Restart2(void); /* Add for avoiding compile warning, Karen Hsu, 2004/01/14 */
BYTE RTFAPI _rtfLock(BYTE * Lock); // Temp = *Lock; *Lock = 1; return Temp;
static void INTERN LockDevice (RTFDevice * Dev);
static void INTERN DiscardOtherBuffer(RTFBuffer * B);
static void * INTERN SearchBuffer (RTFDevice * Dev, RTFSector Sector);
static void * INTERN GetBuffer (RTFDevice * Dev, RTFSector Sector, UINT Flags);
static void INTERN ScanDevices(void);
static void INTERN UnmountDevice(RTFDevice * Dev, int CloseFiles);
static char INTERN ScanPartitionTable(char volatile DriveLetter, RTFDevice * Dev, int PartitionKind);
static int INTERN GenerateShortName(const char * LongName, char * ShortName);
static void INTERN IncShortName(char * ShortName);
#define RTFRoundUp(N, Multiple) (((N)+(Multiple)-1) & ~((Multiple)-1))
#define RTFRoundDown(N, Multiple) ((N) & ~((Multiple)-1))
#define CLUSTER_TO_SECTOR(Drive, Cluster) ((Drive)->FirstDataSector + (((Cluster)-2L) << (Drive)->SPerCShift))
#define CLUSTER_TO_SECTOR_DIR(Drive, Cluster) (((Cluster) == RTF_ROOT_DIR) ? (Drive)->FirstDirSector : CLUSTER_TO_SECTOR(Drive, Cluster))
#define CLUSTER_TO_SECTOR_OFS(Drive, Cluster, Ofs) ((Drive)->FirstDataSector + (((Cluster)-2L) << (Drive)->SPerCShift) + ((Ofs) >> (Drive)->Dev->DevData.SectorShift))
#define CLUSTER_TO_SECTOR_DIR_OFS(Drive, Cluster, Ofs) ((((Cluster) == RTF_ROOT_DIR) ? (Drive)->FirstDirSector : CLUSTER_TO_SECTOR(Drive, Cluster)) + ((Ofs) >> (Drive)->Dev->DevData.SectorShift))
#define SECTOR_OFS(Drive, Ofs) ((Ofs) & ((Drive)->Dev->DevData.SectorSize-1))
#define SAME_DIR_ENTRY(D1, D2) (((D1).Cluster == (D2).Cluster) && ((D1).Index == (D2).Index))
#define DIRS_PER_SECTOR(Drive) (Drive->Dev->DevData.SectorSize/sizeof(RTFDOSDirEntry))
// Buffer flags
#define B_VALID 0x01 // buffer has valid data
#define B_DIRTY 0x02 // buffer has valid data and must be written to disk
#define B_INUSE 0x04 // buffer is being accessed by RTFiles
#define B_BUSY 0x08 // buffer is being accessed by a device driver
#define B_SINGLE 0x10 // single buffer for emergent use only /* Guarantee fixed disk access, Karen Hsu, 2005/05/19 */
/*----------------------------------*/
static int INTERN PowerTwo(unsigned int i)
{
if (i == 0)
return 0; // it's a power of two, put we need > 0
while (i != 0)
{
if ((i & 1) && (i != 1))
return 0;
i >>= 1;
}
return 1;
}
/*-----------------------------------*/
static void INTERN ToHexString(char * Name, DWORD TimeStamp)
// write 8 hex digits, no zero termination
{
UINT i;
char HexDigits[] = "0123456789ABCDEF";
for (i=0; i<8; i++)
{
Name[7-i] = HexDigits[TimeStamp & 0xF];
TimeStamp >>= 4;
}
}
/*-----------------------------------*/
static int INTERN IsValidShortNameChar(char c)
// ".", "\\", and ":" is invalid
{
if ( strchr(ShortNameChars, c) )
return 1;
else
return 0;
}
/*-----------------------------------*/
/* Check the validity of filename with ascii code only */
int RTFAPI IsValidLongNameChar(WCHAR c)
//static int INTERN IsValidLongNameChar(WCHAR c)
// "\\" and ":" is invalid
{
char LongNameChars[] = ".+,;=[]";
if ( c<0x80 )
return ( strchr(ShortNameChars, (char)c) || strchr(LongNameChars, (char)c) );
return 1;
}
/*-----------------------------------*/
/* check only the last filename component */
static void INTERN CheckValidFileName(const WCHAR * FileName)
{
const WCHAR *p = kal_wstrrchr(FileName, 0x005c);
if (p == NULL)
p = FileName;
else
p++;
/* Fix Dot-begin issue, Karen Hsu, 2004/04/29, ADD START */
if((*p == 0x2E) || (*p == 0x20))
{
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, RTF_INVALID_FILENAME, NULL, (BYTE *)FileName);
#endif
XRAISE(RTF_INVALID_FILENAME);
}
/* Fix Dot-begin issue, Karen Hsu, 2004/04/29, ADD END */
for ( ;*p != 0x0; p++)
{ if (!IsValidLongNameChar(*p) || *p == 0xFFFF /* UCS2 convert failure mark, WCP_SW, 2005/11/17*/)
{
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, RTF_INVALID_FILENAME, NULL, (BYTE *)FileName);
#endif
XRAISE(RTF_INVALID_FILENAME);
}
}
/* Fix Dot-end issue, Karen Hsu, 2004/04/29, ADD START */
p--;
if(*p == 0x2E)
{
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, RTF_INVALID_FILENAME, NULL, (BYTE *)FileName);
#endif
XRAISE(RTF_INVALID_FILENAME);
}
/* Fix Dot-end issue, Karen Hsu, 2004/04/29, ADD END */
}
/*-----------------------------------*/
/* COMPare Unicode and Ascii STRING */
int compUAstring(const char * FileName, const char* str, int len)
{
int i;
for (i=0; i<len; i++)
{
if (!compASCII(FileName, i, str[i]))
return 0;
}
return 1;
}
/*-----------------------------------*/
WCHAR UnicodetoNative(WCHAR unicode)
{
if ( unicode<0x80 )
return unicode;
else
/* Support SFN in active encoding, Karen Hsu, 2004/05/28, MOD START */
{
WCHAR encode;
encode = UCS2_TO_WCHAR(unicode);
ASSERT(encode != 0x0000);
return encode;
}
/* Support SFN in active encoding, Karen Hsu, 2004/05/28, MOD END */
}
/*-----------------------------------*/
WCHAR NativetoUnicode(WCHAR native)
{
return native;
}
/*-----------------------------------*/
static char INTERN _rtftoupper(signed char c)
{
if ( (c >= 'a') && (c <= 'z') )
return c - ('a' - 'A');
return c;
}
/*-----------------------------------*/
WCHAR RTFAPI wchartoupper(WCHAR c)
{
// check if ascii code
if ( (c>=0x61) && (c<=0x7a) )
return c - (0x61 - 0x41);
return c;
}
/*-----------------------------------*/
static RTFErrorAction INTERN HandleCriticalError(RTFDevice * Dev, int ErrorCode);
static int INTERN GetDiskGeometry(RTFDevice * Dev, RTFPartitionRecord * DiskGeometry, BYTE * MediaDescriptor);
/*-----------------------------------*/
static void INTERN CheckMedia(RTFDevice * Dev)
{
if ((Dev->DevData.MediaRemovedReported == 0) ||
(Dev->DevData.MediaPresent == 0))
{
Dev->DevData.MediaRemovedReported = 1;
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
{
if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NOR");
else if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NAND");
else
kal_sprintf(TraceTmpBuf, "Dev:Card");
memset(TraceTmpBuf+strlen((char *)TraceTmpBuf)+1, 0, 2);
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, RTF_MEDIA_CHANGED, NULL, (BYTE *)TraceTmpBuf);
}
#endif
XRAISE(RTF_MEDIA_CHANGED);
}
}
/*-----------------------------------*/
static int INTERN MountDevice(RTFDevice * Dev, DWORD Flags)
{
int volatile Result;
RTFSYSFreeMutex((RTFMutex *)RTFLock);
XTRY
case XCODE:
Dev->DevData.MediaRemovedReported = 1;
CheckMedia(Dev);
Dev->DevData.ErrorCondition = RTF_NO_ERROR;
Dev->DevData.MediaDescriptor = 0;
memset((void *)&Dev->DevData.Geometry, 0, sizeof(Dev->DevData.Geometry));
Dev->DevData.MountState = Initialized;
Result = Dev->Driver->MountDevice(Dev->DriverData, Dev->DeviceNumber, Dev->DeviceType, Dev->DeviceFlags);
if (Result < RTF_NO_ERROR)
{
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
{
if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NOR");
else if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NAND");
else
kal_sprintf(TraceTmpBuf, "Dev:Card");
memset(TraceTmpBuf+strlen((char *)TraceTmpBuf)+1, 0, 2);
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, Result, NULL, (BYTE *)TraceTmpBuf);
}
#endif
XRAISE(Result);
}
if (Result > RTF_MIN_BUFFER_SIZE)
{
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
{
if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NOR");
else if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NAND");
else
kal_sprintf(TraceTmpBuf, "Dev:Card");
memset(TraceTmpBuf+strlen((char *)TraceTmpBuf)+1, 0, 2);
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, RTF_INVALID_SECTOR_SIZE, NULL, (BYTE *)TraceTmpBuf);
}
#endif
XRAISE(RTF_INVALID_SECTOR_SIZE);
}
if (!PowerTwo(Result))
{
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
{
if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NOR");
else if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NAND");
else
kal_sprintf(TraceTmpBuf, "Dev:Card");
memset(TraceTmpBuf+strlen((char *)TraceTmpBuf)+1, 0, 2);
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, RTF_INVALID_SECTOR_SIZE, NULL, (BYTE *)TraceTmpBuf);
}
#endif
XRAISE(RTF_INVALID_SECTOR_SIZE);
}
Dev->DevData.SectorSize = Result;
Dev->DevData.SectorShift = 0;
while ((1 << Dev->DevData.SectorShift) < Dev->DevData.SectorSize)
Dev->DevData.SectorShift++;
break;
default:
if (Flags & NO_RAISE)
{
Result = XVALUE;
XHANDLED;
}
break;
case XFINALLY:
RTFSYSLockMutex(RTFLock, RTF_INFINITE);
break;
XEND
if (Result >= RTF_NO_ERROR)
{
/* Modify for write protect issue, Karen Hsu, 2004/04/07, MOD START */
if(GetDiskGeometry(Dev, &Dev->DevData.Geometry, &Dev->DevData.MediaDescriptor) == RTF_WRITE_PROTECTION)
Dev->DeviceFlags |= MT_DEVICE_WRITE_PROTECT;
else
Dev->DeviceFlags &= ~MT_DEVICE_WRITE_PROTECT;
//GetDiskGeometry(Dev, &Dev->DevData.Geometry, &Dev->DevData.MediaDescriptor);
/* Modify for write protect issue, Karen Hsu, 2004/04/07, MOD END */
/* Add for usb normal mode access, , 2005/12/01, ADD START */
if (Dev->DeviceNumber == gFS_DeviceNumOfSYSDRV)
{
Dev->DeviceFlags |= MT_DEVICE_NO_EXPORT;
}
/* Add for usb normal mode access, , 2005/12/01, ADD END */
Dev->DevData.MountState = Mounted;
}
/* Reserve drive name for mount error device, Karen Hsu, 2004/03/04, ADD START */
else
{
if(GetDiskGeometry(Dev, &Dev->DevData.Geometry, &Dev->DevData.MediaDescriptor))
{
if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
NorPartition = KAL_TRUE;
else if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
NandPartition = KAL_TRUE;
}
}
/* Reserve drive name for mount error device, Karen Hsu, 2004/03/04, ADD END */
return Result;
}
/*-----------------------------------*/
static int INTERN ShutDown(RTFDevice * Dev)
{
int volatile Result;
RTFSYSFreeMutex(RTFLock);
XTRY
case XCODE:
CheckMedia(Dev);
Result = Dev->Driver->ShutDown(Dev->DriverData);
break;
default:
Result = XVALUE;
XHANDLED;
break;
case XFINALLY:
RTFSYSLockMutex(RTFLock, RTF_INFINITE);
break;
XEND
return Result;
}
/*-----------------------------------*/
static int INTERN ReadSectors(RTFDevice * Dev, void * Data, RTFSector Sector, UINT Sectors, DWORD Flags)
{
int volatile Result;
RTFSYSFreeMutex(RTFLock);
XTRY
case XCODE:
CheckMedia(Dev);
if (Dev->DevData.ErrorCondition < RTF_NO_ERROR)
{
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
{
if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NOR, Sector: %d, Sectors: %d", Sector, Sectors);
else if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NAND, Sector: %d, Sectors: %d", Sector, Sectors);
else
kal_sprintf(TraceTmpBuf, "Dev:Card, Sector: %d, Sectors: %d", Sector, Sectors);
memset(TraceTmpBuf+strlen((char *)TraceTmpBuf)+1, 0, 2);
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, Dev->DevData.ErrorCondition, NULL, (BYTE *)TraceTmpBuf);
}
#endif
XRAISE(Dev->DevData.ErrorCondition);
}
if (Dev->DevData.MountState < Mounted)
{
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
{
if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NOR, Sector: %d, Sectors: %d", Sector, Sectors);
else if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NAND, Sector: %d, Sectors: %d", Sector, Sectors);
else
kal_sprintf(TraceTmpBuf, "Dev:Card, Sector: %d, Sectors: %d", Sector, Sectors);
memset(TraceTmpBuf+strlen((char *)TraceTmpBuf)+1, 0, 2);
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, RTF_DRIVE_NOT_READY, NULL, (BYTE *)TraceTmpBuf);
}
#endif
XRAISE(RTF_DRIVE_NOT_READY);
}
Result = Dev->Driver->ReadSectors(Dev->DriverData, Sector, Sectors, Data);
if (Result < RTF_NO_ERROR)
{
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
{
if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NOR, Sector: %d, Sectors: %d", Sector, Sectors);
else if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NAND, Sector: %d, Sectors: %d", Sector, Sectors);
else
kal_sprintf(TraceTmpBuf, "Dev:Card, Sector: %d, Sectors: %d", Sector, Sectors);
memset(TraceTmpBuf+strlen((char *)TraceTmpBuf)+1, 0, 2);
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, Result, NULL, (BYTE *)TraceTmpBuf);
}
#endif
XRAISE(Result);
}
break;
default:
if (((Flags & NO_CRITICAL) == 0) &&
(HandleCriticalError(Dev, XVALUE) == RTFRetry))
{
XHANDLED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -