This patch corrects a problem with argument processing in the kexec
executable. As it now stands, most arguments that take a value MUST
be specified as
--option=value
instead of the typical alternate specification
--option value
This is due to the argv permuting normally done by getopt_long().
Consider the example
kexec -l kernel-name --append "kernel options" --initrd=path
The getopt_long() loop in main() will reorder this to
kexec
-l
--append
--initrd=path
kernel-name
"kernel options"
Note the append option's value was separated from the option name.
A later getopt_long() loop, e.g., the one in kexec-bzImage.c, will
erroneously use "--initrd=path" as the value for "--append".
The problem cannot be fixed by preventing getopt_long() from permuting
the argv vector, i.e., by setting the first char of the "optstring"
argument to "-" (consider the getopt_long() call in main(), it will
not understand that --append has a value).
An alternate solution would be to build a single unified optstring
for all calls to getopt_long(), but that would add a lot of complexity
to the program, requiring some sort of option registering process,
with the automatic detection of the "kernel" type adding to the
complexity.
Finally, one could decree "ALWAYS concat the value to the option name
with an equal sign," but, well...
So, the chosen solution is simply to hand each getopt_long() loop a
copy of the original argument list so the permuted list is never passed
from one getopt_long() to the next. This is done by making a copy of
the argv vector, i.e., the pointers to the strings, not copies of the
strings themselves. The use of the unpermuted argv vector also required
main() to pass the kernel name itself to my_load(), instead of the
permuted vector index.
--
David N. Lombard
Rossmoor, Orange County, CA
http://www.fourmilab.ch/cgi-bin/uncgi/Earth?imgsize=320&opt=-z&lat=33.8&ns=North&lon=118.08&ew=West&alt=7&img=learth.evif
Patch to correct option passing using either
--option=value
or
--option value
--- ./kexec/kexec.c.orig 2006-01-01 14:49:50.000000000 -0800
+++ ./kexec/kexec.c 2006-01-01 16:26:01.000000000 -0800
@@ -497,10 +497,9 @@ static void update_purgatory(struct kexe
/*
* Load the new kernel
*/
-static int my_load(const char *type, int fileind, int argc, char **argv,
+static int my_load(const char *type, char *kernel, int argc, char **argv,
unsigned long kexec_flags)
{
- char *kernel;
char *kernel_buf;
off_t kernel_size;
int i = 0;
@@ -516,12 +515,6 @@ static int my_load(const char *type, int
info.kexec_flags = kexec_flags;
result = 0;
- if (argc - fileind <= 0) {
- fprintf(stderr, "No kernel specified\n");
- usage();
- return -1;
- }
- kernel = argv[fileind];
/* slurp in the input kernel */
kernel_buf = slurp_decompress_file(kernel, &kernel_size);
#if 0
@@ -708,15 +701,22 @@ int main(int argc, char *argv[])
char *endptr;
int opt;
int result = 0;
- int fileind;
+ char *kernel;
static const struct option options[] = {
KEXEC_OPTIONS
{ 0, 0, 0, 0},
};
static const char short_options[] = KEXEC_OPT_STR;
+ char **targv;
+ size_t largv = (argc + 1)*sizeof( argv );
+
+ targv = malloc( largv );
+ if( !(targv = malloc( largv )) )
+ die( "Unable to malloc %ld bytes\n", largv );
+ (void) memcpy( targv, argv, largv );
opterr = 0; /* Don't complain about unrecognized options here */
- while ((opt = getopt_long(argc, argv, short_options, options, 0)) !=
-1) {
+ while ((opt = getopt_long(argc, targv, short_options, options, 0)) !=
-1) {
switch(opt) {
case OPT_HELP:
usage();
@@ -785,18 +785,25 @@ int main(int argc, char *argv[])
}
}
- fileind = optind;
+ kernel = (argc - optind <= 0) ? NULL : targv[optind];
/* Reset getopt for the next pass; called in other source modules */
opterr = 1;
optind = 1;
- result = arch_process_options(argc, argv);
+ (void) memcpy( targv, argv, largv );
+
+ result = arch_process_options(argc, targv);
if (do_unload) {
result = k_unload(kexec_flags);
}
if (do_load && (result == 0)) {
- result = my_load(type, fileind, argc, argv, kexec_flags);
+ if ( kernel == NULL ) {
+ fprintf(stderr, "No kernel specified\n");
+ usage();
+ return 1;
+ }
+ result = my_load(type, kernel, argc, argv, kexec_flags);
}
if ((result == 0) && do_shutdown) {
result = my_shutdown();
_______________________________________________
fastboot mailing list
[email protected]
https://lists.osdl.org/mailman/listinfo/fastboot