[U-Boot] [PATCH 1/1]: filesystems : add "file exists" cmd

This adds "file exists" commands to generic FS as well as to FAT, EXT4, and UBIFS. Also adds "file size" command to UBIFS.
The return value for "file exists" commands is REVERSED i.e. they return 1 if file exists and 0 otherwise. This is a deliberate decision because those commands are supposed to be used almost exclusively in scripts and TRUE value is _not_ zero while FALSE is zero.
As of now the only way to check for a file existence is to attempt a read on that file (aka load.) That works but it makes an unnecessary read, overwrites memory at destination address if file not a zero length one, and outputs unnecessary messages to the console in any case.
Checking file existence in scripts is a valuable feature that allows the higher level software (e.g. Linux) to interact with U-Boot by creating some semaphore files and rebooting. We do use it quite extensively for system setup at manufacturing time and for other purposes (e.g. our Android "recovery" is implemented this way.)
Signed-off-by: Sergey Kubushyn ksi@koi8.net --- --- a/include/fs.h +++ b/include/fs.h @@ -90,6 +90,8 @@ int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int fstype); int file_exists(const char *dev_type, const char *dev_part, const char *file, int fstype); +int do_file_exists(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], + int fstype); int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int fstype);
--- a/fs/fs.c +++ b/fs/fs.c @@ -76,7 +76,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. */ @@ -449,6 +449,18 @@ int file_exists(const char *dev_type, const char *dev_part, const char *file, return fs_exists(file); }
+int do_file_exists(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; + + return fs_exists(argv[3]); +} + int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int fstype) {
--- a/cmd/ext4.c +++ b/cmd/ext4.c @@ -48,6 +48,18 @@ int do_ext4_size(cmd_tbl_t *cmdtp, int flag, int argc, return do_size(cmdtp, flag, argc, argv, FS_TYPE_EXT); }
+int do_ext4_file_exists(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + ret = do_file_exists(cmdtp, flag, argc, argv, FS_TYPE_EXT); + + if (ret == 0) return 1; + if (ret == 1) return 0; + return ret; +} + int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { @@ -92,3 +104,9 @@ U_BOOT_CMD(ext4load, 7, 0, do_ext4_load, "<interface> [<dev[:part]> [addr [filename [bytes [pos]]]]]\n" " - load binary file 'filename' from 'dev' on 'interface'\n" " to address 'addr' from ext4 filesystem"); + +U_BOOT_CMD(ext4exist, 4, 0, do_ext4_file_exists, + "check if a file exists", + "<interface> <dev[:part]> <filename>\n" + " - Check if file 'filename' from 'dev' on 'interface'\n" + " exists and return true/false (for scripting.)");
--- a/cmd/fat.c +++ b/cmd/fat.c @@ -19,6 +19,23 @@ #include <fat.h> #include <fs.h>
+int do_fat_file_exists(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int ret; + + ret= do_file_exists(cmdtp, flag, argc, argv, FS_TYPE_FAT); + + if (ret == 0) return 1; + if (ret == 1) return 0; + return ret; +} + +U_BOOT_CMD(fatexist, 4, 0, do_fat_file_exists, + "check if a file exists", + "<interface> <dev[:part]> <filename>\n" + " - Check if file 'filename' from 'dev' on 'interface'\n" + " exists and return true/false (for scripting.)"); + int do_fat_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { return do_size(cmdtp, flag, argc, argv, FS_TYPE_FAT);
--- a/cmd/ubifs.c +++ b/cmd/ubifs.c @@ -98,6 +98,7 @@ static int do_ubifs_ls(cmd_tbl_t *cmdtp, int flag, int argc, return ret; }
+ static int do_ubifs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -137,6 +138,45 @@ static int do_ubifs_load(cmd_tbl_t *cmdtp, int flag, int argc, return ret; }
+static int do_ubifs_file_exists(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int ret; + + if (!ubifs_mounted) { + printf("UBIFS not mounted, use ubifsmount to mount volume first!\n"); + return -2; + } + + if (argc < 2) + return CMD_RET_USAGE; + + if (ret == 0) return 1; + if (ret == 1) return 0; + return ret; +} + +static int do_ubifs_size(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + loff_t size; + + if (!ubifs_mounted) { + printf("UBIFS not mounted, use ubifsmount to mount volume first!\n"); + return CMD_RET_FAILURE; + } + + if (argc < 2) + return CMD_RET_USAGE; + + if (ubifs_size(argv[1], &size) < 0) + return CMD_RET_FAILURE; + + setenv_hex("filesize", size); + + return 0; +} + U_BOOT_CMD( ubifsmount, 2, 0, do_ubifs_mount, "mount UBIFS volume", @@ -158,6 +198,22 @@ U_BOOT_CMD( );
U_BOOT_CMD( + ubifsexist, 2, 0, do_ubifs_file_exists, + "check if a file exists", + "<filename>\n" + " - Check if file 'filename' exists and\n" + " return true/false (for scripting.)" +); + +U_BOOT_CMD( + ubifssize, 2, 0, do_ubifs_size, + "determine a file's size", + "<filename>\n" + " - Find file 'filename'\n" + " and determine its size." +); + +U_BOOT_CMD( ubifsload, 4, 0, do_ubifs_load, "load file from an UBIFS filesystem", "<addr> <filename> [bytes]\n"
--- ****************************************************************** * KSI@home KOI8 Net < > The impossible we do immediately. * * Las Vegas NV, USA < > Miracles require 24-hour notice. * ******************************************************************

On Wed, Oct 05, 2016 at 12:38:01PM -0700, Sergey Kubushyn wrote:
This adds "file exists" commands to generic FS as well as to FAT, EXT4, and UBIFS. Also adds "file size" command to UBIFS.
The return value for "file exists" commands is REVERSED i.e. they return 1 if file exists and 0 otherwise. This is a deliberate decision because those commands are supposed to be used almost exclusively in scripts and TRUE value is _not_ zero while FALSE is zero.
As of now the only way to check for a file existence is to attempt a read on that file (aka load.) That works but it makes an unnecessary read, overwrites memory at destination address if file not a zero length one, and outputs unnecessary messages to the console in any case.
Checking file existence in scripts is a valuable feature that allows the higher level software (e.g. Linux) to interact with U-Boot by creating some semaphore files and rebooting. We do use it quite extensively for system setup at manufacturing time and for other purposes (e.g. our Android "recovery" is implemented this way.)
Signed-off-by: Sergey Kubushyn ksi@koi8.net
Can you please do this in at least two patches? file size to ubi should be its own patch. Also:
+int do_ext4_file_exists(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
+{
- int ret;
- ret = do_file_exists(cmdtp, flag, argc, argv, FS_TYPE_EXT);
- if (ret == 0) return 1;
- if (ret == 1) return 0;
- return ret;
+}
I can only assume this hasn't been compile tested in a while, and you should simplify the code into a single if/else and a comment on what we want/mean. Thanks!

On Sat, 8 Oct 2016, Tom Rini wrote:
On Wed, Oct 05, 2016 at 12:38:01PM -0700, Sergey Kubushyn wrote:
This adds "file exists" commands to generic FS as well as to FAT, EXT4, and UBIFS. Also adds "file size" command to UBIFS.
The return value for "file exists" commands is REVERSED i.e. they return 1 if file exists and 0 otherwise. This is a deliberate decision because those commands are supposed to be used almost exclusively in scripts and TRUE value is _not_ zero while FALSE is zero.
As of now the only way to check for a file existence is to attempt a read on that file (aka load.) That works but it makes an unnecessary read, overwrites memory at destination address if file not a zero length one, and outputs unnecessary messages to the console in any case.
Checking file existence in scripts is a valuable feature that allows the higher level software (e.g. Linux) to interact with U-Boot by creating some semaphore files and rebooting. We do use it quite extensively for system setup at manufacturing time and for other purposes (e.g. our Android "recovery" is implemented this way.)
Signed-off-by: Sergey Kubushyn ksi@koi8.net
Can you please do this in at least two patches? file size to ubi should be its own patch. Also:
Sure, will do later today.
+int do_ext4_file_exists(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
+{
- int ret;
- ret = do_file_exists(cmdtp, flag, argc, argv, FS_TYPE_EXT);
- if (ret == 0) return 1;
- if (ret == 1) return 0;
- return ret;
+}
I can only assume this hasn't been compile tested in a while, and you should simplify the code into a single if/else and a comment on what we want/mean. Thanks!
The problem is do_file_exists() can return not just 0 if file exists or 1 if it doesn't but also a negative value for "I don't know" i.e. when e.g. FS mount failed.
I don't know if those return codes are somehow processed further up (too much time to dig everything to the bare metal) so I decided to return that value as-is if it happened. Sure it could be done like e.g.
return (ret == 0);
even without any if-elses and it is probably the proper way to do it but I fell victim of perfectionism :))
Will re-do it with the above construction and split in 2 parts. Will also send it with git send-email so it won't end up garbled.
--- ****************************************************************** * KSI@home KOI8 Net < > The impossible we do immediately. * * Las Vegas NV, USA < > Miracles require 24-hour notice. * ******************************************************************

On Sat, 8 Oct 2016, Sergey Kubushyn wrote:
On Sat, 8 Oct 2016, Tom Rini wrote:
On Wed, Oct 05, 2016 at 12:38:01PM -0700, Sergey Kubushyn wrote:
This adds "file exists" commands to generic FS as well as to FAT, EXT4, and UBIFS. Also adds "file size" command to UBIFS.
The return value for "file exists" commands is REVERSED i.e. they return 1 if file exists and 0 otherwise. This is a deliberate decision because those commands are supposed to be used almost exclusively in scripts and TRUE value is _not_ zero while FALSE is zero.
As of now the only way to check for a file existence is to attempt a read on that file (aka load.) That works but it makes an unnecessary read, overwrites memory at destination address if file not a zero length one, and outputs unnecessary messages to the console in any case.
Checking file existence in scripts is a valuable feature that allows the higher level software (e.g. Linux) to interact with U-Boot by creating some semaphore files and rebooting. We do use it quite extensively for system setup at manufacturing time and for other purposes (e.g. our Android "recovery" is implemented this way.)
Signed-off-by: Sergey Kubushyn ksi@koi8.net
Can you please do this in at least two patches? file size to ubi should be its own patch. Also:
Sure, will do later today.
+int do_ext4_file_exists(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
+{
- int ret;
- ret = do_file_exists(cmdtp, flag, argc, argv, FS_TYPE_EXT);
- if (ret == 0) return 1;
- if (ret == 1) return 0;
- return ret;
+}
I can only assume this hasn't been compile tested in a while, and you should simplify the code into a single if/else and a comment on what we want/mean. Thanks!
The problem is do_file_exists() can return not just 0 if file exists or 1 if it doesn't but also a negative value for "I don't know" i.e. when e.g. FS mount failed.
I don't know if those return codes are somehow processed further up (too much time to dig everything to the bare metal) so I decided to return that value as-is if it happened. Sure it could be done like e.g.
return (ret == 0);
even without any if-elses and it is probably the proper way to do it but I fell victim of perfectionism :))
Will re-do it with the above construction and split in 2 parts. Will also send it with git send-email so it won't end up garbled.
OK, please disregard this patch altogether. I somehow missed "test -e" command that has been implemented something like 2 years ago and that command makes this entire patch unnecessary.
I will rewrite my scripts with "test -e" before submitting new boards.
--- ****************************************************************** * KSI@home KOI8 Net < > The impossible we do immediately. * * Las Vegas NV, USA < > Miracles require 24-hour notice. * ******************************************************************
participants (2)
-
Sergey Kubushyn
-
Tom Rini