⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdfat.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 4 页
字号:
    return dwEntries;
}

static DWORD ConvertFATEntriesToBytes(DWORD dwPartNo, DWORD dwEntries){
    DWORD dwBytes = FAT_ERROR;
    switch(Partition[dwPartNo].FileSystem){
    case PART_FAT12:
        dwBytes = FAT12_ENTRIES2BYTES(dwEntries);
        break;
    case PART_FAT16:
        dwBytes = FAT16_ENTRIES2BYTES(dwEntries);
        break;
    case PART_FAT32:
        dwBytes = FAT32_ENTRIES2BYTES(dwEntries);
        break;
    }
    return dwBytes;
}

static BOOL IsFreeFATEntry(DWORD dwPartNo, DWORD dwCluster){
    BOOL isFree = FALSE;
    switch(Partition[dwPartNo].FileSystem){
    case PART_FAT12:
        isFree = FAT12_ISFREE(dwCluster);
        break;
    case PART_FAT16:
        isFree = FAT16_ISFREE(dwCluster);
        break;
    case PART_FAT32:
        isFree = FAT32_ISFREE(dwCluster);
        break;
    }
    return isFree;
}

static BOOL IsAllocFATEntry(DWORD dwPartNo, DWORD dwCluster){
    BOOL isAlloc = FALSE;
    switch(Partition[dwPartNo].FileSystem){
    case PART_FAT12:
        isAlloc = FAT12_ISALLOC(dwCluster, Partition[dwPartNo].FATEntryNumber);
        break;
    case PART_FAT16:
        isAlloc = FAT16_ISALLOC(dwCluster, Partition[dwPartNo].FATEntryNumber);
        break;
    case PART_FAT32:
        isAlloc = FAT32_ISALLOC(dwCluster, Partition[dwPartNo].FATEntryNumber);
        break;
    }
    return isAlloc;
}

static BOOL IsDefectFATEntry(DWORD dwPartNo, DWORD dwCluster){
    BOOL isDefect = FALSE;
    switch(Partition[dwPartNo].FileSystem){
    case PART_FAT12:
        isDefect = FAT12_ISDEFECT(dwCluster);
        break;
    case PART_FAT16:
        isDefect = FAT16_ISDEFECT(dwCluster);
        break;
    case PART_FAT32:
        isDefect = FAT32_ISDEFECT(dwCluster);
        break;
    }
    return isDefect;
}

static BOOL IsEndFATEntry(DWORD dwPartNo, DWORD dwCluster){
    BOOL isEnd = FALSE;
    switch(Partition[dwPartNo].FileSystem){
    case PART_FAT12:
        isEnd = FAT12_ISEND(dwCluster);
        break;
    case PART_FAT16:
        isEnd = FAT16_ISEND(dwCluster);
        break;
    case PART_FAT32:
        isEnd = FAT32_ISEND(dwCluster);
        break;
    }
    return isEnd;
}

static BOOL FillCacheFATEntries(DWORD dwPartNo, DWORD dwCluster){
    DWORD dwByteOffset, dwReadBytes;
    // 1.invalidate CacheFATEntryBegin&CacheFATEntryEnd
    Partition[dwPartNo].CacheFATEntryBegin = FAT_ERROR;
    Partition[dwPartNo].CacheFATEntryEnd   = FAT_ERROR;
    // 2.convert dwCluster to dwByteOffset
    dwByteOffset = ConvertFATEntriesToBytes(dwPartNo, dwCluster);
    // 3.read FAT entry from partition
    dwReadBytes = FATReadPartition(dwPartNo, Partition[dwPartNo].CacheFATEntry,
        sizeof(Partition[dwPartNo].CacheFATEntry), Partition[dwPartNo].StartingFATEntry+dwByteOffset);
    // 4.check result
    if(dwReadBytes==FAT_ERROR || dwReadBytes<GetFATEntryBytes(dwPartNo)){
        return FALSE;
    }
    // 5.update cache variable
    Partition[dwPartNo].CacheFATEntryBegin = dwCluster;
    Partition[dwPartNo].CacheFATEntryEnd   = dwCluster+ConvertBytesToFATEntries(dwPartNo, dwReadBytes);
    return TRUE;
}

