📄 fatfs.c
字号:
// Check it is a directory
if (!S_ISDIR(ds.node->mode))
return ENOTDIR;
if (ds.node != disk->root)
fatfs_node_ref(disk, ds.node);
*dir_out = (cyg_dir)ds.node;
}
else
{
// If no output dir is required, this means that the mte and
// dir arguments are the current cdir setting and we should
// forget this fact.
fatfs_node_t *node = (fatfs_node_t *)dir;
if (node != disk->root)
fatfs_node_unref(disk, node);
}
return ENOERR;
}
// -------------------------------------------------------------------------
// fatfs_stat()
// Get struct stat info for named object.
static int
fatfs_stat(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name,
struct stat *buf)
{
fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
fatfs_dirsearch_t ds;
int err;
CYG_TRACE4(TFS, "Stat mte=%p dir=%p name='%s' buf=%p",
mte, dir, name, buf);
init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);
err = fatfs_find(&ds);
if (err != ENOERR)
return err;
// Fill in the status
buf->st_mode = ds.node->mode;
buf->st_ino = (ino_t)ds.node->cluster;
buf->st_dev = 0;
buf->st_nlink = 1;
buf->st_uid = 0;
buf->st_gid = 0;
buf->st_size = ds.node->size;
buf->st_atime = ds.node->atime;
buf->st_mtime = ds.node->mtime;
buf->st_ctime = ds.node->ctime;
return ENOERR;
}
// -------------------------------------------------------------------------
// fatfs_getinfo()
// Getinfo. Nothing to support here at present.
static int
fatfs_getinfo(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name,
int key,
void *buf,
int len)
{
CYG_TRACE6(TFS, "Getinfo mte=%p dir=%p name='%s' key=%d buf=%p len=%d",
mte, dir, name, key, buf, len);
return EINVAL;
}
// -------------------------------------------------------------------------
// fatfs_setinfo()
// Setinfo. Nothing to support here at present.
static int
fatfs_setinfo(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name,
int key,
void *buf,
int len)
{
CYG_TRACE6(TFS, "Getinfo mte=%p dir=%p name='%s' key=%d buf=%p len=%d",
mte, dir, name, key, buf, len);
return EINVAL;
}
//==========================================================================
// File operations
// -------------------------------------------------------------------------
// fatfs_fo_read()
// Read data from the file.
static int
fatfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
cyg_uint32 pos = fp->f_offset;
ssize_t resid = uio->uio_resid;
int i;
CYG_TRACE3(TFO, "Read fp=%p uio=%p pos=%d", fp, uio, pos);
// Loop over the io vectors until there are none left
for (i = 0; i < uio->uio_iovcnt; i++)
{
cyg_iovec *iov = &uio->uio_iov[i];
char *buf = (char *)iov->iov_base;
off_t len = iov->iov_len;
// Loop over each vector filling it with data from the file.
while (len > 0 && pos < node->size)
{
cyg_uint32 l = len;
int err;
// Adjust size to end of file if necessary
if (l > node->size-pos)
l = node->size-pos;
// Read data
err = fatfs_read_data(disk, node, buf, &l, pos);
if (err != ENOERR)
return err;
// Update working vars
len -= l;
buf += l;
pos += l;
resid -= l;
}
}
// We successfully read some data,
// update the access time, file offset and transfer residue.
node->atime = cyg_timestamp();
uio->uio_resid = resid;
fp->f_offset = (off_t)pos;
return ENOERR;
}
// -------------------------------------------------------------------------
// fatfs_fo_write()
// Write data to file.
static int
fatfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
cyg_uint32 pos = fp->f_offset;
ssize_t resid = uio->uio_resid;
int err = ENOERR;
int i;
CYG_TRACE3(TFO, "Write fp=%p uio=%p pos=%d", fp, uio, pos);
// If the APPEND mode bit was supplied, force all writes to
// the end of the file.
if (fp->f_flag & CYG_FAPPEND)
pos = fp->f_offset = node->size;
// Check that pos is within current file size, or at the very end.
if (pos < 0 || pos > node->size)
return EINVAL;
// Now loop over the iovecs until they are all done, or
// we get an error.
for (i = 0; i < uio->uio_iovcnt; i++)
{
cyg_iovec *iov = &uio->uio_iov[i];
char *buf = (char *)iov->iov_base;
off_t len = iov->iov_len;
// Loop over the vector writing it to the file until it has
// all been done.
while (len > 0)
{
cyg_uint32 l = len;
// Write data
err = fatfs_write_data(disk, node, buf, &l, pos);
// Update working vars
len -= l;
buf += l;
pos += l;
resid -= l;
// Stop writing if there is no more space in the file and
// indicate end of data.
if (err == ENOSPC)
break;
if (err != ENOERR)
return err;
}
}
// We wrote some data successfully, update the modified and access
// times of the node, increase its size appropriately, and update
// the file offset and transfer residue.
node->mtime =
node->atime = cyg_timestamp();
if (pos > node->size)
node->size = pos;
uio->uio_resid = resid;
fp->f_offset = (off_t)pos;
return err;
}
// -------------------------------------------------------------------------
// fatfs_fo_lseek()
// Seek to a new file position.
static int
fatfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
{
fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
off_t pos = *apos;
CYG_TRACE3(TFO, "Lseek fp=%p pos=%d whence=%d", fp, fp->f_offset, whence);
switch (whence)
{
case SEEK_SET:
// Pos is already where we want to be.
break;
case SEEK_CUR:
// Add pos to current offset.
pos += fp->f_offset;
break;
case SEEK_END:
// Add pos to file size.
pos += node->size;
break;
default:
return EINVAL;
}
// Check that pos is still within current file size, or at the
// very end.
if (pos < 0 || pos > node->size)
return EINVAL;
// All OK, set fp offset and return new position.
*apos = fp->f_offset = pos;
CYG_TRACE2(TFO, "Lseek fp=%p new pos=%d", fp, *apos);
return ENOERR;
}
// -------------------------------------------------------------------------
// fatfs_fo_ioctl()
// Handle ioctls. Currently none are defined.
static int
fatfs_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, CYG_ADDRWORD data)
{
CYG_TRACE3(TFO, "Ioctl fp=%p com=%x data=%x", fp, com, data);
return EINVAL;
}
// -------------------------------------------------------------------------
// fatfs_fo_fsync().
// Force the file out to data storage.
static int
fatfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
{
fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
int err;
CYG_TRACE2(TFO, "Fsync fp=%p mode=%d", fp, mode);
err = fatfs_write_file_attr(disk, node);
if (ENOERR == err)
err = cyg_blib_sync(&disk->blib);
return err;
}
// -------------------------------------------------------------------------
// fatfs_fo_close()
// Close a file.
static int
fatfs_fo_close(struct CYG_FILE_TAG *fp)
{
fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
int err = ENOERR;
CYG_TRACE1(TFO, "Close fp=%p", fp);
if (node != disk->root)
err = fatfs_write_file_attr(disk, node);
fatfs_node_unref(disk, node);
return err;
}
// -------------------------------------------------------------------------
// fatfs_fo_fstat()
// Get file status.
static int
fatfs_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf)
{
fatfs_node_t *node = (fatfs_node_t *)fp->f_data;
CYG_TRACE2(TFO, "Fstat fp=%p buf=%p", fp, buf);
// Fill in the status
buf->st_mode = node->mode;
buf->st_ino = (ino_t)node->cluster;
buf->st_dev = 0;
buf->st_nlink = 1;
buf->st_uid = 0;
buf->st_gid = 0;
buf->st_size = node->size;
buf->st_atime = node->atime;
buf->st_mtime = node->mtime;
buf->st_ctime = node->ctime;
return ENOERR;
}
// -------------------------------------------------------------------------
// fatfs_fo_getinfo()
// Get info.
static int
fatfs_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf, int len)
{
CYG_TRACE4(TFO, "Getinfo fp=%p key=%d buf=%p len=%d", fp, key, buf, len);
return EINVAL;
}
// -------------------------------------------------------------------------
// fatfs_fo_setinfo()
// Set info.
static int
fatfs_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf, int len)
{
CYG_TRACE4(TFO, "Setinfo fp=%p key=%d buf=%p len=%d", fp, key, buf, len);
return EINVAL;
}
//==========================================================================
// Directory operations
// -------------------------------------------------------------------------
// fatfs_fo_dirread()
// Read a single directory entry from a file.
static int
fatfs_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
fatfs_disk_t *disk = (fatfs_disk_t *)fp->f_mte->data;
fatfs_node_t *dir = (fatfs_node_t *)fp->f_data;
struct dirent *ent = (struct dirent *)uio->uio_iov[0].iov_base;
cyg_uint32 pos = fp->f_offset;
char *nbuf = ent->d_name;
off_t len = uio->uio_iov[0].iov_len;
fatfs_node_t node;
int err;
CYG_TRACE3(TFO, "Dirread fp=%p uio=%p pos=%d", fp, uio, pos);
if (len < sizeof(struct dirent))
return EINVAL;
err = fatfs_get_dir_entry_node(disk, dir, &pos, &node);
if (err != ENOERR)
return (err == EEOF ? ENOERR : err);
strcpy(nbuf, node.filename);
dir->atime = cyg_timestamp();
uio->uio_resid -= sizeof(struct dirent);
fp->f_offset = (off_t)(pos + 1);
return ENOERR;
}
// -------------------------------------------------------------------------
// fatfs_fo_dirlseek()
// Seek directory to start.
static int
fatfs_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence)
{
CYG_TRACE2(TFO, "Dirlseek fp=%p whence=%d", fp, whence);
// Only allow SEEK_SET to zero
if (whence != SEEK_SET || *pos != 0)
return EINVAL;
*pos = fp->f_offset = 0;
return ENOERR;
}
// -------------------------------------------------------------------------
// EOF fatfs.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -