diff options
| -rw-r--r-- | disk/part.c | 31 | ||||
| -rw-r--r-- | fs/fs.c | 104 | ||||
| -rw-r--r-- | include/fs.h | 67 | ||||
| -rw-r--r-- | include/part.h | 9 | 
4 files changed, 199 insertions, 12 deletions
| diff --git a/disk/part.c b/disk/part.c index c67fdacc792..aa9183d6964 100644 --- a/disk/part.c +++ b/disk/part.c @@ -331,6 +331,24 @@ int part_get_info(struct blk_desc *dev_desc, int part,  	return -1;  } +int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info) +{ +	info->start = 0; +	info->size = dev_desc->lba; +	info->blksz = dev_desc->blksz; +	info->bootable = 0; +	strcpy((char *)info->type, BOOT_PART_TYPE); +	strcpy((char *)info->name, "Whole Disk"); +#if CONFIG_IS_ENABLED(PARTITION_UUIDS) +	info->uuid[0] = 0; +#endif +#ifdef CONFIG_PARTITION_TYPE_GUID +	info->type_guid[0] = 0; +#endif + +	return 0; +} +  int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,  			  struct blk_desc **dev_desc)  { @@ -523,18 +541,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str,  		(*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); -		info->start = 0; -		info->size = (*dev_desc)->lba; -		info->blksz = (*dev_desc)->blksz; -		info->bootable = 0; -		strcpy((char *)info->type, BOOT_PART_TYPE); -		strcpy((char *)info->name, "Whole Disk"); -#if CONFIG_IS_ENABLED(PARTITION_UUIDS) -		info->uuid[0] = 0; -#endif -#ifdef CONFIG_PARTITION_TYPE_GUID -		info->type_guid[0] = 0; -#endif +		part_get_info_whole_disk(*dev_desc, info);  		ret = 0;  		goto cleanup; @@ -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; @@ -69,6 +70,12 @@ 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; +} +  struct fstype_info {  	int fstype;  	char *name; @@ -92,6 +99,20 @@ 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);  };  static struct fstype_info fstypes[] = { @@ -112,6 +133,7 @@ static struct fstype_info fstypes[] = {  		.write = fs_write_unsupported,  #endif  		.uuid = fs_uuid_unsupported, +		.opendir = fs_opendir_unsupported,  	},  #endif  #ifdef CONFIG_FS_EXT4 @@ -131,6 +153,7 @@ static struct fstype_info fstypes[] = {  		.write = fs_write_unsupported,  #endif  		.uuid = ext4fs_uuid, +		.opendir = fs_opendir_unsupported,  	},  #endif  #ifdef CONFIG_SANDBOX @@ -146,6 +169,7 @@ static struct fstype_info fstypes[] = {  		.read = fs_read_sandbox,  		.write = fs_write_sandbox,  		.uuid = fs_uuid_unsupported, +		.opendir = fs_opendir_unsupported,  	},  #endif  #ifdef CONFIG_CMD_UBIFS @@ -161,6 +185,7 @@ static struct fstype_info fstypes[] = {  		.read = ubifs_read,  		.write = fs_write_unsupported,  		.uuid = fs_uuid_unsupported, +		.opendir = fs_opendir_unsupported,  	},  #endif  	{ @@ -175,6 +200,7 @@ static struct fstype_info fstypes[] = {  		.read = fs_read_unsupported,  		.write = fs_write_unsupported,  		.uuid = fs_uuid_unsupported, +		.opendir = fs_opendir_unsupported,  	},  }; @@ -228,6 +254,31 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)  		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;  		}  	} @@ -334,6 +385,59 @@ 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 do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],  		int fstype)  { diff --git a/include/fs.h b/include/fs.h index 2f2aca8378b..0869ad6e80c 100644 --- a/include/fs.h +++ b/include/fs.h @@ -27,6 +27,17 @@  int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype);  /* + * fs_set_blk_dev_with_part - Set current block device + partition + * + * Similar to fs_set_blk_dev(), but useful for cases where you already + * know the blk_desc and part number. + * + * Returns 0 on success. + * Returns non-zero if invalid partition or error accessing the disk. + */ +int fs_set_blk_dev_with_part(struct blk_desc *desc, int part); + +/*   * Print the list of files on the partition previously set by fs_set_blk_dev(),   * in directory "dirname".   * @@ -79,6 +90,62 @@ int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,  	     loff_t *actwrite);  /* + * Directory entry types, matches the subset of DT_x in posix readdir() + * which apply to u-boot. + */ +#define FS_DT_DIR  4         /* directory */ +#define FS_DT_REG  8         /* regular file */ +#define FS_DT_LNK  10        /* symbolic link */ + +/* + * A directory entry, returned by fs_readdir().  Returns information + * about the file/directory at the current directory entry position. + */ +struct fs_dirent { +	unsigned type;       /* one of FS_DT_x (not a mask) */ +	loff_t size;         /* size in bytes */ +	char name[256]; +}; + +/* Note: fs_dir_stream should be treated as opaque to the user of fs layer */ +struct fs_dir_stream { +	/* private to fs. layer: */ +	struct blk_desc *desc; +	int part; +}; + +/* + * fs_opendir - Open a directory + * + * @filename: the path to directory to open + * @return a pointer to the directory stream or NULL on error and errno + *    set appropriately + */ +struct fs_dir_stream *fs_opendir(const char *filename); + +/* + * fs_readdir - Read the next directory entry in the directory stream. + * + * Works in an analogous way to posix readdir().  The previously returned + * directory entry is no longer valid after calling fs_readdir() again. + * After fs_closedir() is called, the returned directory entry is no + * longer valid. + * + * @dirs: the directory stream + * @return the next directory entry (only valid until next fs_readdir() or + *    fs_closedir() call, do not attempt to free()) or NULL if the end of + *    the directory is reached. + */ +struct fs_dirent *fs_readdir(struct fs_dir_stream *dirs); + +/* + * fs_closedir - close a directory stream + * + * @dirs: the directory stream + */ +void fs_closedir(struct fs_dir_stream *dirs); + +/*   * Common implementation for various filesystem commands, optionally limited   * to a specific filesystem type via the fstype parameter.   */ diff --git a/include/part.h b/include/part.h index 0d5c99836b2..86117a7ce5d 100644 --- a/include/part.h +++ b/include/part.h @@ -98,6 +98,12 @@ int host_get_dev_err(int dev, struct blk_desc **blk_devp);  /* disk/part.c */  int part_get_info(struct blk_desc *dev_desc, int part, disk_partition_t *info); +/** + * part_get_info_whole_disk() - get partition info for the special case of + * a partition occupying the entire disk. + */ +int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info); +  void part_print(struct blk_desc *dev_desc);  void part_init(struct blk_desc *dev_desc);  void dev_print(struct blk_desc *dev_desc); @@ -203,6 +209,9 @@ static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; }  static inline int part_get_info(struct blk_desc *dev_desc, int part,  				disk_partition_t *info) { return -1; } +static inline int part_get_info_whole_disk(struct blk_desc *dev_desc, +					   disk_partition_t *info) +{ return -1; }  static inline void part_print(struct blk_desc *dev_desc) {}  static inline void part_init(struct blk_desc *dev_desc) {}  static inline void dev_print(struct blk_desc *dev_desc) {} | 
