📄 fatlite.c
字号:
/***********************************************************************************/
/* M-Systems Confidential */
/* Copyright (C) M-Systems Flash Disk Pioneers Ltd. 1995-2003 */
/* All Rights Reserved */
/***********************************************************************************/
/* NOTICE OF M-SYSTEMS OEM */
/* SOFTWARE LICENSE AGREEMENT */
/* */
/* THE USE OF THIS SOFTWARE IS GOVERNED BY A SEPARATE LICENSE */
/* AGREEMENT BETWEEN THE OEM AND M-SYSTEMS. REFER TO THAT AGREEMENT */
/* FOR THE SPECIFIC TERMS AND CONDITIONS OF USE, */
/* OR CONTACT M-SYSTEMS FOR LICENSE ASSISTANCE: */
/* E-MAIL = info@m-sys.com */
/***********************************************************************************/
/*
* $Log: V:/PVCSDB/DiskOnChip/archives/general storage/TrueFFS/src/fs/fatlite.c-arc $
*
* Rev 1.17 Jan 14 2004 22:35:36 oris
* Removed FL_USER_DUAL_FILENAMES compilation flag
*
* Rev 1.16 Jan 14 2004 22:30:16 oris
* Replaced old (5.x) TrueFFS variable types
* Several additional bug fixes in SureFS
*
* Rev 1.15 Dec 29 2003 10:50:06 oris
* Bug fix - Competability bug - mixed cased files were saved as short names
*
* Rev 1.14 Dec 22 2003 07:38:30 oris
* Bug fix - In case the next free cluster was cluster number 2 and it was the only free cluster left on the media , SureFS used to return that there is no more free space.
* Bug fix - SureFS no longer places the archive attribute to directories.
* Bug fix - flFindNextFile routine closes the search handle only when there are no more files in the directory. Any other error code, will not close the search handle.
* Bug fix - Accessing a file that resides on the same directory sector but on a diffrent disk partition (BDTL) might cause cross link problems.
* Changed the short file name entry of a file with a long name to all '_'.
*
*
* Rev 1.13 Dec 04 2003 12:49:28 oris
* SureFS will now allow the use of the last 2 clusters of the media.
*
* Rev 1.12 Dec 01 2003 16:08:10 oris
* Bug fix - SureFS used to allow creation of directories with the same name but diffrent case.
*
* Rev 1.11 Nov 09 2003 17:07:04 OmerK
* Bug fix - Bad Root Directory handling in CloseFile routine
*
* Rev 1.10 Nov 06 2003 14:31:18 omerk
* Bug fix - Bad Root Directory handling in Long File Names.
*
* Rev 1.9 Oct 23 2003 20:56:38 OriS
* Bug fix - Missing check for continues '\' character
*
* Rev 1.6 Oct 20 2003 09:00:30 oris
* Improoved TrueFFS compatibility
*
* Rev 1.5 Sep 30 2003 17:57:34 oris
* Added SureFS and long file names support
*
* Rev 1.4 Sep 01 2003 19:08:48 oris
* - Removed tffsRAMXXX calls.
*
* Rev 1.3 May 18 2003 13:29:16 OriS
* Removed warnings
*
* Rev 1.2 May 11 2003 08:25:48 OriS
* Replaced all flAddLongToFarPointer calls with addToFarPointer.T?
*
* Rev 1.1 May 06 2003 11:53:00 OriS
* Changed TFFSCPY to tffsRAMcpy
* Changed TFFSCMP to tffsRAMcmp
* Changed TFFSSET to tffsRAMset
*
* Rev 1.0 Apr 09 2003 12:16:02 OriS
* Initial revision.
*
*/
#include "bddefs.h"
#if (defined(FL_FILES) && (FL_FILES > 0))
#include "dosformt.h"
/*******************************/
/* Available compilation flags */
/*******************************/
#define CHECK_LFN /* Indicating all long file names directory entries must */
/* be detected and repaired */
/* #define FL_SURE_FS_SHOW_TREE */
/**************************************************************************/
/* Local variables */
File fileTable[FL_FILES]; /* the file table */
/* The following arrays contain bit fields of ASCII character codes */
static const FLByte SfnAllowedChars[12] = { (FLByte)0xfa, /*Ascii 0x20-0x27*/
(FLByte)0x23, /*Ascii 0x28-0x2f*/
(FLByte)0xff, /*Ascii 0x30-0x37*/
(FLByte)0x03, /*Ascii 0x38-0x3f*/
(FLByte)0xff, /*Ascii 0x40-0x47*/
(FLByte)0xff, /*Ascii 0x48-0x4f*/
(FLByte)0xff, /*Ascii 0x50-0x57*/
(FLByte)0xd7, /*Ascii 0x58-0x5f*/
(FLByte)0x01, /*Ascii 0x60-0x67*/
(FLByte)0x00, /*Ascii 0x68-0x6f*/
(FLByte)0x00, /*Ascii 0x70-0x77*/
(FLByte)0xf8}; /*Ascii 0x78-0x7f*/
static const FLByte LfnAllowedChars[12] = { (FLByte)0xfb, /*Ascii 0x20-0x27*/
(FLByte)0x3b, /*Ascii 0x28-0x2f*/
(FLByte)0xff, /*Ascii 0x30-0x37*/
(FLByte)0x2b, /*Ascii 0x38-0x3f*/
(FLByte)0xff, /*Ascii 0x40-0x47*/
(FLByte)0xff, /*Ascii 0x48-0x4f*/
(FLByte)0xff, /*Ascii 0x50-0x57*/
(FLByte)0xff, /*Ascii 0x58-0x5f*/
(FLByte)0xff, /*Ascii 0x60-0x67*/
(FLByte)0xff, /*Ascii 0x68-0x6f*/
(FLByte)0xff, /*Ascii 0x70-0x77*/
(FLByte)0x6f}; /*Ascii 0x78-0x7f*/
/* Fat-lite specific macros */
#define directory ((DirectoryEntry *) vol.volBuffer.flData)
#define PATH_BUFF_CHARS (PATH_CHARACTERS_MAX_NUM + 1)
#define SUFF_BUFF_SIZE 100
#define MAX_TEST_LEVEL 2 /* perimit maximum suffix equal to 1599 */
#define MAX_SHORT_NAME_SUFFIX 999
#define MAX_SUFFIX_IDX(level) ((SUFF_BUFF_SIZE << 3) * level)
#define MIN_SUFFIX_IDX(level) ((SUFF_BUFF_SIZE << 3) * (level - 1))
#define MAX_DIGITS_NUM 7
#define FL_DEFAULT_SHORT_NAME (const FLByte *)("___________")
#define FLIsDigit(val) (((val) >= '0') && ((val) <= '9'))
#define FLIsLower(val) (((val) >= 'a') && ((val) <= 'z'))
#define FLIsUpper(val) (((val) >= 'A') && ((val) <= 'Z'))
#define FLIsAlpha(val) (FLIsUpper(val) || FLIsLower(val))
#define FLToLower(val) (FLIsUpper(val) ? (val-('A'-'a')) : (val))
#define FLToUpper(val) (FLIsLower(val) ? (val+('A'-'a')) : (val))
#define LFN_ORDER_NUM(entry) ((FLByte)(((LfnDirectoryEntry *)(entry))->orderNum & 0x1f))
#define IS_LAST_LFN_ENTRY(entry) ((FLByte)(((LfnDirectoryEntry *)(entry))->orderNum & 0x40))
#define SET_LAST_LFN_ENTRY(entry) (((LfnDirectoryEntry *)(entry))->orderNum |= 0x40)
/* Calculates offset in bytes based on sector number and index in sector */
#define CALC_ENTRY_OFFSET(sector, idx) (((sector) << FL_SECTOR_SIZE_BITS) + \
((idx) * sizeof(DirectoryEntry)))
#define CALC_SECTOR_FROM_OFFSET(offset) ((offset) >> FL_SECTOR_SIZE_BITS)
#define CALC_INDEX_FROM_OFFSET(offset) (((offset) % FL_SECTOR_SIZE) / sizeof(DirectoryEntry))
/* Number of directory entries required to contain the long file name. */
/* This number does not include a short form entry */
#define LFN_ENTRIES_NUM(chars) ((chars)? ((chars) / UNICODE_CHAR_PER_LFN_ENTRY + \
(((chars) % UNICODE_CHAR_PER_LFN_ENTRY)? 1: 0)): 0)
/* Note - Some instances do not use IS_INCLUDED. In order to change */
/* it, search the file for the IS_INCLUDED macro. The instance where */
/* we do not use it, there is a comment with the "IS_INCLUDED" word */
#define IS_INCLUDED(arr, ch) \
((arr)[((ch) - ' ') >> 3] & ((FLDword)1 << (((ch) - ' ') & 7)))
enum { LFN_ENTRY_READ, LFN_ENTRY_WRITE };
#define FL_FIRST_VALID_CLUSTER 2
#define FL_LAST_VALID_CLUSTER ( vol.maxCluster + FL_FIRST_VALID_CLUSTER )
#define IsValidCluster(C) ( ( (C) >= FL_FIRST_VALID_CLUSTER ) && ( (C) < FL_LAST_VALID_CLUSTER ) )
/* Local variables */
#ifdef FL_NO_LONG_FILENAMES_SUPPORT
static FLWchar pathBuff[2][PATH_BUFF_CHARS], nameBuff[LFN_NAME_MAX_CHARACTERS + 1]; /* ORI TO CHECK STATIC*/
#endif
/* Exported functions - forward definition */
FLStatus closeFile(File *file);
FLStatus flushBuffer(Volume vol);
/* Local functions - forward definition */
static void setCurrentDateTime(DirectoryEntry *dirEntry);
static FLStatus updateSector(Volume vol, SectorNo sectorNo, FLBoolean read);
static FLStatus setFATentry(Volume vol, unsigned cluster, unsigned entry);
static FLStatus allocateCluster(File *file);
static FLStatus extendDirectory(File *file, unsigned ownerDir);
static FLStatus readMultiSector( Volume vol, File *file, FLDword stillToRead, SectorNo* sectors);
static FLStatus writeMultiSector(Volume vol, File *file, FLDword stillToWrite,
SectorNo* sectors);
static FLStatus findDirEntry(Volume *pVol, FLWchar FAR1 *path, File *file);
static FLStatus findFileHdlr(Volume vol, File *file, IOreq FAR2 *ioreq);
static FLStatus openFileHdlr( Volume vol, IOreq FAR2 *ioreq);
static FLStatus findFirstFileHdlr(Volume vol, IOreq FAR2 *ioreq);
static FLStatus findNextFileHdlr(File *file, IOreq FAR2 *ioreq);
static FLStatus deleteFileHdlr(Volume vol, IOreq FAR2 *ioreq, FLBoolean isDirectory);
static FLStatus joinFileHdlr (File *file, IOreq FAR2 *ioreq);
static FLStatus renameFileHdlr(Volume vol, IOreq FAR2 *ioreq);
static FLStatus splitFileHdlr (File *file, IOreq FAR2 *ioreq);
static FLStatus makeDirHdlr(Volume vol, IOreq FAR2 *ioreq);
static unsigned getFatSector( Volume *pVol, unsigned entry);
static FLStatus getPreviousSectorNo( File *file);
static FLStatus getNextSectorNo( File *file);
static FLDword getLfnName( FLPathSegment *path, LfnDirectoryEntry *lfnEntry,
FLDword entriesNum, FLLfnSearch *lfn);
static void getSfnString( FLPathSegment *str, FLByte buff[NAME_8_3_MAX_LENGTH + 1]);
static FLStatus setSfnName( const FLByte *str, DirectoryEntry *entry);
static void getSfnName( DirectoryEntry *entry, FLWchar sfnName[NAME_8_3_MAX_LENGTH + 1]);
static FLByte calcLfnChecksum( const DirectoryEntry *entry);
static FLStatus setLfnName( FLPathSegment *str, File *file);
static FLDword readLfnEntryChars( LfnDirectoryEntry *entry, FLSWord *buff, FLWord size);
static void writeLfnEntryChars( LfnDirectoryEntry *entry, FLWchar *str, FLSWord length);
static int lfnToSfn( FLPathSegment *str, FLByte name[NAME_8_3_MAX_LENGTH + 1],
FLWord suffix);
static FLWord compareSfnWithSuffix( DirectoryEntry *entry, FLByte *name);
static FLStatus fillLfnEntries( FLPathSegment *lfnStr, File *file, FLByte checksum);
static FLWord suffBuffIndexToSuffix( FLWord idx, FLByte val, FLSWord level);
static DirectoryEntry FAR0 *treatNameInSector( FLPathSegment *path, DirectoryEntry FAR0 *dirEntry,FLLfnSearch *lfn );
static FLSDword FLStringToLong( const FLByte *nptr );
static FLDword FLNumberToString( FLByte *buffer, FLWord num );
#ifdef FL_LONG_FILENAMES_ASCII_SUPPORT
static FLStatus asciiFindFile(Volume *pVol, File *file, IOreq FAR2 *ioreq);
static FLStatus asciiOpenFile(Volume *pVol, IOreq FAR2 *ioreq);
static FLStatus asciiFindFirstFile(Volume *pVol, IOreq FAR2 *ioreq);
static FLStatus asciiFindNextFile(File *file, IOreq FAR2 *ioreq);
static FLStatus asciiDeleteFile(Volume *pVol, IOreq FAR2 *ioreq, FLBoolean isDirectory);
static FLStatus asciiJoinFile (File *file, IOreq FAR2 *ioreq);
static FLStatus asciiRenameFile(Volume *pVol, IOreq FAR2 *ioreq);
static FLStatus asciiSplitFile (File *file, IOreq FAR2 *ioreq);
static FLStatus asciiMakeDir(Volume *pVol, IOreq FAR2 *ioreq);
#endif /* FL_LONG_FILENAMES_ASCII_SUPPORT */
#ifdef FL_NO_LONG_FILENAMES_SUPPORT
static FLStatus simpleFindFile(Volume *pVol, File *file, IOreq FAR2 *ioreq);
static FLStatus simpleOpenFile(Volume *pVol, IOreq FAR2 *ioreq);
static FLStatus simpleFindFirstFile(Volume *pVol, IOreq FAR2 *ioreq);
static FLStatus simpleFindNextFile(File *file, IOreq FAR2 *ioreq);
static FLStatus simpleDeleteFile(Volume *pVol, IOreq FAR2 *ioreq, FLBoolean isDirectory);
static FLStatus simpleJoinFile (File *file, IOreq FAR2 *ioreq);
static FLStatus simpleRenameFile(Volume *pVol, IOreq FAR2 *ioreq);
static FLStatus simpleSplitFile (File *file, IOreq FAR2 *ioreq);
static FLStatus simpleMakeDir(Volume *pVol, IOreq FAR2 *ioreq);
#endif /* FL_NO_LONG_FILENAMES_SUPPORT */
#ifndef FL_NO_SURE_FS_SUPPORT
static FLStatus reverseFreeFatEntries( Volume vol, unsigned firstCluster,
FLSDword numClusters, unsigned lastCluster);
static FLStatus setAttentionFlag( Volume *pVol, DirectoryEntry *entry, FLByte attFlag);
static void getAttentionFlag( const DirectoryEntry *entry, FLByte *attFlag);
static FLStatus getGlobalAttentionFlag( Volume *pVol, unsigned *flag);
static FLStatus repairFile(File *file, FLByte attFlag);
static FLStatus scanTree(Volume vol);
#endif /* FL_NO_SURE_FS_SUPPORT */
/* Forward declaration */
static FLStatus deleteFileEntries( File *file);
static FLStatus setGlobalAttentionFlag( Volume *pVol, unsigned flag);
static DirectoryEntry FAR0 *findFileName( const FLPathSegment *pathInfo,
DirectoryEntry FAR0 *dirEntry,
FLLfnSearch *lfn );
static FLBoolean findSpaceInSector( const FLPathSegment *pathInfo,
DirectoryEntry FAR0 *dirEntry,
FLLfnSearch *lfn );
static DirectoryEntry FAR0 *getFirstFileName( FLPathSegment *pathInfo,
const DirectoryEntry FAR0 *dirEntry,
FLLfnSearch *lfn );
static FLStatus setNameInDirEntries(FLWchar *path, File *file);
static int checkLfnName( LfnDirectoryEntry FAR0 *lfnEntry,
FLDword entriesNum,
FLLfnSearch *lfnSearch);
#ifdef FL_NO_LONG_FILENAMES_SUPPORT
/*-------------------------------------------------------------------------------------------
* s i m p l e P a t h T o U n i c o d e
* Translates FLSimplePath null terminated array to Unicode string.
* Input: path - array to be translated to Unicode string.
* Output: buff - buffer to receive translated Unicode string
* Return: flOK or flPathTooLong
*------------------------------------------------------------------------------------------*/
static FLStatus simplePathToUnicode( FLWchar *buff, const FLSimplePath *path)
{
FLSWord i, j, dotIdx;
FLByte *ptr;
FLStatus ret = flOK;
for (j = 0, ptr = (FLByte *)path;
*ptr && (j < PATH_CHARACTERS_MAX_NUM); ptr += sizeof(FLSimplePath)) {
buff[j++] = (FLWchar)'\\';
for (i = 0; (i < SHORT_NAME_MAX_LENGTH) && (j < PATH_CHARACTERS_MAX_NUM); i++) {
if (ptr[i] != ' ')
buff[j++] = (FLWchar)ptr[i];
}
dotIdx = j;
if (j < PATH_CHARACTERS_MAX_NUM)
buff[j++] = (FLWchar)'.';
for (; (i < (SHORT_NAME_MAX_LENGTH + EXTENSION_MAX_LENGTH))
&& (j < PATH_CHARACTERS_MAX_NUM); i++) {
if (ptr[i] != ' ')
buff[j++] = (FLWchar)ptr[i];
}
if ((j - dotIdx) == 1)
j = dotIdx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -