📄 fatfs.c
字号:
err = fatfs_get_disk_info(disk);
if (err != ENOERR)
{
fatfs_tcache_delete(disk);
cyg_blib_delete(&disk->blib);
free(disk->bcache_mem);
free(disk);
return err;
}
#if TFS
print_disk_info(disk);
#endif
CYG_TRACE0(TFS, "Initializing node cache");
fatfs_node_cache_init(disk);
CYG_TRACE0(TFS, "Initializing root node");
fatfs_get_root_node(disk, &root_data);
disk->root = fatfs_node_alloc(disk, &root_data);
fatfs_node_ref(disk, disk->root);
mte->root = (cyg_dir)disk->root;
mte->data = (CYG_ADDRWORD)disk;
CYG_TRACE0(TFS, "Disk mounted");
return ENOERR;
}
// -------------------------------------------------------------------------
// fatfs_umount()
// Unmount the filesystem. This will currently only succeed if the
// filesystem is empty.
static int
fatfs_umount(cyg_mtab_entry *mte)
{
fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
fatfs_node_t *root = (fatfs_node_t *)mte->root;
CYG_TRACE3(TFS, "Umount mte=%p %d live nodes %d dead nodes",
mte, fatfs_get_live_node_count(disk),
fatfs_get_dead_node_count(disk));
if (root->refcnt > 1)
return EBUSY;
if (fatfs_get_live_node_count(disk) != 1)
return EBUSY;
fatfs_node_unref(disk, root);
fatfs_node_cache_flush(disk);
fatfs_tcache_delete(disk);
// FIXME: cache delete can fail if cache can't be synced
cyg_blib_delete(&disk->blib);
free(disk->bcache_mem);
free(disk);
mte->root = CYG_DIR_NULL;
mte->data = (CYG_ADDRWORD)NULL;
CYG_TRACE0(TFS, "Disk umounted");
return ENOERR;
}
// -------------------------------------------------------------------------
// fatfs_open()
// Open a file for reading or writing.
static int
fatfs_open(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name,
int mode,
cyg_file *file)
{
fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
fatfs_node_t *node = NULL;
fatfs_dirsearch_t ds;
int err;
CYG_TRACE5(TFS, "Open mte=%p dir=%p name='%s' mode=%d file=%p",
mte, dir, name, mode, file);
init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);
err = fatfs_find(&ds);
if (err == ENOENT)
{
if (ds.last && (mode & O_CREAT))
{
fatfs_node_t node_data;
// No node there, if the O_CREAT bit is set then we must
// create a new one. The dir and name fields of the dirsearch
// object will have been updated so we know where to put it.
CYG_TRACE1(TFS, "Creating new file '%s'", name);
err = fatfs_create_file(disk, ds.dir, ds.name,
ds.namelen, &node_data);
if (err != ENOERR)
return err;
node = fatfs_node_alloc(disk, &node_data);
if (NULL == node)
return ENOMEM;
// Update directory times
ds.dir->atime =
ds.dir->mtime = cyg_timestamp();
err = ENOERR;
}
}
else if (err == ENOERR)
{
// The node exists. If the O_CREAT and O_EXCL bits are set, we
// must fail the open.
if ((mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
err = EEXIST;
else
node = ds.node;
}
if (err == ENOERR && (mode & O_TRUNC))
{
// If the O_TRUNC bit is set we must clean out the file data.
CYG_TRACE0(TFS, "Truncating file");
fatfs_trunc_file(disk, node);
}
if (err != ENOERR)
return err;
// Check that we actually have a file here
if (S_ISDIR(node->mode))
return EISDIR;
// Make a reference to this file node
fatfs_node_ref(disk, node);
// Initialize the file object
file->f_flag |= mode & CYG_FILE_MODE_MASK;
file->f_type = CYG_FILE_TYPE_FILE;
file->f_ops = &fatfs_fileops;
file->f_offset = (mode & O_APPEND) ? node->size : 0;
file->f_data = (CYG_ADDRWORD)node;
file->f_xops = 0;
return ENOERR;
}
// -------------------------------------------------------------------------
// fatfs_unlink()
// Remove a file link from its directory.
static int
fatfs_unlink(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name)
{
fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
fatfs_dirsearch_t ds;
int err;
CYG_TRACE3(TFS, "Unlink mte=%p dir=%p name='%s'", mte, dir, name);
init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);
err = fatfs_find(&ds);
if (err != ENOERR)
return err;
if (ds.node->refcnt > 0)
return EBUSY;
// Delete node
err = fatfs_delete_file(disk, ds.node);
if (err == ENOERR)
fatfs_node_free(disk, ds.node);
return err;
}
// -------------------------------------------------------------------------
// fatfs_mkdir()
// Create a new directory.
static int
fatfs_mkdir(cyg_mtab_entry *mte, cyg_dir dir, const char *name)
{
fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
fatfs_dirsearch_t ds;
int err;
CYG_TRACE3(TFS, "Mkdir mte=%p dir=%p name='%s'", mte, dir, name);
init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);
err = fatfs_find(&ds);
if (err == ENOENT)
{
if (ds.last)
{
fatfs_node_t node_data;
// The entry does not exist, and it is the last element in
// the pathname, so we can create it here.
err = fatfs_create_dir(disk, ds.dir, ds.name,
ds.namelen, &node_data);
if (err != ENOERR)
return err;
fatfs_node_alloc(disk, &node_data);
return ENOERR;
}
}
else if (err == ENOERR)
{
return EEXIST;
}
return err;
}
// -------------------------------------------------------------------------
// fatfs_rmdir()
// Remove a directory.
static int
fatfs_rmdir(cyg_mtab_entry *mte, cyg_dir dir, const char *name)
{
fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
fatfs_dirsearch_t ds;
int err;
CYG_TRACE3(TFS, "Rmdir mte=%p dir=%p name='%s'", mte, dir, name);
init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);
err = fatfs_find(&ds);
if (err != ENOERR)
return err;
// Check that this is actually a directory.
if (!S_ISDIR(ds.node->mode))
return EPERM;
if (ds.node->refcnt > 0)
return EBUSY;
err = fatfs_delete_file(disk, ds.node);
if (err == ENOERR)
fatfs_node_free(disk, ds.node);
return err;
}
// -------------------------------------------------------------------------
// fatfs_rename()
// Rename a file/dir.
static int
fatfs_rename(cyg_mtab_entry *mte,
cyg_dir dir1,
const char *name1,
cyg_dir dir2,
const char *name2)
{
fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
fatfs_dirsearch_t ds1, ds2;
int err;
CYG_TRACE5(TFS, "Rename mte=%p dir1=%p name1='%s' dir2=%p name2='%s'",
mte, dir1, name1, dir2, name2);
init_dirsearch(&ds1, disk, (fatfs_node_t *)dir1, name1);
err = fatfs_find(&ds1);
if (err != ENOERR)
return err;
// Protect the found nodes from being reused by the
// following search
fatfs_node_ref(disk, ds1.dir);
fatfs_node_ref(disk, ds1.node);
init_dirsearch(&ds2, disk, (fatfs_node_t *)dir2, name2);
err = fatfs_find(&ds2);
if (err == ENOERR && ds2.last)
{
err = EEXIST;
goto out;
}
if (err == ENOENT && !ds2.last)
goto out;
if (ds1.node == ds2.node)
{
err = ENOERR;
goto out;
}
err = fatfs_rename_file(disk, ds1.dir, ds1.node, ds2.dir,
ds2.name, ds2.namelen);
fatfs_node_rehash(disk, ds1.node);
out:
fatfs_node_unref(disk, ds1.dir);
fatfs_node_unref(disk, ds1.node);
if (err == ENOERR)
{
ds1.dir->atime =
ds1.dir->mtime =
ds2.dir->atime =
ds2.dir->mtime = cyg_timestamp();
}
return err;
}
// -------------------------------------------------------------------------
// fatfs_link()
// Make a new directory entry for a file.
static int
fatfs_link(cyg_mtab_entry *mte,
cyg_dir dir1,
const char *name1,
cyg_dir dir2,
const char *name2,
int type)
{
CYG_TRACE6(TFS, "Link mte=%p dir1=%p name1='%s' dir2=%p name2='%s' type=%d",
mte, dir1, name1, dir2, name2, type);
// Linking not supported
return EINVAL;
}
// -------------------------------------------------------------------------
// fatfs_opendir()
// Open a directory for reading.
static int
fatfs_opendir(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name,
cyg_file *file)
{
fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
fatfs_dirsearch_t ds;
int err;
CYG_TRACE4(TFS, "Opendir mte=%p dir=%p name='%s' file=%p",
mte, dir, name, file);
init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);
err = fatfs_find(&ds);
if (err != ENOERR)
return err;
// Check it is really a directory.
if (!S_ISDIR(ds.node->mode))
return ENOTDIR;
// Make a reference to this dir node
fatfs_node_ref(disk, ds.node);
// Initialize the file object
file->f_type = CYG_FILE_TYPE_FILE;
file->f_ops = &fatfs_dirops;
file->f_data = (CYG_ADDRWORD)ds.node;
file->f_xops = 0;
file->f_offset = 0;
return ENOERR;
}
// -------------------------------------------------------------------------
// fatfs_chdir()
// Change directory support.
static int
fatfs_chdir(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name,
cyg_dir *dir_out)
{
fatfs_disk_t *disk = (fatfs_disk_t *)mte->data;
CYG_TRACE4(TFS, "Chdir mte=%p dir=%p dir_out=%p name=%d",
mte, dir, dir_out, name);
if (dir_out != NULL)
{
// This is a request to get a new directory pointer in
// *dir_out.
fatfs_dirsearch_t ds;
int err;
init_dirsearch(&ds, disk, (fatfs_node_t *)dir, name);
err = fatfs_find(&ds);
if (err != ENOERR)
return err;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -