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

📄 fs_fat32.c

📁 這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU
💻 C
📖 第 1 页 / 共 4 页
字号:
          /* We are not sure of the state of the file buffer so           * the safest thing to do is just invalidate it           */          (void)fat_ffcacheinvalidate(fs, ff);          /* Read all of the sectors directory into user memory */          ret = fat_hwread(fs, userbuffer, readsector, nsectors);          if (ret < 0)            {              goto errout_with_semaphore;            }          ff->ff_sectorsincluster -= nsectors - 1;          ff->ff_currentsector     = readsector + nsectors - 1;          bytesread                = nsectors * fs->fs_hwsectorsize;        }      else        {          /* We are reading a partial sector.  First, read the whole sector           * into the file data buffer.  This is a caching buffer so if           * it is already there then all is well.           */          ret = fat_ffcacheread(fs, ff, readsector);          if (ret < 0)            {              goto errout_with_semaphore;            }          /* Copy the partial sector into the user buffer */          bytesread = fs->fs_hwsectorsize - sectorindex;          if (bytesread > buflen)            {              bytesread = buflen;            }          memcpy(userbuffer, &ff->ff_buffer[sectorindex], bytesread);          ff->ff_currentsector = readsector;        }      /* Set up for the next sector read */      userbuffer      += bytesread;      ff->ff_position += bytesread;      readsize        += bytesread;      buflen          -= bytesread;    }  fat_semgive(fs);  return readsize;errout_with_semaphore:  fat_semgive(fs);  return ret;}/**************************************************************************** * Name: fat_write ****************************************************************************/static ssize_t fat_write(FAR struct file *filp, const char *buffer,                         size_t buflen){  struct inode         *inode;  struct fat_mountpt_s *fs;  struct fat_file_s    *ff;  sint32                cluster;  size_t                writesector;  unsigned int          byteswritten;  unsigned int          writesize;  unsigned int          nsectors;  ubyte                *userbuffer = (ubyte*)buffer;  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 file was opened for write access */  if ((ff->ff_oflags & O_WROK) == 0)    {      ret = -EACCES;      goto errout_with_semaphore;    }  /* Check if the file size would exceed the range of size_t */  if (ff->ff_size + buflen < ff->ff_size)    {      ret = -EFBIG;      goto errout_with_semaphore;    }  /* Loop until either (1) all data has been transferred, or (2) an   * error occurs.   */  byteswritten = 0;  writesector = ff->ff_currentsector;  while (buflen > 0)    {      /* Get offset into the sector where we begin the read */      int sectorindex = ff->ff_position & SEC_NDXMASK(fs);      /* Check if the current read stream happens to lie on a       * sector boundary.       */      if (sectorindex == 0)        {          /* Decrement the number of sectors left in this cluster */          ff->ff_sectorsincluster--;          /* Are there unwritten sectors remaining in this cluster */          if (ff->ff_sectorsincluster > 0)            {              /* Yes.. There are more sectors in this cluster to be written.               * just increment the current sector number and write.               */              writesector = ff->ff_currentsector + 1;            }          else            {              /* No.. Handle the case of the first sector of the file */              if (ff->ff_position == 0)                {                  /* Check the first cluster of the file.  Zero means that                   * the file is empty -- perhaps the file was truncated or                   * created when it was opened                   */                  if (ff->ff_startcluster == 0)                    {                      /* In this case, we have to create a new cluster chain */                      ff->ff_startcluster = fat_createchain(fs);                    }                  /* Start writing at the first cluster of the file */                  cluster = ff->ff_startcluster;                }              /* But in the general case, we have to extend the current               * cluster by one (unless lseek was used to move the file               * position back from the end of the file)               */              else                {                    /* Extend the chain by adding a new cluster after                     * the last one                     */                    cluster = fat_extendchain(fs, ff->ff_currentcluster);                }              /* Verify the cluster number */              if (cluster < 0)                {                  ret = cluster;                  goto errout_with_semaphore;                }              else if (cluster < 2 || cluster >= fs->fs_nclusters)                {                  ret = -ENOSPC;                  goto errout_with_semaphore;                }              /* Setup to write the first sector from the new cluster */              ff->ff_currentcluster   = cluster;              ff->ff_sectorsincluster = fs->fs_fatsecperclus;              writesector             = fat_cluster2sector(fs, cluster);            }        }      /* Check if there is unwritten data in the file buffer */      ret = fat_ffcacheflush(fs, ff);      if (ret < 0)        {          goto errout_with_semaphore;        }      /* Check if the user has provided a buffer large enough to       * hold one or more complete sectors.       */      nsectors = buflen / fs->fs_hwsectorsize;      if (nsectors > 0)        {          /* Write maximum contiguous sectors directly from the user's           * buffer without using our tiny read buffer.           *           * Limit the number of sectors that we write on this time           * through the loop to the remaining contiguous sectors           * in this cluster           */          if (nsectors > ff->ff_sectorsincluster)            {              nsectors = ff->ff_sectorsincluster;            }          /* We are not sure of the state of the file buffer so           * the safest thing to do is just invalidate it           */          (void)fat_ffcacheinvalidate(fs, ff);          /* Write all of the sectors directory from user memory */          ret = fat_hwwrite(fs, userbuffer, writesector, nsectors);          if (ret < 0)            {              goto errout_with_semaphore;            }          ff->ff_sectorsincluster -= nsectors - 1;          ff->ff_currentsector     = writesector + nsectors - 1;          writesize                = nsectors * fs->fs_hwsectorsize;          ff->ff_bflags           |= FFBUFF_MODIFIED;        }      else        {          /* We are write a partial sector.  We will first have to           * read the full sector in memory as part of a read-modify-write           * operation.           */          if (ff->ff_position < ff->ff_size)            {              ff->ff_currentsector = writesector;              ret = fat_ffcacheread(fs, ff, writesector);              if (ret < 0)                {                  goto errout_with_semaphore;                }            }          /* Copy the partial sector from the user buffer */          writesize = fs->fs_hwsectorsize - sectorindex;          if (writesize > buflen)            {              writesize = buflen;            }          memcpy(&ff->ff_buffer[sectorindex], userbuffer, writesize);          ff->ff_currentsector = writesector;          ff->ff_bflags |= (FFBUFF_DIRTY|FFBUFF_VALID|FFBUFF_MODIFIED);        }      /* Set up for the next write */      userbuffer += writesize;      ff->ff_position += writesize;      byteswritten += writesize;      buflen -= writesize;    }  /* The transfer has completed without error.  Update the file size */  if (ff->ff_position > ff->ff_size)    {      ff->ff_size = ff->ff_position;    }  fat_semgive(fs);  return byteswritten;errout_with_semaphore:  fat_semgive(fs);  return ret;}/**************************************************************************** * Name: fat_seek ****************************************************************************/static off_t fat_seek(FAR struct file *filp, off_t offset, int whence){  struct inode         *inode;  struct fat_mountpt_s *fs;  struct fat_file_s    *ff;  sint32                cluster;  ssize_t               position;  unsigned int          clustersize;  unsigned int          sectoroffset;  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);  /* Map the offset according to the whence option */  switch (whence)  {      case SEEK_SET: /* The offset is set to offset bytes. */          position = offset;          break;      case SEEK_CUR: /* The offset is set to its current location plus                      * offset bytes. */          position = offset + ff->ff_position;          break;      case SEEK_END: /* The offset is set to the size of the file plus                      * offset bytes. */          position = offset + ff->ff_size;          break;      default:          return -EINVAL;  }  /* Make sure that the mount is still healthy */  fat_semtake(fs);  ret = fat_checkmount(fs);  if (ret != OK)    {        goto errout_with_semaphore;    }  /* Check if there is unwritten data in the file buffer */  ret = fat_ffcacheflush(fs, ff);  if (ret < 0)  {      goto errout_with_semaphore;  }  /* Attempts to set the position beyound the end of file will   * work if the file is open for write access.   */  if (position > ff->ff_size && (ff->ff_oflags & O_WROK) == 0)    {        /* Otherwise, the position is limited to the file size */        position = ff->ff_size;    }  /* Set file position to the beginning of the file */  ff->ff_position         = 0;  ff->ff_sectorsincluster = 1;  /* Move file position if necessary */  if (position)    {        /* Get the start cluster of the file */        cluster = ff->ff_startcluster;        if (!cluster)        {            /* Create a new cluster chain if the file does not have one */            cluster = fat_createchain(fs);            if (cluster < 0)            {                ret = cluster;                goto errout_with_semaphore;            }            ff->ff_startcluster = cluster;        }        if (cluster)        {            /* If the file has a cluster chain, follow it to the             * requested position.             */            clustersize = fs->fs_fatsecperclus * fs->fs_hwsectorsize;            for (;;)            {                /* Skip over clusters prior to the one containing                 * the requested position.                 */                ff->ff_currentcluster = cluster;                if (position <= clustersize)                {                    break;                }                /* Extend the cluster chain if write in enabled.  NOTE:                 * this is not consistent with the lseek description:                 * "The  lseek() function allows the file offset to be                 * set beyond the end of the file (but this does not                 * change the size of the file).  If data is later written                 * at  this  point, subsequent reads of the data in the                 * gap (a "hole") return null bytes ('\0') until data                 * is actually written into the gap."                 */                if ((ff->ff_oflags & O_WROK) != 0)                {                    /* Extend the cluster chain (fat_extendchain                     * will follow the existing chain or add new                     * clusters as needed.                     */                    cluster = fat_extendchain(fs, cluster);                }                else                {                    /* Other we can only follong the existing chain */                    cluster = fat_getcluster(fs, cluster);                }                if (cluster < 0)                {                    /* An error occurred getting the cluster */                    ret = cluster;                    goto errout_with_semaphore;                }                /* Zero means that there is no further clusters available                 * in the chain.                 */                if (cluster == 0)                {                    /* At the position to the current locaiton and                     * break out.                     */                    position = clustersize;                    break;                }                if (cluster >= fs->fs_nclusters)                {                    ret = -ENOSPC;                    goto errout_with_semaphore;                }                /* Otherwise, update the position and continue looking */                ff->ff_position += clustersize;                position        -= clustersize;            }            /* We get here after we have found the sector containing             * the requested position.             */            sectoroffset = (position - 1) / fs->fs_hwsectorsize;            /* And get the current sector from the cluster and             * the sectoroffset into the cluster.             */            ff->ff_currentsector =                fat_cluster2sector(fs, cluster) + sectoroffset;            /* Load the sector corresponding to the position */            if ((position & SEC_NDXMASK(fs)) != 0)            {                ret = fat_ffcacheread(fs, ff, ff->ff_currentsector);                if (ret < 0)                {                    goto errout_with_semaphore;                }            }            /* Save the number of sectors left in the cluster */            ff->ff_sectorsincluster = fs->fs_fatsecperclus - sectoroffset;            /* And save the new file position */            ff->ff_position += position;        }    }  /* If we extended the size of the file, then mark the file as modified. */  if ((ff->ff_oflags & O_WROK) != 0 &&  ff->ff_position > ff->ff_size)    {        ff->ff_size    = ff->ff_position;        ff->ff_bflags |= FFBUFF_MODIFIED;    }  fat_semgive(fs);  return OK;errout_with_semaphore:  fat_semgive(fs);  return ret;}/**************************************************************************** * Name: fat_ioctl ****************************************************************************/static int fat_ioctl(FAR struct file *filp, int cmd, unsigned long arg){  struct inode         *inode;  struct fat_mountpt_s *fs;  struct fat_file_s    *ff;  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;

⌨️ 快捷键说明

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