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

📄 tmfat32.c

📁 PNX1500上Fat32文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * Copyright (C) 2003 Koninklijke Philips Electronics N.V.,
 * All Rights Reserved.
 *
 * This source code and any compilation or derivative thereof is the
 * proprietary information of Koninklijke Philips Electronics N.V.
 * and is confidential in nature.
 * Under no circumstances is this software to be exposed to or placed
 * under an Open Source License of any type without the expressed
 * written permission of Koninklijke Philips Electronics N.V.
 *
 *----------------------------------------------------------*/
/*!
 *      \file           tmFat32.c
 *
 *      This file implements the tmFat32 API.
 *
 */
/*-----------------------------------------------------------
 *
 *      %version:       ds08#22 %
 *      instance:       DS_4
 *      %date_created:  Thu Nov 09 17:40:12 2006 %
 *
 */
 //-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Standard include files:
//-----------------------------------------------------------------------------
//

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>

//-----------------------------------------------------------------------------
// Project include files:
//-----------------------------------------------------------------------------
//

#if USE_GENERIC_C
#include <unistd.h>
#include <dirent.h>
#else
#include <tmNxTypes.h>
#include <tmNxCompId.h>
#include <tmDbg.h>
#include <tmbslCore.h>
#include <tmosal.h>
#include <tmbslIde.h>
#include <IODrivers.h>
#include <sys/syslimits.h>
#include <tmFat32.h>
#include <tmFat32Device.h>
#include <tmFat32Ide.h>
#endif

#include <tmFat32Private.h>
#include <tmFat32Debug.h>
#include <tmFat32Ram.h>

//-----------------------------------------------------------------------------
// Types and defines:
//-----------------------------------------------------------------------------

// Set default device driver

#if USE_GENERIC_C || USE_SIMULATOR
#define TMFAT_DEFAULT_DEVICE      tmFat32_RamDevice
#else
#define TMFAT_DEFAULT_DEVICE      tmFat32_IdeDevice
#endif

#if 1   // Optimized to write as many contiguous clusters as possible
#define WRITE_METHOD    SET_CLUSTER_CONTENT_NOCACHE
#else   // Non-optimized to write one cluster at a time
#define WRITE_METHOD    SET_CLUSTER_CONTENT
#endif

typedef struct DSKSZTOSECPERCLUS 
{
    UInt32	DiskSize;
    UInt8	SecPerClusVal;
} DSKSZTOSECPERCLUS;

#define USE_FILE_SEARCH_RESULTS         0
#define USE_DIR_SEARCH_RESULTS          1
                                          
#define CLUSTER_TO_SECTOR(clus)    (gptmFat32_PrivateInfo->dataAreaBase + \
                                ((clus) - gptmFat32_PrivateInfo->rootDirCluster) * \
                                gptmFat32_PrivateInfo->sectorsPerCluster)
                                
//-----------------------------------------------------------------------------
// Global data:
//-----------------------------------------------------------------------------
//

extern tmFat32_Devices_t    tmFat32DeviceList[];    // List of supported devices

ptmFat32_FS_t   gptmFat32_PrivateInfo;

static tmFat32_FS_t *tmFat32_List = Null;   // List of mounted tmFat32 file systems.

#if USE_REENTRANCY
Bool gtmFat32_Locked = False;
#if defined(__TCS__)
tmosalMutexHandle_t gtmFat32_Lock;
#endif // defined(__TCS__)
#endif // USE_REENTRANCY

// Scratch buffers

static char         temp_cd[PATH_MAX+1];                    // 1024 + 1 Current directory
static UInt8        temp_buffer[32 * 1024];                 // 32K Biggest legal cluster
static char         temp_path[PATH_MAX+1];                  // 1024 + 1 Temp full pathname
static char         norm_path1[PATH_MAX+1];                 // 1024 + 1 Normalized pathname
static char         norm_path2[PATH_MAX+1];                 // 1024 + 1 Normalized pathname

static UInt8        temp_dir[DIR_ENTRY_SIZE * (0x3F + 1)];  // 2048 Max possible long name entries
                                                            // plus final short name entry
static UInt8        temp_dir2[DIR_ENTRY_SIZE * (0x3F + 1)]; // Another copy

static UInt16       temp_fname[256]; // Long file name (UCS2) is maximum 255, not including trailing NUL.

#if USE_MML
static tmFat32_FS_t temp_fs;       // So we can create a heap
#endif

// Illegal characters in a short name

static char illegal_short[] = {0x22, 0x2A, 0x2B, 0x2C, /* 0x2E, */ 0x2F, 
                               0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 
                               0x5B, 0x5C, 0x5D, 0x7C};

// Illegal characters in a long name
 
static char illegal_long[] =  {0x22, 0x2A, /* 0x2B , 0x2C, */ /* 0x2E, */ 0x2F, 
                               0x3A, /* 0x3B,*/ 0x3C, /*0x3D,*/ 0x3E, 0x3F, 
                               /*0x5B,*/ 0x5C, /*0x5D,*/ 0x7C};

//-----------------------------------------------------------------------------
// Internal Prototypes:
//-----------------------------------------------------------------------------
//

static void     UTIL_add_volume(tmFat32_FS_t * p);
static void     UTIL_delete_volume(tmFat32_FS_t * p);
static void     UTIL_date_time(int op, int what, UInt8 *d, time_t *tout, tmosalDateTime_t *tin);
static int      UTIL_get_short_name(UInt8 *src, String name);
static int      UTIL_get_long_name(UInt8 *src, String name);
static UInt8   *UTIL_get_cluster_address(UInt32 cluster);
static int      UTIL_fat_content(int op, UInt32 entry, UInt32 value, UInt32 *result);
static int      UTIL_find_file(String fullpath, ptmFat32_File_t info);
static int      UTIL_allocate_cluster(UInt32 *clust, UInt32 chain, Bool clear);
static Bool     UTIL_is_FAT(ptmFat32_FS_t p, UInt8 part_type);
static Bool     UTIL_is_FAT32(ptmFat32_FS_t p);
static int      UTIL_find_magic_sector(tmFat32_DeviceDriver_Read Read, 
                     tmFat32_FS_t *p,UInt64 *sector, UInt8  *secbuf);
static Bool     UTIL_find_partition(ptmFat32_FS_t p, UInt64 mbrBase, int index, int depth);
static int      UTIL_compare_dos_names(String s1, String s2);

// File I/O driver functions

static tmErrorCode_t   _IOD_Init (void);
static tmErrorCode_t   _IOD_Term (void);

static Int32           _IOD_Access (String path, Int32 mode);
static Int32           _IOD_Stat (String path, struct stat *buf);
static Int32           _IOD_Fstat ( Int32 file,  struct stat *buf);

static Int32           _IOD_Open ( String path, Int32 oflag,  Int32 mode);
static Int32           _IOD_Read ( Int32 file,  Pointer buf,  Int32 nbyte);
static Int32           _IOD_Seek ( Int32 file,  Int32 offset, Int32 whence);
static Int32           _IOD_Close ( Int32 file);
static Int32           _IOD_Seek ( Int32 file,  Int32 offset, Int32 whence);

static Int32           _IOD_Sync (void);
static Int32           _IOD_FSync (Int32  file);

static DIR*            _IOD_Opendir ( ConstString path );
static void            _IOD_Rewinddir( DIR*   dir  );
static struct dirent*  _IOD_Readdir  ( DIR*   dir  );
static Int32           _IOD_Closedir ( DIR*   dir);

static Int32           _IOD_Mkdir ( String path, Int32 mode );
static Int32           _IOD_Rmdir ( String path );
static Int32           _IOD_Unlink ( String path );
static Int32           _IOD_Move ( String src,  String dest );
static Int32           _IOD_Link ( String src,  String dest );
static Int32           _IOD_Fcntl ( Int32 file,  Int32 cmd,    Int32 flags);
static Int32           _IOD_Write ( Int32 file,  Pointer buf,  Int32 nbyte);

static tmErrorCode_t tmFat32_Term_ForReal(tmFat32_FS_t * p);

//-----------------------------------------------------------------------------
// Internal Functions
//-----------------------------------------------------------------------------
//
static tmErrorCode_t UTIL_Ucs2toUtf8(const UInt16 *ch, UInt8 *utf8)
{
  if(ch && (ch[0]==(UInt16)0xfeff || ch[0]==(UInt16)0xfffe)){
    ch++;
  }
  if(utf8==NULL) {
    int bytesNeeded = 0, i;

    for (i=0; ch[i]/* i<ch.length */; i++) {
      if (ch[i] < 0x80) {
        ++bytesNeeded;
      } else if (ch[i] < 0x0800) {
        bytesNeeded += 2;
      } else {
        bytesNeeded += 3;
      }
#if 0 /* This is only for UTF32? */
      if (ch[i] < 0x10000) {
        bytesNeeded += 3;
      }
      else {
        bytesNeeded += 4;
      }
#endif
    }
    return bytesNeeded;
  } else {
    int i, bytes;

    for(i=0, bytes = 0; ch[i]/* i<ch.length */; i++) {
      if(ch[i] < 0x80) {
        utf8[bytes++] = (UInt8)ch[i];
      } else if (ch[i] < 0x0800) {
        utf8[bytes++] = (UInt8)(ch[i]>> 6 | 0xC0);
        utf8[bytes++] = (UInt8)((ch[i] & 0x3F) | 0x80);
      } else {
        utf8[bytes++] = (UInt8)(ch[i]>> 12 | 0xE0);
        utf8[bytes++] = (UInt8)((ch[i]>> 6 & 0x3F) | 0x80);
        utf8[bytes++] = (UInt8)((ch[i] & 0x3F) | 0x80);
      }
#if 0 /* This is only for UTF32? */
      else if (ch[i] < 0x10000) {
        utf8[bytes++] = (UInt8)(ch[i]>> 12 | 0xE0);
        utf8[bytes++] = (UInt8)((ch[i]>> 6 & 0x3F) | 0x80);
        utf8[bytes++] = (UInt8)((ch[i] & 0x3F) | 0x80);
      }
      else {
        utf8[bytes++] = (UInt8)(ch[i]>> 18 | 0xF0);
        utf8[bytes++] = (UInt8)((ch[i]>> 12 & 0x3F) | 0x80);
        utf8[bytes++] = (UInt8)((ch[i]>> 6 & 0x3F) | 0x80);
        utf8[bytes++] = (UInt8)((ch[i] & 0x3F) | 0x80);
      }
#endif
    }
    utf8[bytes++] = 0; /* NULL-terminator */

    return TM_OK/* utf8 */;
  }
}

