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

📄 filesys.c

📁 picoos源码。The RTOS and the TCP/IP stack will be built automatically.
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 *  Copyright (c) 2004, Dennis Kuschel.
 *  All rights reserved. 
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote
 *      products derived from this software without specific prior written
 *      permission. 
 *
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 *  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 *  INDIRECT,  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 *  OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

/**
 * @file    filesys.c
 * @author  Dennis Kuschel
 * @brief   Simple file system for embedded devices
 *
 * This software is from http://mycpu.mikrocontroller.net.
 * Please send questions and bug reports to dennis_k@freenet.de.
 */

#include "filesys.h"


/*---------------------------------------------------------------------------
 *  DEFINES
 *-------------------------------------------------------------------------*/

#define FS_DRIVE_ID             "RamDrive"
#define FS_DRIVE_IDLEN          8
#define FS_MAXIMAGES            2

#ifndef FS_MAXFILES
#define FS_MAXFILES  10
#endif

#ifndef SYS_MTASK_LOCK
#define SYS_MTASK_DECLARELOCK(lock)
#define SYS_MTASK_CREATELOCK(lock)      do { } while(0)
#define SYS_MTASK_DESTROYLOCK(lock)     do { } while(0)
#define SYS_MTASK_LOCK(lock)            do { } while(0)
#define SYS_MTASK_UNLOCK(lock)          do { } while(0)
#endif



/*---------------------------------------------------------------------------
 *  TYPEDEFS
 *-------------------------------------------------------------------------*/

typedef struct {
  u32_t             nextBlock;
  u32_t             data[1];
} FSBLOCK_t;

typedef struct {
  u32_t             nextBlock;
  u32_t             prevBlock;
  u32_t             flags;
  u32_t             firstFileBlock; /* or last nextBlock */
  u32_t             filesize;
  struct fsys_time  time;
  char              filename[1]; /* must be the last element */
} FSDIRBLOCK_t;

#define SIZEOF_DIRBLOCK(fnsize)  (sizeof(FSDIRBLOCK_t)-1 + (fnsize))

#define FSDIR_F_DELETED     0x00000001
#define FSDIR_F_IGNORE      0x00000002
#define FSDIR_F_DELONCLOSE  0x00000004
#define FSDIR_F_SUBDIR      0x00000008

typedef struct {
  char              driveId[(FS_DRIVE_IDLEN+3)&~3];
  u32_t             driveSize;
  u32_t             freeBlocksList;
  u32_t             freeDirBlocksList;
  u32_t             firstDirBlock;
  u16_t             bytesPerBlock;
  u16_t             bytesPerDirBlock;
  u16_t             dirBlocksPerBlock;
  u16_t             maxFilenameLength;
} FSROOTBLOCK_t;

typedef struct {
  u32_t             flags;
  FSROOTBLOCK_t     *rootblock;
} FSIMAGE_t;

#define FSIMG_F_EXTERNALIMG 0x00000001
#define FSIMG_F_READONLY    0x00000002

typedef struct {
  sint_t            mode;
  u32_t             flags;
  u32_t             image;
  u32_t             dirblock;
  u32_t             curBlock;
  u32_t             curDataPtr;
  u32_t             curPosition;
  FSDIRBLOCK_t      *dblockptr;
} FSFILE_t;

#define FSFILE_F_USED       0x00000001

typedef struct {
  sint_t            image;
  u32_t             dirblock;
  u32_t             refcount;
} FSFILEREF_t;

typedef struct {
  sint_t            image;
  u32_t             dirblock;
  char              mask[FS_MAXFNAMELEN];
} FSSEARCH_t;



/*---------------------------------------------------------------------------
 *  MACROS
 *-------------------------------------------------------------------------*/

#define FSROOTBLOCK(img)    fsimages_g[img].rootblock
#define ISREADONLY(img)     ((fsimages_g[img].flags & FSIMG_F_READONLY) != 0)
#define FSALIGN32(val)      (((val) + sizeof(u32_t)-1) & ~(sizeof(u32_t)-1))
#define FS_DATABYTESPERBLOCK(rb)    ((rb)->bytesPerBlock - sizeof(u32_t))



/*---------------------------------------------------------------------------
 *  GLOBAL VARIABLES
 *-------------------------------------------------------------------------*/

static sint_t       fsInitialized_g = 0;
char                fnbuffer_g[FS_MAXFNAMELEN];

FSIMAGE_t           fsimages_g[FS_MAXIMAGES];
#define FS_RAMIMAGE  0
#define FS_EXTIMAGE  1


static FSFILE_t     fsFileList_g[FS_MAXFILES];
static FSFILEREF_t  fsRefList_g[FS_MAXFILES];
static FSSEARCH_t   fsSearchList_g[FS_MAXFILES];

#if FS_SUBDIRECTORIES
static struct  fsys_finddata  finfo_g;
static FSSEARCH_t   fsearch_g;
#endif

SYS_MTASK_DECLARELOCK(fsTaskLock_g)



/*---------------------------------------------------------------------------
 *  FUNCTION PROTOTYPES
 *-------------------------------------------------------------------------*/

static void     fs_getCurrentTime(struct fsys_time *time);
static u32_t    fs_allocBlock(FSROOTBLOCK_t *rb);
static void     fs_freeBlock(FSROOTBLOCK_t *rb, u32_t blockNmbr);
static void     fs_freeBlockChain(FSROOTBLOCK_t *rb, u32_t firstBlockNmbr);
static u32_t    fs_findFile(sint_t *img, const char *filename);
static u32_t    fs_newFile(sint_t *img,const char *filename,sint_t overwrite);
static char*    fs_validateFileName(const char* filename);
static sint_t   fs_containWildcard(const char* filename);
static sint_t   fs_isFileOpened(const char* filename, sint_t forWriting);
static void     fs_incRefCount(sint_t img, u32_t dirblock);
static void     fs_decRefCount(sint_t img, u32_t dirblock);
static u32_t    fs_allocDirBlock(FSROOTBLOCK_t *rb);
static void     fs_freeDirBlock(FSROOTBLOCK_t *rb, u32_t blockNmbr);
static u32_t    fs_lastBlock(FSROOTBLOCK_t *rb,u32_t dirblock,u32_t *blocks);
static sint_t   fs_open(const char *filename, const sint_t mode);
static sint_t   fs_seek(const sint_t file, const sint_t position,
                        const sint_t origin);
static void     fs_closeAllFiles(void);
static sint_t   fs_formatImage(sint_t img, u32_t blocksize,
                               u32_t maxFilenameLength);
static void     fs_tempFilename(char *fname);
static void     fs_removeDirEntry(FSROOTBLOCK_t *rb, u32_t dirblock);
static s32_t    fs_findnext(FSSEARCH_t *fs, struct fsys_finddata *fileinfo);
static sint_t   fs_getWriteableImage(void);
static void     fs_blockrestToDirblock(FSROOTBLOCK_t *rb, u32_t block);
static FSBLOCK_t*       fs_getBlock(FSROOTBLOCK_t *rb, u32_t blocknbr);
static FSDIRBLOCK_t*    fs_getDirBlock(FSROOTBLOCK_t *rb, u32_t blocknbr);

#if FS_SUBDIRECTORIES
static sint_t   fs_isDirEmpty(const char *pathname, char **fnout);
#endif



/*---------------------------------------------------------------------------
 *  FUNCTION IMPLEMENTATION
 *-------------------------------------------------------------------------*/


/* Open a file for read or write access.
 */
sint_t  fsys_open(const char *filename, const sint_t mode)
{
  sint_t fh;

  if (fsInitialized_g == 0)
    return -1;

  if (fs_containWildcard(filename))
    return -1;

  SYS_MTASK_LOCK(fsTaskLock_g);
  fh = fs_open(filename, mode);
  SYS_MTASK_UNLOCK(fsTaskLock_g);
  return fh;
}


/* Create and open a temporary file.
 */
