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

📄 filesys.c

📁 picoos源码。The RTOS and the TCP/IP stack will be built automatically.
💻 C
📖 第 1 页 / 共 4 页
字号:
{
  FSROOTBLOCK_t *rb;
  FSDIRBLOCK_t  *dbl;
  FSFILE_t      *f;
  sint_t        file;
  u32_t         d;
  sint_t        img;
  char          *fn;

  fn = fs_validateFileName(filename);
  if (*fn == 0)
    return -1;

  /* allocate a file descriptor */
  for (file = 0; (file < FS_MAXFILES) && 
                 (fsFileList_g[file].flags & FSFILE_F_USED); file++);
  if (file >= FS_MAXFILES)
    return -1;

  f = &fsFileList_g[file];

  if (mode & (FSO_CREAT | FSO_TRUNC))
  {
    /* FSO_CREAT: create a new file, FSO_TRUNC: overwrite existing file */
    d = 0;
    img = 0;
    if (((mode & FSO_TRUNC) && fs_isFileOpened(fn, 0)) ||
        fs_isFileOpened(fn, 1))
      return -1; /* error: can't truncate a yet opened file, and can't
                    write to a file that is just opened for writing */
    if (!(mode & FSO_TRUNC))
    {
      d = fs_findFile(&img, fn);
      if ((mode & FSO_EXCL) && (d != 0))
        return -1;  /* error, file exist */
    }
    if (!(mode & FSO_CREAT))
    {
      if (!(mode & FSO_RDONLY))
        d = fs_findFile(&img, fn);
      if (d == 0)
        return -1; /* error: rdonly is set or file does not exist */
      d = 0;
    }
    if (d == 0)
      d = fs_newFile(&img, fn, (mode & FSO_TRUNC) ? 1 : 0);
    if ((d == 0) || ISREADONLY(img))
      return -1;
    rb = FSROOTBLOCK(img);
  }
  else
  {
    /* open an existing file */
    if (!(mode & FSO_RDONLY))
    {
      /* may do a write access, but
         this is not allowed while someone else
         is writing to the file */
      if (fs_isFileOpened(fn, 1))
        return -1;
    }
    d = fs_findFile(&img, fn);
    if (d == 0)
      return -1;  /* file not found */
    if (!(mode & FSO_RDONLY) && ISREADONLY(img))
      return -1;  /* image not writeable */
    rb = FSROOTBLOCK(img);
  }

  dbl = fs_getDirBlock(rb, d);
  if (dbl->flags & FSDIR_F_SUBDIR)
    return -1;

  f->mode        = mode;
  f->flags       = FSFILE_F_USED;
  f->image       = img;
  f->dirblock    = d;
  f->curBlock    = 0;
  f->curDataPtr  = 0;
  f->curPosition = 0;
  f->dblockptr   = dbl;

  fs_incRefCount(img, d);

  return file;
}


static sint_t fs_getWriteableImage(void)
{
  sint_t i;

  for (i=0; i < FS_MAXIMAGES; i++)
  {
    if ((fsimages_g[i].rootblock != NULL) &&
        ((fsimages_g[i].flags & FSIMG_F_READONLY) == 0))
    {
      return i;
    }
  }
  return -1;
}


static u32_t  fs_newFile(sint_t *img, const char *filename, sint_t overwrite)
{
  FSROOTBLOCK_t *rb;
  FSDIRBLOCK_t  *dbl;
  u32_t n, pb, b;
  sint_t i, i2;

  /* find writeable image */
  i = fs_getWriteableImage();
  if (i < 0)
    return 0;
  rb = FSROOTBLOCK(i);

  if (sysStrlen(filename) >= rb->maxFilenameLength)
    return -1;

  *img = i;
  n = fs_findFile(&i2, filename);
  if (n != 0)
  {
    if ((overwrite == 0) || (i != i2))
      return 0;

    dbl = fs_getDirBlock(rb, n);
    if (dbl->flags & FSDIR_F_SUBDIR)
      return 0;

    /* overwrite an existing file */
    fs_freeBlockChain(rb, dbl->firstFileBlock);
  }
  else
  {
    /* create a new file */
    n = fs_allocDirBlock(rb);
    if (n == 0)
      return 0;

    pb = 0;
    for (b = rb->firstDirBlock; b != 0; b = fs_getDirBlock(rb, b)->nextBlock)
      pb = b;

    if (pb == 0)
    {
      rb->firstDirBlock = n;
    }
    else
    {
      fs_getDirBlock(rb, pb)->nextBlock = n;
    }

    dbl = fs_getDirBlock(rb, n);
    dbl->prevBlock = pb;
    sysStrcpy(dbl->filename, filename);
  }

  /* initialize directory entry */
  dbl->firstFileBlock = 0;
  dbl->filesize       = 0;
  fs_getCurrentTime(&dbl->time);

  return n;
}


/* create a temporary file name */
static void fs_tempFilename(char *fname)
{
  struct fsys_time  fstime;
  u32_t  d, n;

  fs_getCurrentTime(&fstime);
  n = (((u32_t) fstime.min) << 6) | (u32_t) fstime.sec;

  do
  {
    sprintf(fname, "TEMP%04x", n++);
    d = fs_findFile(NULL, fname);
  }
  while (d > 0);
}


/*-------------------------------------------------------------------------*/


static u32_t fs_allocBlock(FSROOTBLOCK_t *rb)
{
  FSBLOCK_t *bl;
  u32_t n;

  if (rb->freeBlocksList == 0)
    return 0;

  n  = rb->freeBlocksList;
  bl = fs_getBlock(rb, n);
  rb->freeBlocksList = bl->nextBlock;
  bl->nextBlock = 0;
  return n;
}


static void fs_freeBlock(FSROOTBLOCK_t *rb, u32_t blockNmbr)
{
  fs_getBlock(rb, blockNmbr)->nextBlock = rb->freeBlocksList;
  rb->freeBlocksList = blockNmbr;
}


static void fs_freeBlockChain(FSROOTBLOCK_t *rb, u32_t firstBlockNmbr)
{
  FSBLOCK_t *bl;
  u32_t n, b;

  b = firstBlockNmbr;
  while (b != 0)
  {
    bl = fs_getBlock(rb, b);
    n  = bl->nextBlock;
    fs_freeBlock(rb, b);
    b  = n;
  }
}


static void fs_blockrestToDirblock(FSROOTBLOCK_t *rb, u32_t block)
{
  FSDIRBLOCK_t *dbl;
  u32_t db;
  u16_t i;

  db = block * rb->dirBlocksPerBlock + 1;
  for (i = rb->dirBlocksPerBlock; i > 1; i--)
  {
    dbl = fs_getDirBlock(rb, db);
    dbl->nextBlock = rb->freeDirBlocksList;
    rb->freeDirBlocksList = db;
    ++db;
  }
}


static u32_t fs_allocDirBlock(FSROOTBLOCK_t *rb)
{
  FSDIRBLOCK_t *dbl;
  u32_t n;

  n = rb->freeDirBlocksList;
  if (n == 0)
  {
    n = fs_allocBlock(rb);
    if (n == 0)
      return 0;

    fs_blockrestToDirblock(rb, n);
    n *= rb->dirBlocksPerBlock;
    dbl = fs_getDirBlock(rb, n);
  }
  else
  {
    dbl = fs_getDirBlock(rb, n);
    rb->freeDirBlocksList = dbl->nextBlock;
  }

  dbl->nextBlock = 0;
  dbl->flags = 0;
  return n;
}


static void fs_freeDirBlock(FSROOTBLOCK_t *rb, u32_t blockNmbr)
{
  FSDIRBLOCK_t  *dbl;

  dbl = fs_getDirBlock(rb, blockNmbr);
  dbl->flags = FSDIR_F_DELETED;
  dbl->firstFileBlock = dbl->nextBlock;
  dbl->nextBlock = rb->freeDirBlocksList;
  rb->freeDirBlocksList = blockNmbr;
}


static void fs_removeDirEntry(FSROOTBLOCK_t *rb, u32_t dirblock)
{
  FSDIRBLOCK_t  *dbl;

  dbl = fs_getDirBlock(rb, dirblock);

  /* free data area of the file */
  fs_freeBlockChain(rb, dbl->firstFileBlock);

  /* remove the directory entry */
  if (dbl->nextBlock != 0)
    fs_getDirBlock(rb, dbl->nextBlock)->prevBlock = dbl->prevBlock;

  if (dbl->prevBlock == 0)
  {
    rb->firstDirBlock = dbl->nextBlock;
  }
  else
  {
    fs_getDirBlock(rb, dbl->prevBlock)->nextBlock = dbl->nextBlock;
  }

  fs_freeDirBlock(rb, dirblock);
}


static void fs_closeAllFiles(void)
{
  sint_t i;
  for (i = 0; i < FS_MAXFILES; i++)
  {
    fsFileList_g[i].flags   = 0;
    fsRefList_g[i].refcount = 0;
    fsSearchList_g[i].image = -1;
  }
}


static sint_t fs_formatImage(sint_t img, u32_t blocksize,
                             u32_t maxFilenameLength)
{
  FSROOTBLOCK_t  *rb;
  u32_t          bpb, bpd, blocks, b;

  if (fsimages_g[img].flags & FSIMG_F_READONLY)
    return -1;

  if (blocksize == 0)
    blocksize = 512;
  if (maxFilenameLength == 0)
    maxFilenameLength = (blocksize/2) - SIZEOF_DIRBLOCK(0);
  maxFilenameLength = maxFilenameLength & ~(sizeof(u32_t)-1);
  if (maxFilenameLength > FS_MAXFNAMELEN)
    maxFilenameLength = FS_MAXFNAMELEN;

  bpb = FSALIGN32(blocksize);
  bpd = FSALIGN32(SIZEOF_DIRBLOCK(maxFilenameLength));

  if ((maxFilenameLength < 2) || (bpd > bpb))
    return -1;

  rb = fsimages_g[img].rootblock;
  blocks = rb->driveSize / bpb;
  if (blocks < 3)
    return -1;

  sysMemCopy(rb->driveId, FS_DRIVE_ID, FS_DRIVE_IDLEN);

  rb->bytesPerBlock = (u16_t) bpb;
  rb->dirBlocksPerBlock = (u16_t) (bpb / bpd);

  rb->maxFilenameLength = (u16_t) ((maxFilenameLength +
    ((bpb/rb->dirBlocksPerBlock) - SIZEOF_DIRBLOCK(maxFilenameLength))) &
      ~(sizeof(u32_t)-1));
  if (rb->maxFilenameLength > FS_MAXFNAMELEN)
    rb->maxFilenameLength = FS_MAXFNAMELEN;

  rb->bytesPerDirBlock =
    FSALIGN32(SIZEOF_DIRBLOCK(rb->maxFilenameLength));

  rb->firstDirBlock     = 0;
  rb->freeBlocksList    = 1;
  rb->freeDirBlocksList = 0;

  for (b = 1; b < (blocks - 1); b++)
  {
    fs_getBlock(rb, b)->nextBlock = b + 1;
  }
  fs_getBlock(rb, b)->nextBlock = 0;

  if (sizeof(FSROOTBLOCK_t) <= rb->bytesPerDirBlock)
  {
    fs_blockrestToDirblock(rb, 0);
  }

  return 0;
}


/*-------------------------------------------------------------------------*/


/* This function returns a pointer to the RAM based image in memory.
 * The image is locked after this operation, so no file operation will
 * change the image. After processing the image, the function
 * fsys_unlockImage must be called.
 */
