commands/cmp: Only return success when both files have the same contents

This allows the cmp command to be used in GRUB scripts to conditionally
run commands based on whether two files are the same.

The command is now quiet by default and the -v switch can be given to enable
verbose mode, the previous behavior.

Update documentation accordingly.

Suggested-by: Li Gen <ligenlive@gmail.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
Glenn Washburn 2022-12-15 12:13:30 -06:00 committed by Daniel Kiper
parent 004ffa68ae
commit 4ba977777c
2 changed files with 33 additions and 17 deletions

View File

@ -4508,9 +4508,14 @@ on platforms that support CMOS.
@node cmp @node cmp
@subsection cmp @subsection cmp
@deffn Command cmp file1 file2 @deffn Command cmp [@option{-v}] file1 file2
Compare the file @var{file1} with the file @var{file2}. If they differ Compare the file @var{file1} with the file @var{file2}. If they are completely
in size, print the sizes like this: identical, @code{$?} will be set to 0. Otherwise, if the files are not identical,
@code{$?} will be set to a nonzero value.
By default nothing will be output. If the @option{-v} is used, verbose mode is
enabled. In this mode when when the files differ in size, print the sizes like
this:
@example @example
Differ in size: 0x1234 [foo], 0x4321 [bar] Differ in size: 0x1234 [foo], 0x4321 [bar]
@ -4523,7 +4528,6 @@ bytes like this:
Differ at the offset 777: 0xbe [foo], 0xef [bar] Differ at the offset 777: 0xbe [foo], 0xef [bar]
@end example @end example
If they are completely identical, nothing will be printed.
@end deffn @end deffn

View File

@ -22,14 +22,21 @@
#include <grub/file.h> #include <grub/file.h>
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/command.h> #include <grub/command.h>
#include <grub/extcmd.h>
#include <grub/i18n.h> #include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
#define BUFFER_SIZE 512 #define BUFFER_SIZE 512
static const struct grub_arg_option options[] =
{
{0, 'v', 0, N_("Enable verbose output"), 0, 0},
{0, 0, 0, 0, 0, 0}
};
static grub_err_t static grub_err_t
grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), grub_cmd_cmp (grub_extcmd_context_t ctxt,
int argc, char **args) int argc, char **args)
{ {
grub_ssize_t rd1, rd2; grub_ssize_t rd1, rd2;
@ -38,19 +45,20 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
grub_file_t file2 = 0; grub_file_t file2 = 0;
char *buf1 = 0; char *buf1 = 0;
char *buf2 = 0; char *buf2 = 0;
grub_err_t err = GRUB_ERR_TEST_FAILURE;
if (argc != 2) if (argc != 2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0], if (ctxt->state[0].set)
args[1]); grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0], args[1]);
file1 = grub_file_open (args[0], GRUB_FILE_TYPE_CMP); file1 = grub_file_open (args[0], GRUB_FILE_TYPE_CMP);
file2 = grub_file_open (args[1], GRUB_FILE_TYPE_CMP); file2 = grub_file_open (args[1], GRUB_FILE_TYPE_CMP);
if (! file1 || ! file2) if (! file1 || ! file2)
goto cleanup; goto cleanup;
if (grub_file_size (file1) != grub_file_size (file2)) if (ctxt->state[0].set && (grub_file_size (file1) != grub_file_size (file2)))
grub_printf_ (N_("Files differ in size: %llu [%s], %llu [%s]\n"), grub_printf_ (N_("Files differ in size: %llu [%s], %llu [%s]\n"),
(unsigned long long) grub_file_size (file1), args[0], (unsigned long long) grub_file_size (file1), args[0],
(unsigned long long) grub_file_size (file2), args[1]); (unsigned long long) grub_file_size (file2), args[1]);
@ -78,9 +86,10 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
{ {
if (buf1[i] != buf2[i]) if (buf1[i] != buf2[i])
{ {
grub_printf_ (N_("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n"), if (ctxt->state[0].set)
(unsigned long long) (i + pos), buf1[i], grub_printf_ (N_("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n"),
args[0], buf2[i], args[1]); (unsigned long long) (i + pos), buf1[i],
args[0], buf2[i], args[1]);
goto cleanup; goto cleanup;
} }
} }
@ -90,7 +99,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
while (rd2); while (rd2);
/* TRANSLATORS: it's always exactly 2 files. */ /* TRANSLATORS: it's always exactly 2 files. */
grub_printf_ (N_("The files are identical.\n")); if (ctxt->state[0].set)
grub_printf_ (N_("The files are identical.\n"));
err = GRUB_ERR_NONE;
} }
cleanup: cleanup:
@ -102,18 +113,19 @@ cleanup:
if (file2) if (file2)
grub_file_close (file2); grub_file_close (file2);
return grub_errno; return err;
} }
static grub_command_t cmd; static grub_extcmd_t cmd;
GRUB_MOD_INIT(cmp) GRUB_MOD_INIT(cmp)
{ {
cmd = grub_register_command ("cmp", grub_cmd_cmp, cmd = grub_register_extcmd ("cmp", grub_cmd_cmp, 0,
N_("FILE1 FILE2"), N_("Compare two files.")); N_("FILE1 FILE2"), N_("Compare two files."),
options);
} }
GRUB_MOD_FINI(cmp) GRUB_MOD_FINI(cmp)
{ {
grub_unregister_command (cmd); grub_unregister_extcmd (cmd);
} }