sint_t  fsys_opent(char *filename, const sint_t mode)
{
  sint_t fh;

  if ((fsInitialized_g == 0) || (filename == NULL))
    return -1;

  SYS_MTASK_LOCK(fsTaskLock_g);
  fs_tempFilename(filename);
  fh = fs_open(filename, mode | FSO_CREAT | FSO_EXCL);
  SYS_MTASK_UNLOCK(fsTaskLock_g);
  return fh;
}


/* Close a file again.
 */
void fsys_close(const sint_t file)
{
  if ((fsInitialized_g == 0) || ((uint_t)file >= FS_MAXFILES))
    return;

  SYS_MTASK_LOCK(fsTaskLock_g);
  if (fsFileList_g[file].flags & FSFILE_F_USED)
  {
    fsFileList_g[file].flags = 0;
    fs_decRefCount(fsFileList_g[file].image, fsFileList_g[file].dirblock);
  }
  SYS_MTASK_UNLOCK(fsTaskLock_g);
}


/* Write a block of data to a file.
 */
sint_t  fsys_write(const sint_t file, const char *buf, const sint_t count)
{
  FSROOTBLOCK_t *rb;
  FSFILE_t  *f;
  u32_t     c, b, d, s, w;
  
  if ((fsInitialized_g == 0) ||
      ((uint_t)file >= FS_MAXFILES) ||
      (count < 0))
    return -1;

  SYS_MTASK_LOCK(fsTaskLock_g);

  f = &fsFileList_g[file];
  if (!(f->flags & FSFILE_F_USED) ||
      (f->mode & FSO_RDONLY))
  {
    SYS_MTASK_UNLOCK(fsTaskLock_g);
    return -1;
  }

  if ((f->mode & FSO_APPEND) &&
      (f->curPosition < f->dblockptr->filesize))
  {
    if (fs_seek(file, 0, FSSEEK_END) < 0)
    {
      SYS_MTASK_UNLOCK(fsTaskLock_g);
      return -1;
    }
  }

  rb = FSROOTBLOCK(f->image);
  b = f->curBlock;
  d = f->curDataPtr;
  c = (u32_t) count;
  w = 0;

  while (c != 0)
  {
    /* if curDataPtr == 0 we need to go to the next block */
    if (d == 0)
    {
      if (b == 0)
      {
        b = f->dblockptr->firstFileBlock;
      }
      else
      {
        b = fs_getBlock(rb, b)->nextBlock;
      }
      if (b == 0)
      {
        b = fs_allocBlock(rb);
        if (b == 0)
        {
          SYS_MTASK_UNLOCK(fsTaskLock_g);
          return (sint_t) w;  /* error: disk full */
        }
        if (f->curBlock == 0)
        {
          f->dblockptr->firstFileBlock = b;
        }
        else
        {
          fs_getBlock(rb, f->curBlock)->nextBlock = b;
        }
      }
      f->curBlock = b;
    }

    /* copy data */
    s = FS_DATABYTESPERBLOCK(rb) - d;
    if (s > c)
      s = c;
    sysMemCopy(((u8_t*)(fs_getBlock(rb, b)->data)) + d, buf + w, s);

    d += s;
    if (d >= FS_DATABYTESPERBLOCK(rb))
      d = 0;

    f->curDataPtr = d;
    f->curPosition += s;

    if (f->curPosition > f->dblockptr->filesize)
      f->dblockptr->filesize = f->curPosition;

    w += s;
    c -= s;
  }

  SYS_MTASK_UNLOCK(fsTaskLock_g);
  return w;
}


/* Read a block of data from a file.
 */
sint_t  fsys_read(const sint_t file, const char *buf, const sint_t count)
{
  FSROOTBLOCK_t *rb;
  FSFILE_t  *f;
  u32_t     b, c, d, r, s, l;

  if ((fsInitialized_g == 0) || ((uint_t)file >= FS_MAXFILES))
    return -1;

  SYS_MTASK_LOCK(fsTaskLock_g);

  f = &fsFileList_g[file];
  if (!(f->flags & FSFILE_F_USED) ||
      (f->mode & FSO_WRONLY))
  {
    SYS_MTASK_UNLOCK(fsTaskLock_g);
    return -1;
  }

  rb = FSROOTBLOCK(f->image);
  b = f->curBlock;
  d = f->curDataPtr;
  c = (u32_t) count;
  r = 0;

  while ((c != 0) && (f->curPosition < f->dblockptr->filesize))
  {
    /* if curDataPtr == 0 we need to go to the next block */
    if (d == 0)
    {
      if (b == 0)
      {
        b = f->dblockptr->firstFileBlock;
      }
      else
      {
        b = fs_getBlock(rb, b)->nextBlock;
      }
      if (b == 0)
      {
        SYS_MTASK_UNLOCK(fsTaskLock_g);
        return (sint_t) r; /* reached end of file */
      }
      f->curBlock = b;
    }

    /* copy data */
    s = FS_DATABYTESPERBLOCK(rb) - d;
    if (s > c)
      s = c;
    l = f->dblockptr->filesize - f->curPosition;
    if (s > l)
      s = l;

    sysMemCopy((u8_t*)buf + r,
               ((u8_t*)(fs_getBlock(rb, b)->data)) + d, s);

    d += s;
    if (d >= FS_DATABYTESPERBLOCK(rb))
      d = 0;

    f->curDataPtr = d;
    f->curPosition += s;

    r += s;
    c -= s;
  }

  SYS_MTASK_UNLOCK(fsTaskLock_g);
  return (sint_t) r;
}


/* Tests if the file pointer has reached the end of the file.
 */
sint_t  fsys_eof(const sint_t file)
{
  FSFILE_t  *f;
  sint_t    rc;

  if ((fsInitialized_g == 0) ||
      ((uint_t)file >= FS_MAXFILES))
    return -1;

  SYS_MTASK_LOCK(fsTaskLock_g);

  f = &fsFileList_g[file];
  if (!(f->flags & FSFILE_F_USED))
  {
    rc = -1;
  }
  else
  {
    rc = (f->curPosition >= f->dblockptr->filesize) ? 1 : 0;
  }

  SYS_MTASK_UNLOCK(fsTaskLock_g);
  return rc;
}


/* Set the file pointer to a new position.
 */
sint_t  fsys_seek(const sint_t file, const sint_t position, 
                  const sint_t origin)
{
  sint_t rc;

  if ((fsInitialized_g == 0) ||
      ((uint_t)file >= FS_MAXFILES))
    return -1;

  SYS_MTASK_LOCK(fsTaskLock_g);
  rc =  fs_seek(file, position, origin);
  SYS_MTASK_UNLOCK(fsTaskLock_g);
  return rc;
}


/* Get current file pointer position.
 */
sint_t  fsys_tell(const sint_t file)
{
  FSFILE_t  *f;
  sint_t    rc;

  if ((fsInitialized_g == 0) ||
      ((uint_t)file >= FS_MAXFILES))
    return -1;

  SYS_MTASK_LOCK(fsTaskLock_g);
  f = &fsFileList_g[file];
  if (f->flags & FSFILE_F_USED)
  {
    rc = (sint_t) f->curPosition;
  }
  else
  {
    rc = -1;
  }
  SYS_MTASK_UNLOCK(fsTaskLock_g);
  return rc;
}


/* Delete a file from a writeable RAM-Drive.
 */
sint_t  fsys_remove(const char *filename)
{
  FSROOTBLOCK_t *rb;
  FSDIRBLOCK_t  *dbl;
  u32_t         b;
  sint_t        img;
  char          *fn;

  if ((fsInitialized_g == 0) ||
      fs_containWildcard(filename))
    return -1;

  SYS_MTASK_LOCK(fsTaskLock_g);

  fn = fs_validateFileName(filename);
  b = fs_findFile(&img, fn);
  if (b == 0)
  {
    SYS_MTASK_UNLOCK(fsTaskLock_g);
    return -1; /* file not found */
  }

  rb = FSROOTBLOCK(img);
  dbl = fs_getDirBlock(rb, b);

  if (ISREADONLY(img) ||
      fs_isFileOpened(fn, 0) ||

⌨️ 快捷键说明

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