mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-17 20:51:39 +00:00
fs: fat: support unlink
In this patch, unlink support is added to FAT file system. A directory can be deleted only if it is empty. In this implementation, only a directory entry for a short file name will be removed. So entries for a long file name can and should be reclaimed with fsck. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
e2519daf5c
commit
f8240ce95d
3 changed files with 135 additions and 1 deletions
|
@ -1184,6 +1184,138 @@ int file_fat_write(const char *filename, void *buffer, loff_t offset,
|
||||||
return file_fat_write_at(filename, offset, buffer, maxsize, actwrite);
|
return file_fat_write_at(filename, offset, buffer, maxsize, actwrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fat_dir_entries(fat_itr *itr)
|
||||||
|
{
|
||||||
|
fat_itr *dirs;
|
||||||
|
fsdata fsdata = { .fatbuf = NULL, }, *mydata = &fsdata;
|
||||||
|
/* for FATBUFSIZE */
|
||||||
|
int count;
|
||||||
|
|
||||||
|
dirs = malloc_cache_aligned(sizeof(fat_itr));
|
||||||
|
if (!dirs) {
|
||||||
|
debug("Error: allocating memory\n");
|
||||||
|
count = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* duplicate fsdata */
|
||||||
|
fat_itr_child(dirs, itr);
|
||||||
|
fsdata = *dirs->fsdata;
|
||||||
|
|
||||||
|
/* allocate local fat buffer */
|
||||||
|
fsdata.fatbuf = malloc_cache_aligned(FATBUFSIZE);
|
||||||
|
if (!fsdata.fatbuf) {
|
||||||
|
debug("Error: allocating memory\n");
|
||||||
|
count = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
fsdata.fatbufnum = -1;
|
||||||
|
dirs->fsdata = &fsdata;
|
||||||
|
|
||||||
|
for (count = 0; fat_itr_next(dirs); count++)
|
||||||
|
;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
free(fsdata.fatbuf);
|
||||||
|
free(dirs);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int delete_dentry(fat_itr *itr)
|
||||||
|
{
|
||||||
|
fsdata *mydata = itr->fsdata;
|
||||||
|
dir_entry *dentptr = itr->dent;
|
||||||
|
|
||||||
|
/* free cluster blocks */
|
||||||
|
clear_fatent(mydata, START(dentptr));
|
||||||
|
if (flush_dirty_fat_buffer(mydata) < 0) {
|
||||||
|
printf("Error: flush fat buffer\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* update a directory entry
|
||||||
|
* TODO:
|
||||||
|
* - long file name support
|
||||||
|
* - find and mark the "new" first invalid entry as name[0]=0x00
|
||||||
|
*/
|
||||||
|
memset(dentptr, 0, sizeof(*dentptr));
|
||||||
|
dentptr->name[0] = 0xe5;
|
||||||
|
|
||||||
|
if (set_cluster(mydata, itr->clust, itr->block,
|
||||||
|
mydata->clust_size * mydata->sect_size) != 0) {
|
||||||
|
printf("error: writing directory entry\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fat_unlink(const char *filename)
|
||||||
|
{
|
||||||
|
fsdata fsdata = { .fatbuf = NULL, };
|
||||||
|
fat_itr *itr = NULL;
|
||||||
|
int n_entries, ret;
|
||||||
|
char *filename_copy, *dirname, *basename;
|
||||||
|
|
||||||
|
filename_copy = strdup(filename);
|
||||||
|
split_filename(filename_copy, &dirname, &basename);
|
||||||
|
|
||||||
|
if (!strcmp(dirname, "/") && !strcmp(basename, "")) {
|
||||||
|
printf("Error: cannot remove root\n");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
itr = malloc_cache_aligned(sizeof(fat_itr));
|
||||||
|
if (!itr) {
|
||||||
|
printf("Error: allocating memory\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fat_itr_root(itr, &fsdata);
|
||||||
|
if (ret)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
total_sector = fsdata.total_sect;
|
||||||
|
|
||||||
|
ret = fat_itr_resolve(itr, dirname, TYPE_DIR);
|
||||||
|
if (ret) {
|
||||||
|
printf("%s: doesn't exist (%d)\n", dirname, ret);
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!find_directory_entry(itr, basename)) {
|
||||||
|
printf("%s: doesn't exist\n", basename);
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fat_itr_isdir(itr)) {
|
||||||
|
n_entries = fat_dir_entries(itr);
|
||||||
|
if (n_entries < 0) {
|
||||||
|
ret = n_entries;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (n_entries > 2) {
|
||||||
|
printf("Error: directory is not empty: %d\n",
|
||||||
|
n_entries);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = delete_dentry(itr);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
free(fsdata.fatbuf);
|
||||||
|
free(itr);
|
||||||
|
free(filename_copy);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int fat_mkdir(const char *new_dirname)
|
int fat_mkdir(const char *new_dirname)
|
||||||
{
|
{
|
||||||
dir_entry *retdent;
|
dir_entry *retdent;
|
||||||
|
|
3
fs/fs.c
3
fs/fs.c
|
@ -170,16 +170,17 @@ static struct fstype_info fstypes[] = {
|
||||||
.read = fat_read_file,
|
.read = fat_read_file,
|
||||||
#ifdef CONFIG_FAT_WRITE
|
#ifdef CONFIG_FAT_WRITE
|
||||||
.write = file_fat_write,
|
.write = file_fat_write,
|
||||||
|
.unlink = fat_unlink,
|
||||||
.mkdir = fat_mkdir,
|
.mkdir = fat_mkdir,
|
||||||
#else
|
#else
|
||||||
.write = fs_write_unsupported,
|
.write = fs_write_unsupported,
|
||||||
|
.unlink = fs_unlink_unsupported,
|
||||||
.mkdir = fs_mkdir_unsupported,
|
.mkdir = fs_mkdir_unsupported,
|
||||||
#endif
|
#endif
|
||||||
.uuid = fs_uuid_unsupported,
|
.uuid = fs_uuid_unsupported,
|
||||||
.opendir = fat_opendir,
|
.opendir = fat_opendir,
|
||||||
.readdir = fat_readdir,
|
.readdir = fat_readdir,
|
||||||
.closedir = fat_closedir,
|
.closedir = fat_closedir,
|
||||||
.unlink = fs_unlink_unsupported,
|
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_FS_EXT4
|
#ifdef CONFIG_FS_EXT4
|
||||||
|
|
|
@ -203,6 +203,7 @@ int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
|
||||||
int fat_opendir(const char *filename, struct fs_dir_stream **dirsp);
|
int fat_opendir(const char *filename, struct fs_dir_stream **dirsp);
|
||||||
int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
|
int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
|
||||||
void fat_closedir(struct fs_dir_stream *dirs);
|
void fat_closedir(struct fs_dir_stream *dirs);
|
||||||
|
int fat_unlink(const char *filename);
|
||||||
int fat_mkdir(const char *dirname);
|
int fat_mkdir(const char *dirname);
|
||||||
void fat_close(void);
|
void fat_close(void);
|
||||||
#endif /* _FAT_H_ */
|
#endif /* _FAT_H_ */
|
||||||
|
|
Loading…
Add table
Reference in a new issue