static DWORD GetFATEntry(DWORD dwPartNo, DWORD dwCluster){
    // check parameter
    if(dwCluster >= Partition[dwPartNo].FATEntryNumber){
        return FAT_ERROR;
    }
    // check cache miss and fill new entries, if need
    if(dwCluster<Partition[dwPartNo].CacheFATEntryBegin || dwCluster>=Partition[dwPartNo].CacheFATEntryEnd){
        if(!FillCacheFATEntries(dwPartNo, dwCluster)){ // fill cache
            return FAT_ERROR;
        }
    }
    // dispatch according file system type
    switch(Partition[dwPartNo].FileSystem){
    case PART_FAT12:
        return FAT12_GETENTRY(Partition[dwPartNo].CacheFATEntry, Partition[dwPartNo].CacheFATEntryBegin, dwCluster);
    case PART_FAT16:
        return FAT16_GETENTRY(Partition[dwPartNo].CacheFATEntry, Partition[dwPartNo].CacheFATEntryBegin, dwCluster);
    case PART_FAT32:
        return FAT32_GETENTRY(Partition[dwPartNo].CacheFATEntry, Partition[dwPartNo].CacheFATEntryBegin, dwCluster);
    default:
        return FAT_ERROR;
    }
}

static DWORD CalculateFATEntries(DWORD dwPartNo, DWORD dwStart){
    DWORD dwCount = 0;
    while(IsAllocFATEntry(dwPartNo, dwStart)){
        ++dwCount;
        dwStart = GetFATEntry(dwPartNo, dwStart);
    }
    if(!IsEndFATEntry(dwPartNo, dwStart)){
        dwCount = FAT_ERROR;
    }
    return dwCount;
}


// help routine for file
static VOID ClearFileInfo(PFILEINFO pFileInfo){
    pFileInfo->PartitionNumber = FAT_ERROR;
    pFileInfo->StartingCluster = FAT_ERROR;
    pFileInfo->FileLength      = FAT_ERROR;
    pFileInfo->FileAttribute   = FAT_ERROR;
    pFileInfo->CurrentCluster  = FAT_ERROR;
    pFileInfo->CurrentPostion  = FAT_ERROR;
}

static VOID InitFileInfo(PFILEINFO pFileInfo, DWORD dwPartNo, DWORD dwStartingCluster, DWORD dwFileLength, DWORD dwAttribute){
    if(dwFileLength == 0){
        // assume length align on cluster length
        DWORD dwCount = CalculateFATEntries(dwPartNo, dwStartingCluster);
        if(dwCount != FAT_ERROR){
            dwFileLength = Partition[dwPartNo].LengthPerCluster*dwCount;
        }
    }
    pFileInfo->PartitionNumber = dwPartNo;
    pFileInfo->StartingCluster = dwStartingCluster;
    pFileInfo->FileLength      = dwFileLength;
    pFileInfo->FileAttribute   = dwAttribute;
    pFileInfo->CurrentCluster  = dwStartingCluster;
    pFileInfo->CurrentPostion  = 0;
}


// help routine for directory
static UINT8 ComputeCheckSum(PUINT8 pName){
    int i;
    UINT8 Sum = 0;

    for(i = 0; i < DIRENTRY_NAMELEN+DIRENTRY_EXTENSIONLEN; ++i){
        // NOTE: The operation is an unsigned char rotate right
        Sum = ((Sum&1)?0x80:0) + (Sum>>1) + *pName++;
    }
    return Sum;
}

static DWORD GetDirEntryNumber(PFILEINFO pFileInfo){
    return FATGetFileSize(pFileInfo)/sizeof(RAWDIRENTRY);
}