#if USE_MML

// tmml wrapper functions

static tmErrorCode_t UTIL_create_heap(UInt32 size, ptmmlMmspHandle_t heap)
{
    tmErrorCode_t rval;

// tmmlMmspNormal is for backward compatibility, not supposed to use it?
//    if((rval = tmmlCreate(heap, size, tmmlMmspNormal)) != TM_OK)
    if((rval = tmmlCreate(heap, size, tmmlMmspNone)) != TM_OK)
    {
        TMFAT_DEBUG1 ("tmmlCreate failed: rval = %#x\n", rval);
    }
    
    return rval;
}

static tmErrorCode_t UTIL_destroy_heap(ptmmlMmspHandle_t heap)
{
    tmErrorCode_t rval;

    if((rval = tmmlDelete(*heap)) != TM_OK)
    {
        TMFAT_DEBUG2 ("tmmlDelete failed: heap = %#x, rval = %#x\n", 
                        heap, rval);
    }
    else
    {
        *heap = 0;
    }
    
    return rval;
}

static pVoid UTIL_malloc(size_t size)
{
    ptmFat32_FS_t   p = GFS;
    tmErrorCode_t   rval;
    pVoid pReturn = Null;
    
    TMFAT_ASSERT (p != Null);

    rval = tmmlMalloc(p->heap, size, &pReturn, tmmlMallocCleared);
    if(rval == TM_OK)
    {
//        TMFAT_DEBUG1 ("UTIL_malloc: pReturn = %#x\n", pReturn);
    }
    else
    {
        TMFAT_DEBUG1 ("UTIL_malloc failed: Null, rval = %#x\n", rval);
    }
    return pReturn;
}

static void UTIL_free(pVoid pFree)
{
    tmmlFree(pFree);
}


#endif // USE_MML

// Cache utilities

// Flush cache. For FAT cache the sector number on the
// disk or the entire FAT cache. For DATA cache the cluster number
// or the entire DATA cache. If flag is FULL_FLUSH then the
// entire appropriate cache is flushed.

static tmErrorCode_t UTIL_flush_cache(int which, UInt32 cluster, UInt64 sector, int flag)
{
    tmErrorCode_t   status = TM_OK;
    ptmFat32_FS_t   p = GFS;
    UInt64          sec;
    UInt32          count;
    UInt32          i;
    UInt32          offset;
    Bool            doit;
    
    if (which == FAT_CACHE)
    {
        Int64      mirrorOffset;   // Sector offset to the mirror FAT from the active FAT
        
        if (p->fatMirroring)
        {
            if (p->activeFat == 0)
                mirrorOffset = p->fatSize;  // Mirror is second FAT
            else
                mirrorOffset = -p->fatSize; // Mirror is first FAT
        }
        else
        {
            mirrorOffset = 0;
        }

//        TMFAT_DEBUG2("Flushing FAT cache, (%s) sector=%llu.\n",
//                      flag == FULL_FLUSH ? "FULL" : "PARTIAL", sector);

        for (i = 0; i < p->fatNumSectors; i++)
        {
            if (flag == FULL_FLUSH)
            {
                doit = p->fatSectorDirty[i];
                sector = p->fatSector[i];
            }
            else
                doit = (sector == p->fatSector[i]) && p->fatSectorDirty[i];

            if (doit)
            {
                offset = i * (p->dev->Info->bytesPerSector / sizeof(UInt32));
                status = p->dev->Write(p->dev->Info, 
                                                    sector, 
                                                    1,
                                                    (UInt8 *) &p->fatCache[offset]);
                if (status != TM_OK)
                    goto done;
                    
                // Once more, with feeling
                
                if (p->fatMirroring)
                {
                    status = p->dev->Write(p->dev->Info, 
                                                        sector + mirrorOffset, 
                                                        1,
                                                        (UInt8 *) &p->fatCache[offset]);
                    if (status != TM_OK)
                        goto done;
                }
                
                p->fatSectorDirty[i] = False;
                if (flag != FULL_FLUSH)
                    break;
            }
        }
    }
    else
    {
//        TMFAT_DEBUG2("Flushing DATA cache, cluster=%u, %s.\n",
//                      cluster, (flag == FULL_FLUSH) ? "FULL" : "PARTIAL");

⌨️ 快捷键说明

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