📄 fs_fat32.c
字号:
/* 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 + -