static BOOL GetDirEntry(PFILEINFO pFileInfo, PDIRENTRY pDirEntry, DWORD dwPos){
    RAWDIRENTRY drEntry;
    // set all field to zero
    memset(pDirEntry, 0, sizeof(*pDirEntry));
    // seek to right position
    if(dwPos != 0){
        if(!FATSetFilePos(pFileInfo, dwPos*sizeof(drEntry))){
            return FALSE;
        }
    }
    // read raw entry
    if(FATReadFile(pFileInfo, &drEntry, sizeof(drEntry)) != sizeof(drEntry)){
        return FALSE;
    }
    // according entry type, fill in
    pDirEntry->Attribute = drEntry.Attribute;
    if(drEntry.Attribute == DIRENTRY_LONGNAME){ // long format
        // filename
        int i, j = 0;
        for(i = 0; i<DIRENTRY_NAMELEN1 && drEntry.Name1[i]!=DIRENTRY_PADDING; ++i){
            pDirEntry->FileName[j++] = (CHAR)drEntry.Name1[i];
        }
        for(i = 0; i<DIRENTRY_NAMELEN2 && drEntry.Name2[i]!=DIRENTRY_PADDING; ++i){
            pDirEntry->FileName[j++] = (CHAR)drEntry.Name2[i];
        }
        for(i = 0; i<DIRENTRY_NAMELEN3 && drEntry.Name3[i]!=DIRENTRY_PADDING; ++i){
            pDirEntry->FileName[j++] = (CHAR)drEntry.Name3[i];
        }
        // checksum&ordinal
        pDirEntry->CheckSum = drEntry.CheckSum;
        pDirEntry->Ordinal  = drEntry.Ordinal;
    }
    else{ // short format
        // filename
        int i, j = 0;
        for(i = 0; i<DIRENTRY_NAMELEN && drEntry.Name[i]!=DIRENTRY_ENDCHAR; ++i){
            pDirEntry->FileName[j++] = drEntry.Name[i];
        }
        for(i = 0; i<DIRENTRY_EXTENSIONLEN && drEntry.Extension[i]!=DIRENTRY_ENDCHAR; ++i){
            if(i == 0){ // add '.'
                pDirEntry->FileName[j++] = '.';
            }
            pDirEntry->FileName[j++] = drEntry.Extension[i];
        }
        // checksum
        pDirEntry->CheckSum = ComputeCheckSum(drEntry.Name);
        // create time
        pDirEntry->Created.wYear         = DIRENTRY_YEAR(drEntry.CreatedDate);
        pDirEntry->Created.wMonth        = DIRENTRY_MONTH(drEntry.CreatedDate);
        pDirEntry->Created.wDay          = DIRENTRY_DAY(drEntry.CreatedDate);
        pDirEntry->Created.wHour         = DIRENTRY_HOUR(drEntry.CreatedTime);
        pDirEntry->Created.wMinute       = DIRENTRY_MINUTE(drEntry.CreatedTime);
        pDirEntry->Created.wSecond       = DIRENTRY_SECONDEX(drEntry.CreatedTime, drEntry.CreatedTimeTenth);
        pDirEntry->Created.wMilliseconds = DIRENTRY_MILLISECOND(drEntry.CreatedTimeTenth);
        // access time
        pDirEntry->Accessed.wYear  = DIRENTRY_YEAR(drEntry.AccessedDate);
        pDirEntry->Accessed.wMonth = DIRENTRY_MONTH(drEntry.AccessedDate);
        pDirEntry->Accessed.wDay   = DIRENTRY_DAY(drEntry.AccessedDate);
        // modify time
        pDirEntry->Modified.wYear         = DIRENTRY_YEAR(drEntry.ModifiedDate);
        pDirEntry->Modified.wMonth        = DIRENTRY_MONTH(drEntry.ModifiedDate);
        pDirEntry->Modified.wDay          = DIRENTRY_DAY(drEntry.ModifiedDate);
        pDirEntry->Modified.wHour         = DIRENTRY_HOUR(drEntry.ModifiedTime);
        pDirEntry->Modified.wMinute       = DIRENTRY_MINUTE(drEntry.ModifiedTime);
        pDirEntry->Modified.wSecond       = DIRENTRY_SECOND(drEntry.ModifiedTime);
        // cluster&length
        pDirEntry->StartingCluster = (drEntry.StartingClusterHi<<16)+drEntry.StartingCluster;
        pDirEntry->FileLength      = drEntry.FileLength;
    }
    return TRUE;
}

static BOOL GetDirEntryEx(PFILEINFO pFileInfo, PDIRENTRY pDirEntry){
    int i, j = 0;
    DWORD dwPrevPos;
    DIRENTRY drEntry[DIRENTRY_MAXCOMP];
    while(1){
        // 1.save current position
        dwPrevPos = FATGetFilePos(pFileInfo);
        // 2.try to get one entry
        if(!GetDirEntry(pFileInfo, pDirEntry, 0)){
            return FALSE;
        }
        // 3.short format? break loop
        if(pDirEntry->Attribute != DIRENTRY_LONGNAME){
            break;
        }
        // 4.otherwise, copy to DirEntry
        if(j < DIRENTRY_MAXCOMP){
            memcpy(&drEntry[j++], pDirEntry, sizeof(*pDirEntry));
        }
    }
    if(j != 0){ // long format
        CHAR FileName[MAX_PATH+1];
        FileName[0] = 0;
        // 1.verify last component flag
        if(!(drEntry[0].Ordinal&DIRENTRY_LASTCOMP)){
            return TRUE; // no flag
        }
        // 2.form long file name
        for(i = j-1; i >= 0; --i){
            // verify ordinal
            if((drEntry[i].Ordinal&DIRENTRY_COMPMASK) != j-i){
                return TRUE; // wrong ordinal
            }
            // verify checksum
            if(drEntry[i].CheckSum != pDirEntry->CheckSum){
                return TRUE; // wrong checksum
            }
            strcat(FileName, drEntry[i].FileName);
        }
        // 3.change to long file name
        strcpy(pDirEntry->FileName, FileName);
        // 4.restore file position for next operation
        FATSetFilePos(pFileInfo, dwPrevPos);
    }
    return TRUE;
}

// if match, it will update *ppCurItem to next item
static BOOL CompareFileName(PCSTR pFileName, PCSTR* ppCurItem){
    PCSTR pCurItem;
    for(pCurItem = *ppCurItem; *pFileName != 0; ++pCurItem, ++pFileName){
        if(*pCurItem == 0){ // pCurItem finish, but pFileName not
            return FALSE;
        }
        if(toupper(*pCurItem) != toupper(*pFileName)){ // no match
            return FALSE;
        }
    }
    // check endpoint
    switch(*pCurItem){
    case '/':
    case '\\':
        ++pCurItem; // skip separator
        // go through
    case '\0':
        *ppCurItem = pCurItem; // update to next
        return TRUE;
    }
    return FALSE;
}

static BOOL FindRootDirEntry(PFILEINFO pFileInfo, PCSTR* ppCurItem){
    DWORD dwPartNo = FAT_ERROR, dwLoop;
    // find partition No.
    if((*ppCurItem)[0]!=0 && (*ppCurItem)[1]==':'){ // specify disk no.
        CHAR DiskName[] = "A:"; // search from A:
        for(dwLoop = 0; dwLoop < PartitionNumber; ++dwLoop, ++DiskName[0]){
            // compare root, if match update ppCurItem to next
            if(CompareFileName(DiskName, ppCurItem)){
                dwPartNo = dwLoop;
                break;
            }
        }
    }
    else if(PartitionNumber > 0){
        dwPartNo = 0; // default partition is zero
        // search active partition
        for(dwLoop = 0; dwLoop < PartitionNumber; ++dwLoop){
            if(Partition[dwLoop].Bootable){
                dwPartNo = dwLoop; // active partition is high priority
                break;
            }
        }
        CompareFileName("", ppCurItem); // skip optional first '/'
    }
    // init pFileInfo
    if(dwPartNo != FAT_ERROR){
        if(Partition[dwPartNo].FileSystem == PART_FAT32){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -