X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=fs%2Ffs.c;h=adae98d021eef1b2c4640a12aef9b0affa43b9d1;hb=a68b0e11ea774492713a65d9fd5bb525fcaefff3;hp=595ff1fe69b5bc446ebd32c3d7badd7726348d63;hpb=e35929e4a1ffe861f2f45e107986568c56c4f077;p=oweals%2Fu-boot.git diff --git a/fs/fs.c b/fs/fs.c index 595ff1fe69..adae98d021 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -1,7 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0 */ #include @@ -14,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +21,7 @@ DECLARE_GLOBAL_DATA_PTR; static struct blk_desc *fs_dev_desc; +static int fs_dev_part; static disk_partition_t fs_partition; static int fs_type = FS_TYPE_ANY; @@ -36,6 +37,35 @@ static inline int fs_ls_unsupported(const char *dirname) return -1; } +/* generic implementation of ls in terms of opendir/readdir/closedir */ +__maybe_unused +static int fs_ls_generic(const char *dirname) +{ + struct fs_dir_stream *dirs; + struct fs_dirent *dent; + int nfiles = 0, ndirs = 0; + + dirs = fs_opendir(dirname); + if (!dirs) + return -errno; + + while ((dent = fs_readdir(dirs))) { + if (dent->type == FS_DT_DIR) { + printf(" %s/\n", dent->name); + ndirs++; + } else { + printf(" %8lld %s\n", dent->size, dent->name); + nfiles++; + } + } + + fs_closedir(dirs); + + printf("\n%d file(s), %d dir(s)\n\n", nfiles, ndirs); + + return 0; +} + static inline int fs_exists_unsupported(const char *filename) { return 0; @@ -69,6 +99,22 @@ static inline int fs_uuid_unsupported(char *uuid_str) return -1; } +static inline int fs_opendir_unsupported(const char *filename, + struct fs_dir_stream **dirs) +{ + return -EACCES; +} + +static inline int fs_unlink_unsupported(const char *filename) +{ + return -1; +} + +static inline int fs_mkdir_unsupported(const char *dirname) +{ + return -1; +} + struct fstype_info { int fstype; char *name; @@ -76,7 +122,7 @@ struct fstype_info { * Is it legal to pass NULL as .probe()'s fs_dev_desc parameter? This * should be false in most cases. For "virtual" filesystems which * aren't based on a U-Boot block device (e.g. sandbox), this can be - * set to true. This should also be true for the dumm entry at the end + * set to true. This should also be true for the dummy entry at the end * of fstypes[], since that is essentially a "virtual" (non-existent) * filesystem. */ @@ -92,6 +138,22 @@ struct fstype_info { loff_t len, loff_t *actwrite); void (*close)(void); int (*uuid)(char *uuid_str); + /* + * Open a directory stream. On success return 0 and directory + * stream pointer via 'dirsp'. On error, return -errno. See + * fs_opendir(). + */ + int (*opendir)(const char *filename, struct fs_dir_stream **dirsp); + /* + * Read next entry from directory stream. On success return 0 + * and directory entry pointer via 'dentp'. On error return + * -errno. See fs_readdir(). + */ + int (*readdir)(struct fs_dir_stream *dirs, struct fs_dirent **dentp); + /* see fs_closedir() */ + void (*closedir)(struct fs_dir_stream *dirs); + int (*unlink)(const char *filename); + int (*mkdir)(const char *dirname); }; static struct fstype_info fstypes[] = { @@ -102,16 +164,23 @@ static struct fstype_info fstypes[] = { .null_dev_desc_ok = false, .probe = fat_set_blk_dev, .close = fat_close, - .ls = file_fat_ls, + .ls = fs_ls_generic, .exists = fat_exists, .size = fat_size, .read = fat_read_file, #ifdef CONFIG_FAT_WRITE .write = file_fat_write, + .unlink = fat_unlink, + .mkdir = fat_mkdir, #else .write = fs_write_unsupported, + .unlink = fs_unlink_unsupported, + .mkdir = fs_mkdir_unsupported, #endif .uuid = fs_uuid_unsupported, + .opendir = fat_opendir, + .readdir = fat_readdir, + .closedir = fat_closedir, }, #endif #ifdef CONFIG_FS_EXT4 @@ -131,6 +200,9 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = ext4fs_uuid, + .opendir = fs_opendir_unsupported, + .unlink = fs_unlink_unsupported, + .mkdir = fs_mkdir_unsupported, }, #endif #ifdef CONFIG_SANDBOX @@ -146,6 +218,9 @@ static struct fstype_info fstypes[] = { .read = fs_read_sandbox, .write = fs_write_sandbox, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, + .unlink = fs_unlink_unsupported, + .mkdir = fs_mkdir_unsupported, }, #endif #ifdef CONFIG_CMD_UBIFS @@ -161,6 +236,27 @@ static struct fstype_info fstypes[] = { .read = ubifs_read, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, + .unlink = fs_unlink_unsupported, + .mkdir = fs_mkdir_unsupported, + }, +#endif +#ifdef CONFIG_FS_BTRFS + { + .fstype = FS_TYPE_BTRFS, + .name = "btrfs", + .null_dev_desc_ok = false, + .probe = btrfs_probe, + .close = btrfs_close, + .ls = btrfs_ls, + .exists = btrfs_exists, + .size = btrfs_size, + .read = btrfs_read, + .write = fs_write_unsupported, + .uuid = btrfs_uuid, + .opendir = fs_opendir_unsupported, + .unlink = fs_unlink_unsupported, + .mkdir = fs_mkdir_unsupported, }, #endif { @@ -175,6 +271,9 @@ static struct fstype_info fstypes[] = { .read = fs_read_unsupported, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, + .unlink = fs_unlink_unsupported, + .mkdir = fs_mkdir_unsupported, }, }; @@ -192,6 +291,19 @@ static struct fstype_info *fs_get_info(int fstype) return info; } +/** + * fs_get_type_name() - Get type of current filesystem + * + * Return: Pointer to filesystem name + * + * Returns a string describing the current filesystem, or the sentinel + * "unsupported" for any unrecognised filesystem. + */ +const char *fs_get_type_name(void) +{ + return fs_get_info(fs_type)->name; +} + int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) { struct fstype_info *info; @@ -226,6 +338,31 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) if (!fs_dev_desc && !info->null_dev_desc_ok) continue; + if (!info->probe(fs_dev_desc, &fs_partition)) { + fs_type = info->fstype; + fs_dev_part = part; + return 0; + } + } + + return -1; +} + +/* set current blk device w/ blk_desc + partition # */ +int fs_set_blk_dev_with_part(struct blk_desc *desc, int part) +{ + struct fstype_info *info; + int ret, i; + + if (part >= 1) + ret = part_get_info(desc, part, &fs_partition); + else + ret = part_get_info_whole_disk(desc, &fs_partition); + if (ret) + return ret; + fs_dev_desc = desc; + + for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) { if (!info->probe(fs_dev_desc, &fs_partition)) { fs_type = info->fstype; return 0; @@ -308,7 +445,7 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, /* If we requested a specific number of bytes, check we got it */ if (ret == 0 && len && *actread != len) - printf("** %s shorter than offset + len **\n", filename); + debug("** %s shorter than offset + len **\n", filename); fs_close(); return ret; @@ -334,6 +471,86 @@ int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, return ret; } +struct fs_dir_stream *fs_opendir(const char *filename) +{ + struct fstype_info *info = fs_get_info(fs_type); + struct fs_dir_stream *dirs = NULL; + int ret; + + ret = info->opendir(filename, &dirs); + fs_close(); + if (ret) { + errno = -ret; + return NULL; + } + + dirs->desc = fs_dev_desc; + dirs->part = fs_dev_part; + + return dirs; +} + +struct fs_dirent *fs_readdir(struct fs_dir_stream *dirs) +{ + struct fstype_info *info; + struct fs_dirent *dirent; + int ret; + + fs_set_blk_dev_with_part(dirs->desc, dirs->part); + info = fs_get_info(fs_type); + + ret = info->readdir(dirs, &dirent); + fs_close(); + if (ret) { + errno = -ret; + return NULL; + } + + return dirent; +} + +void fs_closedir(struct fs_dir_stream *dirs) +{ + struct fstype_info *info; + + if (!dirs) + return; + + fs_set_blk_dev_with_part(dirs->desc, dirs->part); + info = fs_get_info(fs_type); + + info->closedir(dirs); + fs_close(); +} + +int fs_unlink(const char *filename) +{ + int ret; + + struct fstype_info *info = fs_get_info(fs_type); + + ret = info->unlink(filename); + + fs_type = FS_TYPE_ANY; + fs_close(); + + return ret; +} + +int fs_mkdir(const char *dirname) +{ + int ret; + + struct fstype_info *info = fs_get_info(fs_type); + + ret = info->mkdir(dirname); + + fs_type = FS_TYPE_ANY; + fs_close(); + + return ret; +} + int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int fstype) { @@ -348,7 +565,7 @@ int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], if (fs_size(argv[3], &size) < 0) return CMD_RET_FAILURE; - setenv_hex("filesize", size); + env_set_hex("filesize", size); return 0; } @@ -379,7 +596,7 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], if (ep == argv[3] || *ep != '\0') return CMD_RET_USAGE; } else { - addr_str = getenv("loadaddr"); + addr_str = env_get("loadaddr"); if (addr_str != NULL) addr = simple_strtoul(addr_str, NULL, 16); else @@ -388,7 +605,7 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], if (argc >= 5) { filename = argv[4]; } else { - filename = getenv("bootfile"); + filename = env_get("bootfile"); if (!filename) { puts("** No boot file defined **\n"); return 1; @@ -417,8 +634,8 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], } puts("\n"); - setenv_hex("fileaddr", addr); - setenv_hex("filesize", len_read); + env_set_hex("fileaddr", addr); + env_set_hex("filesize", len_read); return 0; } @@ -509,7 +726,7 @@ int do_fs_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], return CMD_RET_FAILURE; if (argc == 4) - setenv(argv[3], uuid); + env_set(argv[3], uuid); else printf("%s\n", uuid); @@ -529,10 +746,44 @@ int do_fs_type(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) info = fs_get_info(fs_type); if (argc == 4) - setenv(argv[3], info->name); + env_set(argv[3], info->name); else printf("%s\n", info->name); return CMD_RET_SUCCESS; } +int do_rm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], + int fstype) +{ + if (argc != 4) + return CMD_RET_USAGE; + + if (fs_set_blk_dev(argv[1], argv[2], fstype)) + return 1; + + if (fs_unlink(argv[3])) + return 1; + + return 0; +} + +int do_mkdir(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], + int fstype) +{ + int ret; + + if (argc != 4) + return CMD_RET_USAGE; + + if (fs_set_blk_dev(argv[1], argv[2], fstype)) + return 1; + + ret = fs_mkdir(argv[3]); + if (ret) { + printf("** Unable to create a directory \"%s\" **\n", argv[3]); + return 1; + } + + return 0; +}