void*  fsys_lockAndGetImage(u32_t *size)
{
  FSROOTBLOCK_t *rb;
  FSBLOCK_t *bl;
  u32_t  b;
  sint_t i;

  SYS_MTASK_LOCK(fsTaskLock_g);

  /* find writeable image in RAM */
  i = fs_getWriteableImage();
  if (i < 0)
  {
    SYS_MTASK_LOCK(fsTaskLock_g);
    return NULL;
  }

  /* clear all unused blocks */
  rb = FSROOTBLOCK(i);
  b = rb->freeBlocksList;
  while (b != 0)
  {
    bl = fs_getBlock(rb, b);
    sysMemSet(bl->data, 0, FS_DATABYTESPERBLOCK(rb));
    b = bl->nextBlock;
  }

  if (size != NULL)
    *size = rb->driveSize;

  return (void*)rb;
}


/* Unlock an image that was previously locked
 * by a call to the function fsys_lockAndGetImage().
 */
void  fsys_unlockImage(void)
{
  SYS_MTASK_UNLOCK(fsTaskLock_g);
}


/*-------------------------------------------------------------------------*/


/* Add an filesystem image to the filesystem.
 * The image can be marked as readonly when the image resides in
 * a non writable (Flash-) ROM.
 */
sint_t  fsys_addDriveImage(void *img, sint_t readonly)
{
  FSROOTBLOCK_t  *rb = (FSROOTBLOCK_t*) img;
  sint_t i;

  if (img == NULL)
    return -1;

  if (sysStrncmp(rb->driveId, FS_DRIVE_ID, FS_DRIVE_IDLEN) != 0)
    return -1;

  if (rb->maxFilenameLength > FS_MAXFNAMELEN)
    return -1;

  SYS_MTASK_LOCK(fsTaskLock_g);

  for (i=0; (i<FS_MAXIMAGES) && (fsimages_g[i].rootblock != NULL); i++);
  if (i >= FS_MAXIMAGES)
  {
    SYS_MTASK_UNLOCK(fsTaskLock_g);
    return -1;
  }

  fsimages_g[i].rootblock = rb;
  fsimages_g[i].flags = FSIMG_F_EXTERNALIMG |
                        ((readonly != 0) ? FSIMG_F_READONLY : 0);

  SYS_MTASK_UNLOCK(fsTaskLock_g);
  return 0;
}


/* Initialize the file system.
 * This function must be called before all others.
 */
sint_t  fsys_init(u32_t size, u32_t blocksize, u32_t maxFilenameLength)
{
  FSROOTBLOCK_t  *rb;
  sint_t         i;

  SYS_MTASK_CREATELOCK(fsTaskLock_g);

  for (i = 0; i < FS_MAXIMAGES; i++)
  {
    fsimages_g[i].rootblock = NULL;
  }

  fs_closeAllFiles();

  if (size != 0)
  {
    rb = NULL;
    if (size > sizeof(FSROOTBLOCK_t))
      rb = (FSROOTBLOCK_t*) sysMemAlloc(size);
    if (rb == NULL)
    {
      SYS_MTASK_DESTROYLOCK(fsTaskLock_g);
      return -1;
    }
    sysMemSet(rb, 0, size);

    fsimages_g[0].rootblock = rb;
    fsimages_g[0].flags = 0;
    rb->driveSize = size;

    if (fs_formatImage(0, blocksize, maxFilenameLength) != 0)
    {
      sysMemFree(rb);
      SYS_MTASK_DESTROYLOCK(fsTaskLock_g);
      return -1;
    }
  }

  fsInitialized_g = 1;
  return 0;
}


/* Terminate the filesystem.
 */
sint_t  fsys_term(void)
{
  sint_t  i;

  fsInitialized_g = 0;

  for (i=0; i<FS_MAXIMAGES; i++)
  {
    if ((fsimages_g[i].rootblock != NULL) &&
        ((fsimages_g[i].flags & FSIMG_F_EXTERNALIMG) == 0))
    {
      sysMemFree(fsimages_g[i].rootblock);
    }
    fsimages_g[i].rootblock = NULL;
  }

  SYS_MTASK_DESTROYLOCK(fsTaskLock_g);
  return 0;
}

⌨️ 快捷键说明

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