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

📄 fs_fat32.c

📁 這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU
💻 C
📖 第 1 页 / 共 4 页
字号:
  inode = filp->f_inode;  fs    = inode->i_private;  DEBUGASSERT(fs != NULL);  /* Make sure that the mount is still healthy */  fat_semtake(fs);  ret = fat_checkmount(fs);  if (ret != OK)    {      fat_semgive(fs);      return ret;    }  /* ioctl calls are just passed through to the contained block driver */  fat_semgive(fs);  return -ENOSYS;}/**************************************************************************** * Name: fat_sync * * Description: Synchronize the file state on disk to match internal, in- *   memory state. * ****************************************************************************/static int fat_sync(FAR struct file *filp){  struct inode         *inode;  struct fat_mountpt_s *fs;  struct fat_file_s    *ff;  uint32                wrttime;  ubyte                *direntry;  int                   ret;  /* Sanity checks */  DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL);  /* Recover our private data from the struct file instance */  ff    = filp->f_priv;  inode = filp->f_inode;  fs    = inode->i_private;  DEBUGASSERT(fs != NULL);  /* Make sure that the mount is still healthy */  fat_semtake(fs);  ret = fat_checkmount(fs);  if (ret != OK)    {      goto errout_with_semaphore;    }  /* Check if the has been modified in any way */  if ((ff->ff_bflags & FFBUFF_MODIFIED) != 0)    {      /* Flush any unwritten data in the file buffer */      ret = fat_ffcacheflush(fs, ff);      if (ret < 0)        {          goto errout_with_semaphore;        }      /* Update the directory entry.  First read the directory       * entry into the fs_buffer (preserving the ff_buffer)       */      ret = fat_fscacheread(fs, ff->ff_dirsector);      if (ret < 0)        {          goto errout_with_semaphore;        }      /* Recover a pointer to the specific directory entry       * in the sector using the saved directory index.       */      direntry = &fs->fs_buffer[ff->ff_dirindex * 32];      /* Set the archive bit, set the write time, and update       * anything that may have* changed in the directory       * entry: the file size, and the start cluster       */      direntry[DIR_ATTRIBUTES] |= FATATTR_ARCHIVE;      DIR_PUTFILESIZE(direntry, ff->ff_size);      DIR_PUTFSTCLUSTLO(direntry, ff->ff_startcluster);      DIR_PUTFSTCLUSTHI(direntry, ff->ff_startcluster >> 16);      wrttime = fat_systime2fattime();      DIR_PUTWRTTIME(direntry, wrttime & 0xffff);      DIR_PUTWRTDATE(direntry, wrttime >> 16);      /* Clear the modified bit in the flags */      ff->ff_bflags &= ~FFBUFF_MODIFIED;      /* Flush these change to disk and update FSINFO (if       * appropriate.       */      fs->fs_dirty = TRUE;      ret          = fat_updatefsinfo(fs);    }errout_with_semaphore:  fat_semgive(fs);  return ret;}/**************************************************************************** * Name: fat_opendir * * Description: Open a directory for read access * ****************************************************************************/static int fat_opendir(struct inode *mountpt, const char *relpath, struct internal_dir_s *dir){  struct fat_mountpt_s *fs;  struct fat_dirinfo_s  dirinfo;  int                     ret;  /* Sanity checks */  DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);  /* Recover our private data from the inode instance */  fs = mountpt->i_private;  /* Make sure that the mount is still healthy */  fat_semtake(fs);  ret = fat_checkmount(fs);  if (ret != OK)    {      goto errout_with_semaphore;    }  /* Find the requested directory */  ret = fat_finddirentry(fs, &dirinfo, relpath);  if (ret < 0)    {      goto errout_with_semaphore;    }  /* Check if this is the root directory */  if (dirinfo.fd_entry == NULL)    {      /* Handle the FAT12/16/32 root directory using the values setup by       * fat_finddirentry() above.       */      dir->u.fat.fd_startcluster = dirinfo.dir.fd_startcluster;      dir->u.fat.fd_currcluster  = dirinfo.dir.fd_currcluster;      dir->u.fat.fd_currsector   = dirinfo.dir.fd_currsector;      dir->u.fat.fd_index        = dirinfo.dir.fd_index;    }  /* This is not the root directory.  Verify that it is some kind of directory */  else if ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY) == 0)    {       /* The entry is not a directory */       ret = -ENOTDIR;       goto errout_with_semaphore;    }  else    {       /* The entry is a directory */      dir->u.fat.fd_startcluster =           ((uint32)DIR_GETFSTCLUSTHI(dirinfo.fd_entry) << 16) |                   DIR_GETFSTCLUSTLO(dirinfo.fd_entry);      dir->u.fat.fd_currcluster  = dir->u.fat.fd_startcluster;      dir->u.fat.fd_currsector   = fat_cluster2sector(fs, dir->u.fat.fd_currcluster);      dir->u.fat.fd_index        = 2;    }  fat_semgive(fs);  return OK;errout_with_semaphore:  fat_semgive(fs);  return ERROR;}/**************************************************************************** * Name: fat_readdir * * Description: Read the next directory entry * ****************************************************************************/static int fat_readdir(struct inode *mountpt, struct internal_dir_s *dir){  struct fat_mountpt_s *fs;  unsigned int            dirindex;  ubyte                  *direntry;  ubyte                   ch;  ubyte                   attribute;  int                     ret = OK;  /* Sanity checks */  DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);  /* Recover our private data from the inode instance */  fs = mountpt->i_private;  /* Make sure that the mount is still healthy */  fat_semtake(fs);  ret = fat_checkmount(fs);  if (ret != OK)    {      goto errout_with_semaphore;    }  /* Read the next directory entry */  dir->fd_dir.d_name[0] = '\0';  while (dir->u.fat.fd_currsector && dir->fd_dir.d_name[0] == '\0')    {      ret = fat_fscacheread(fs, dir->u.fat.fd_currsector);      if (ret < 0)        {          goto errout_with_semaphore;        }      /* Get a reference to the current directory entry */      dirindex = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * 32;      direntry = &fs->fs_buffer[dirindex];      /* Has it reached to end of the directory */      ch = *direntry;      if (ch == DIR0_ALLEMPTY)        {          /* We signal the end of the directory by returning the           * special error -ENOENT           */          ret = -ENOENT;          goto errout_with_semaphore;        }      /* No, is the current entry a valid entry? */      attribute = DIR_GETATTRIBUTES(direntry);      if (ch != DIR0_EMPTY && (attribute & FATATTR_VOLUMEID) == 0)        {          /* Yes.. get the name from the directory info */          (void)fat_dirname2path(dir->fd_dir.d_name, direntry);          /* And the file type */          if ((attribute & FATATTR_DIRECTORY) == 0)            {              dir->fd_dir.d_type = DTYPE_FILE;            }          else            {              dir->fd_dir.d_type = DTYPE_DIRECTORY;            }        }      /* Set up the next directory index */      if (fat_nextdirentry(fs, &dir->u.fat) != OK)        {          ret = -ENOENT;          goto errout_with_semaphore;        }    }  fat_semgive(fs);  return OK;errout_with_semaphore:  fat_semgive(fs);  return ret;}/**************************************************************************** * Name: fat_rewindir * * Description: Reset directory read to the first entry * ****************************************************************************/static int fat_rewinddir(struct inode *mountpt, struct internal_dir_s *dir){  struct fat_mountpt_s *fs;  int ret;  /* Sanity checks */  DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);  /* Recover our private data from the inode instance */  fs = mountpt->i_private;  /* Make sure that the mount is still healthy */  fat_semtake(fs);  ret = fat_checkmount(fs);  if (ret != OK)    {      goto errout_with_semaphore;    }  /* Check if this is the root directory */  if (fs->fs_type != FSTYPE_FAT32 &&      dir->u.fat.fd_startcluster == 0)    {      /* Handle the FAT12/16 root directory */      dir->u.fat.fd_currcluster  = 0;      dir->u.fat.fd_currsector   = fs->fs_rootbase;      dir->u.fat.fd_index        = 0;    }  else if (fs->fs_type == FSTYPE_FAT32 &&           dir->u.fat.fd_startcluster == fs->fs_rootbase)    {      /* Handle the FAT32 root directory */      dir->u.fat.fd_currcluster = dir->u.fat.fd_startcluster;      dir->u.fat.fd_currsector  = fat_cluster2sector(fs, fs->fs_rootbase);      dir->u.fat.fd_index       = 0;    }  /* This is not the root directory */  else    {      dir->u.fat.fd_currcluster  = dir->u.fat.fd_startcluster;      dir->u.fat.fd_currsector   = fat_cluster2sector(fs, dir->u.fat.fd_currcluster);      dir->u.fat.fd_index        = 2;    }  fat_semgive(fs);  return OK;errout_with_semaphore:  fat_semgive(fs);  return ERROR;}/**************************************************************************** * Name: fat_bind * * Description: This implements a portion of the mount operation. This *  function allocates and initializes the mountpoint private data and *  binds the blockdriver inode to the filesystem private data.  The final *  binding of the private data (containing the blockdriver) to the *  mountpoint is performed by mount(). * ****************************************************************************/static int fat_bind(FAR struct inode *blkdriver, const void *data,                    void **handle){  struct fat_mountpt_s *fs;  int ret;  /* Open the block driver */  if (!blkdriver || !blkdriver->u.i_bops)    {      return -ENODEV;    }  if (blkdriver->u.i_bops->open &&       blkdriver->u.i_bops->open(blkdriver) != OK)    {      return -ENODEV;    }  /* Create an instance of the mountpt state structure */  fs = (struct fat_mountpt_s *)zalloc(sizeof(struct fat_mountpt_s));  if (!fs)    {      return -ENOMEM;    }  /* Initialize the allocated mountpt state structure.  The filesystem is   * responsible for one reference ont the blkdriver inode and does not   * have to addref() here (but does have to release in ubind().   */  fs->fs_blkdriver = blkdriver;  /* Save the block driver reference */  sem_init(&fs->fs_sem, 0, 0);   /* Initialize the semaphore that controls access */  /* Then get information about the FAT32 filesystem on the devices managed   * by this block driver.   */  ret = fat_mount(fs, TRUE);  if (ret != 0)    {      sem_destroy(&fs->fs_sem);      free(fs);      return ret;    }  *handle = (void*)fs;  fat_semgive(fs);  return OK;}/**************************************************************************** * Name: fat_unbind * * Description: This implements the filesystem portion of the umount *   operation. * ****************************************************************************/static int fat_unbind(void *handle, FAR struct inode **blkdriver){  struct fat_mountpt_s *fs = (struct fat_mountpt_s*)handle;  int ret;  if (!fs)    {      return -EINVAL;    }  /* Check if there are sill any files opened on the filesystem. */  ret = OK; /* Assume success */  fat_semtake(fs);  if (fs->fs_head)    {      /* We cannot unmount now.. there are open files */      ret = -EBUSY;    }  else    {       /* Unmount ... close the block driver */      if (fs->fs_blkdriver)        {          struct inode *inode = fs->fs_blkdriver;          if (inode)            {              if (inode->u.i_bops && inode->u.i_bops->close)                {                  (void)inode->u.i_bops->close(inode);                }              /* We hold a reference to the block driver but should               * not but mucking with inodes in this context.  So, we will just return               * our contained reference to the block driver inode and let the umount               * logic dispose of it.               */              if (blkdriver)                {                  *blkdriver = inode;                }            }        }      /* Release the mountpoint private data */      if (fs->fs_buffer)        {          free(fs->fs_buffer);        }      free(fs);    }  fat_semgive(fs);  return ret;}/**************************************************************************** * Name: fat_statfs * * Description: Return filesystem statistics * ****************************************************************************/static int fat_statfs(struct inode *mountpt, struct statfs *buf){  struct fat_mountpt_s *fs;  int                   ret;  /* Sanity checks */  DEBUGASSERT(mountpt && mountpt->i_private);  /* Get the mountpoint private data from the inode structure */  fs = mountpt->i_private;  /* Check if the mount is still healthy */  fat_semtake(fs);  ret = fat_checkmount(fs);  if (ret < 0)    {       goto errout_with_semaphore;    }  /* Fill in the statfs info */  memset(buf, 0, sizeof(struct statfs));  buf->f_type    = MSDOS_SUPER_MAGIC;  /* We will claim that the optimal transfer size is the size of a cluster in bytes */  buf->f_bsize   = fs->fs_fatsecperclus * fs->fs_hwsectorsize;  /* Everything else follows in units of clusters */  buf->f_blocks  = fs->fs_nclusters;                        /* Total data blocks in the file system */  ret = fat_nfreeclusters(fs, &buf->f_bfree);               /* Free blocks in the file system */  buf->f_bavail  = buf->f_bfree;                            /* Free blocks avail to non-superuser */  buf->f_namelen = (8+1+3);                                 /* Maximum length of filenames */  fat_semgive(fs);  return OK;errout_with_semaphore:  fat_semgive(fs);  return ret;}/**************************************************************************** * Name: fat_unlink * * Description: Remove a file

⌨️ 快捷键说明

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