[U-Boot] [PATCH 13/17] fs: fat: support mkdir
AKASHI Takahiro
takahiro.akashi at linaro.org
Tue Jul 24 02:01:05 UTC 2018
On Fri, Jul 20, 2018 at 07:14:21PM +0200, Heinrich Schuchardt wrote:
> On 07/20/2018 04:57 AM, AKASHI Takahiro wrote:
> > In this patch, mkdir support is added to FAT file system.
> > A newly created directory contains only "." and ".." entries.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
>
> The patch does set the creation date of the directory according to the
> real time clock but to 1980-01-01T00:00:00Z.
>
> $ ls /mnt/dir1/ -la --full-time
> drwxr-xr-x 2 root root 2048 1980-01-01 01:00:00.000000000 +0100 dir3
>
> Please, set the time correctly if the real time clock is available.
Good point, but I'd like to put this issue into future TODO list
as it will end up introducing a new API, such as gettimeofday()?
(and this is not a FAT-specific issue.)
Thanks,
-Takahiro AKASHI
> Best regards
>
> Heinrich
>
> > ---
> > fs/fat/fat_write.c | 138 +++++++++++++++++++++++++++++++++++++++++++++
> > fs/fs.c | 3 +-
> > include/fat.h | 1 +
> > 3 files changed, 141 insertions(+), 1 deletion(-)
> >
> > diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
> > index cc45a33876..781883c9f4 100644
> > --- a/fs/fat/fat_write.c
> > +++ b/fs/fat/fat_write.c
> > @@ -1185,3 +1185,141 @@ int file_fat_write(const char *filename, void *buffer, loff_t offset,
> > {
> > return file_fat_write_at(filename, offset, buffer, maxsize, actwrite);
> > }
> > +
> > +int fat_mkdir(const char *new_dirname)
> > +{
> > + dir_entry *retdent;
> > + fsdata datablock = { .fatbuf = NULL, };
> > + fsdata *mydata = &datablock;
> > + fat_itr *itr = NULL;
> > + char *dirname_copy, *parent, *dirname;
> > + char l_dirname[VFAT_MAXLEN_BYTES];
> > + int ret = -1;
> > + loff_t actwrite;
> > + unsigned int bytesperclust;
> > + dir_entry *dotdent = NULL;
> > +
> > + dirname_copy = strdup(new_dirname);
> > + if (!dirname_copy)
> > + goto exit;
> > +
> > + split_filename(dirname_copy, &parent, &dirname);
> > + if (!strlen(dirname)) {
> > + ret = -EINVAL;
> > + goto exit;
> > + }
> > +
> > + if (normalize_longname(l_dirname, dirname)) {
> > + printf("FAT: illegal filename (%s)\n", dirname);
> > + ret = -EINVAL;
> > + goto exit;
> > + }
> > +
> > + itr = malloc_cache_aligned(sizeof(fat_itr));
> > + if (!itr) {
> > + ret = -ENOMEM;
> > + goto exit;
> > + }
> > +
> > + ret = fat_itr_root(itr, &datablock);
> > + if (ret)
> > + goto exit;
> > +
> > + total_sector = datablock.bs_total_sect;
> > + if (total_sector == 0)
> > + total_sector = (int)cur_part_info.size; /* cast of lbaint_t */
> > +
> > + ret = fat_itr_resolve(itr, parent, TYPE_DIR);
> > + if (ret) {
> > + printf("%s: doesn't exist (%d)\n", parent, ret);
> > + goto exit;
> > + }
> > +
> > + retdent = find_directory_entry(itr, l_dirname);
> > +
> > + if (retdent) {
> > + printf("%s: already exists\n", l_dirname);
> > + ret = -EEXIST;
> > + goto exit;
> > + } else {
> > + if (itr->is_root) {
> > + /* root dir cannot have "." or ".." */
> > + if (!strcmp(l_dirname, ".") ||
> > + !strcmp(l_dirname, "..")) {
> > + ret = -EINVAL;
> > + goto exit;
> > + }
> > + }
> > +
> > + if (!itr->dent) {
> > + printf("Error: allocating new dir entry\n");
> > + ret = -EIO;
> > + goto exit;
> > + }
> > +
> > + memset(itr->dent, 0, sizeof(*itr->dent));
> > +
> > + /* Set short name to set alias checksum field in dir_slot */
> > + set_name(itr->dent, dirname);
> > + fill_dir_slot(itr, dirname);
> > +
> > + /* Set attribute as archieve for regular file */
> > + fill_dentry(itr->fsdata, itr->dent, dirname, 0, 0,
> > + ATTR_DIR | ATTR_ARCH);
> > +
> > + retdent = itr->dent;
> > + }
> > +
> > + /* Default entries */
> > + bytesperclust = mydata->clust_size * mydata->sect_size;
> > + dotdent = malloc_cache_aligned(bytesperclust);
> > + if (!dotdent) {
> > + ret = -ENOMEM;
> > + goto exit;
> > + }
> > + memset(dotdent, 0, bytesperclust);
> > +
> > + memcpy(dotdent[0].name, ". ", 8);
> > + memcpy(dotdent[0].ext, " ", 3);
> > + dotdent[0].attr = ATTR_DIR | ATTR_ARCH;
> > +
> > + memcpy(dotdent[1].name, ".. ", 8);
> > + memcpy(dotdent[1].ext, " ", 3);
> > + dotdent[1].attr = ATTR_DIR | ATTR_ARCH;
> > + set_start_cluster(mydata, &dotdent[1], itr->start_clust);
> > +
> > + ret = set_contents(mydata, retdent, 0, (__u8 *)dotdent, bytesperclust,
> > + &actwrite);
> > + if (ret < 0) {
> > + printf("Error: writing contents\n");
> > + goto exit;
> > + }
> > + /* Write twice for "." */
> > + set_start_cluster(mydata, &dotdent[0], START(retdent));
> > + ret = set_contents(mydata, retdent, 0, (__u8 *)dotdent, bytesperclust,
> > + &actwrite);
> > + if (ret < 0) {
> > + printf("Error: writing contents\n");
> > + goto exit;
> > + }
> > +
> > + /* Flush fat buffer */
> > + ret = flush_dirty_fat_buffer(mydata);
> > + if (ret) {
> > + printf("Error: flush fat buffer\n");
> > + goto exit;
> > + }
> > +
> > + /* Write directory table to device */
> > + ret = set_cluster(mydata, itr->clust, itr->block,
> > + mydata->clust_size * mydata->sect_size);
> > + if (ret)
> > + printf("Error: writing directory entry\n");
> > +
> > +exit:
> > + free(dirname_copy);
> > + free(mydata->fatbuf);
> > + free(itr);
> > + free(dotdent);
> > + return ret;
> > +}
> > diff --git a/fs/fs.c b/fs/fs.c
> > index 3cb6b21fe9..a92e060296 100644
> > --- a/fs/fs.c
> > +++ b/fs/fs.c
> > @@ -164,14 +164,15 @@ static struct fstype_info fstypes[] = {
> > .read = fat_read_file,
> > #ifdef CONFIG_FAT_WRITE
> > .write = file_fat_write,
> > + .mkdir = fat_mkdir,
> > #else
> > .write = fs_write_unsupported,
> > + .mkdir = fs_mkdir_unsupported,
> > #endif
> > .uuid = fs_uuid_unsupported,
> > .opendir = fat_opendir,
> > .readdir = fat_readdir,
> > .closedir = fat_closedir,
> > - .mkdir = fs_mkdir_unsupported,
> > },
> > #endif
> > #ifdef CONFIG_FS_EXT4
> > diff --git a/include/fat.h b/include/fat.h
> > index 295da0f243..039b6e03de 100644
> > --- a/include/fat.h
> > +++ b/include/fat.h
> > @@ -237,5 +237,6 @@ 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_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
> > void fat_closedir(struct fs_dir_stream *dirs);
> > +int fat_mkdir(const char *dirname);
> > void fat_close(void);
> > #endif /* _FAT_H_ */
> >
>
More information about the U-Boot
mailing list