📄 fatfs.c
字号:
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->dentry);
}
if (err != ENOERR)
return err;
if (S_ISDIR(node->dentry.mode))
return EISDIR;
#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
// if the file is read only and is opened for writing
// fail with permission error
if (S_FATFS_ISRDONLY(node->dentry.attrib) && (mode & O_WRONLY))
return EACCES;
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES
// Allocate file object private data and
// make a reference to this file node
fd = alloc_fatfs_fd(disk, node);
if (NULL == fd)
return EMFILE;
fatfs_node_ref(disk, node);
// Initialize the file object
if (mode & O_APPEND)
fatfs_setpos(disk, &node->dentry, &fd->pos, node->dentry.size);
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->dentry.size : 0;
file->f_data = (CYG_ADDRWORD) fd;
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;
#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
// if the file is read only fail with permission error
if (S_FATFS_ISRDONLY(ds.node->dentry.attrib))
return EPERM;
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES
err = fatfs_delete_file(disk, &ds.node->dentry);
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_uint8 shortname[12+1]={0};
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_dir_entry_t new_dir_dentry;
// The entry does not exist, and it is the last element in
// the pathname, so we can create it here
err=create_shortname(dir, disk,fatfs_utf8_table, ds.name,ds.namelen,shortname);
if(err<0) return err;
err = fatfs_create_dir(disk,
&ds.dir->dentry,
shortname,
strlen(shortname),
ds.name,
ds.namelen,
&new_dir_dentry);
if (err != ENOERR)
return err;
fatfs_node_alloc(disk, &new_dir_dentry);
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;
fatfs_node_t *node;
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;
if (!S_ISDIR(ds.node->dentry.mode))
return EPERM;
if (ds.node->refcnt > 0)
return EBUSY;
err = fatfs_delete_file(disk, &ds.node->dentry);
if (err == ENOERR)
{
node = fatfs_node_find( disk, ".", 1, ds.node->dentry.cluster );
if (node != NULL)
fatfs_node_free(disk, node);
node = fatfs_node_find( disk, "..", 2, ds.node->dentry.cluster );
if (node != NULL)
fatfs_node_free(disk, node);
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_uint8 shortname[12+1]={0};
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;
#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
// if the file is read only fail with permission error
if (S_FATFS_ISRDONLY(ds1.node->dentry.attrib))
return EPERM;
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES
// Protect the found nodes from being reused
// by the search for the ds2 dir/node pair
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);
// Check if the target name already exists
if (err == ENOERR && ds2.last)
{
err = EEXIST;
goto out;
}
// Check if the target dir doesn't exist
if (err == ENOENT && !ds2.last)
goto out;
// Check if the target and the source are the same
if (ds1.node == ds2.node)
{
err = ENOERR;
goto out;
}
err=create_shortname(dir2, disk,fatfs_utf8_table, ds2.name,ds2.namelen,shortname);
if(err<0) return err;
err = fatfs_rename_file(disk,
&ds1.dir->dentry,
&ds1.node->dentry,
&ds2.dir->dentry,
shortname,
strlen(shortname),
ds2.name,
ds2.namelen);
fatfs_node_rehash(disk, ds1.node);
out:
// Unreference previousely protected nodes
fatfs_node_unref(disk, ds1.dir);
fatfs_node_unref(disk, ds1.node);
if (err == ENOERR)
{
ds1.dir->dentry.atime =
ds1.dir->dentry.mtime =
ds2.dir->dentry.atime =
ds2.dir->dentry.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_fd_t *fd;
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;
if (!S_ISDIR(ds.node->dentry.mode))
return ENOTDIR;
// Allocate file object private data and
// make a reference to this file node
fd = alloc_fatfs_fd(disk, ds.node);
if (NULL == fd)
return EMFILE;
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) fd;
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 ds1,ds2,*ds_out;
int err;
init_dirsearch(&ds1, disk, (fatfs_node_t *) dir, name);
err = fatfs_find(&ds1);
if (err != ENOERR)
return err;
if (!S_ISDIR(ds1.node->dentry.mode))
return ENOTDIR;
if((ds1.node->dentry.filename[0]=='.')&&
(ds1.node->dentry.filename[1]=='.')&&
(ds1.node->dentry.filename[2]==0))
{
if(ds1.node->dentry.cluster==0)
{
ds2.node=disk->root;
ds_out=&ds2;
}
else
{
init_dirsearch(&ds2,disk,ds1.node,".");
err=fatfs_find(&ds2);
if(err!=ENOERR)
return err;
ds_out=&ds2;
}
}
else
{
ds_out=&ds1;
}
if(ds_out->node!=disk->root)
fatfs_node_ref(disk,ds_out->node);
*dir_out = (cyg_dir) ds_out->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->dentry.mode;
#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
if (!S_FATFS_ISRDONLY(ds.node->dentry.attrib))
buf->st_mode |= (S_IWUSR | S_IWGRP | S_IWOTH);
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES
buf->st_ino = (ino_t) ds.node->dentry.cluster;
buf->st_dev = 0;
buf->st_nlink = 1;
buf->st_uid = 0;
buf->st_gid = 0;
buf->st_size = ds.node->dentry.size;
buf->st_atime = ds.node->dentry.atime;
buf->st_mtime = ds.node->dentry.mtime;
buf->st_ctime = ds.node->dentry.ctime;
return ENOERR;
}
#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
// -------------------------------------------------------------------------
// fatfs_set_attrib()
// Set FAT file system attributes for specified file
static int
fatfs_set_attrib(cyg_mtab_entry *mte,
cyg_dir dir,
const char *name,
const cyg_fs_attrib_t new_attrib)
{
fatfs_disk_t *disk = (fatfs_disk_t *) mte->data;
fatfs_dirsearch_t ds;
int err;
CYG_TRACE4(TFS, "set_attrib mte=%p dir=%p name='%s' buf=%x",
mte, dir, name, new_attrib);
// Verify new_mode is valid
if ((new_attrib & S_FATFS_ATTRIB) != new_attrib)
return EINVAL;
init_dirsearch(&ds, disk, (fatfs_node_t *) dir, name);
err = fatfs_find(&ds);
if (err != ENOERR)
return err;
// Change the "changeable" mode bits for the file.
ds.node->dentry.attrib =
(ds.node->dentry.attrib & (~S_FATFS_ATTRIB)) | new_attrib;
return fatfs_write_dir_entry(disk,&ds.node->dentry);
}
// -------------------------------------------------------------------------
// fatfs_get_attrib()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -