From: Matt Fleming Date: Fri, 30 Mar 2012 09:57:22 +0000 (+0100) Subject: ldlinux: Automatically lookup file extension X-Git-Tag: syslinux-5.00-pre2~27 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=42c79110981c7117d6f337305c90dfdc6fb8d645;p=platform%2Fupstream%2Fsyslinux.git ldlinux: Automatically lookup file extension The old kernel loader would automatically calculate valid file extensions if one wasn't supplied by the user. For example, if a user types 'ls' we want to run the ls.c32 module. Add support for this to the new code in ldlinux. Reported-by: H. Peter Anvin Signed-off-by: Matt Fleming --- diff --git a/com32/elflink/ldlinux/ldlinux.c b/com32/elflink/ldlinux/ldlinux.c index 6c306ad..fcb3070 100644 --- a/com32/elflink/ldlinux/ldlinux.c +++ b/com32/elflink/ldlinux/ldlinux.c @@ -1,7 +1,9 @@ #include #include +#include #include #include +#include #include "cli.h" #include "console.h" #include "com32.h" @@ -11,40 +13,119 @@ #include -static enum kernel_type parse_kernel_type(char *kernel) -{ +struct file_ext { + const char *name; enum kernel_type type; +}; + +static const struct file_ext file_extensions[] = { + { ".com", KT_COMBOOT }, + { ".cbt", KT_COMBOOT }, + { ".c32", KT_COM32 }, + { ".img", KT_FDIMAGE }, + { ".bss", KT_BSS }, + { ".bin", KT_BOOT }, + { ".bs", KT_BOOT }, + { ".0", KT_PXE }, + { NULL, KT_NONE }, +}; + +/* + * Return a pointer to one byte after the last character of the + * command. + */ +static inline const char *find_command(const char *str) +{ const char *p; - int len; - /* Find the end of the command */ - p = kernel; + p = str; while (*p && !my_isspace(*p)) p++; + return p; +} +static enum kernel_type parse_kernel_type(char *kernel) +{ + const struct file_ext *ext; + const char *p; + int len; + + /* Find the end of the command */ + p = find_command(kernel); len = p - kernel; - if (!strncmp(kernel + len - 4, ".c32", 4)) { - type = KT_COM32; - } else if (!strncmp(kernel + len - 2, ".0", 2)) { - type = KT_PXE; - } else if (!strncmp(kernel + len - 3, ".bs", 3)) { - type = KT_BOOT; - } else if (!strncmp(kernel + len - 4, ".img", 4)) { - type = KT_FDIMAGE; - } else if (!strncmp(kernel + len - 4, ".bin", 4)) { - type = KT_BOOT; - } else if (!strncmp(kernel + len - 4, ".bss", 4)) { - type = KT_BSS; - } else if (!strncmp(kernel + len - 4, ".com", 4) || - !strncmp(kernel + len - 4, ".cbt", 4)) { - type = KT_COMBOOT; + for (ext = file_extensions; ext->name; ext++) { + int elen = strlen(ext->name); + + if (!strncmp(kernel + len - elen, ext->name, elen)) + return ext->type; } + /* use KT_KERNEL as default */ - else - type = KT_KERNEL; + return KT_KERNEL; +} + +/* + * Returns the kernel name with file extension if one wasn't present. + */ +static const char *get_extension(const char *kernel) +{ + const struct file_ext *ext; + const char *p; + int len; + + /* Find the end of the command */ + p = find_command(kernel); + len = p - kernel; + + for (ext = file_extensions; ext->name; ext++) { + char *str; + int elen = strlen(ext->name); + int fd; + + str = malloc(len + elen + 1); - return type; + strncpy(str, kernel, len); + strncpy(str + len, ext->name, elen); + str[len + elen] = '\0'; + + fd = searchdir(str); + free(str); + + if (fd >= 0) + return ext->name; + } + + return NULL; +} + +static const char *apply_extension(const char *kernel, const char *ext) +{ + const char *p; + char *k; + int len = strlen(kernel); + int elen = strlen(ext); + + k = malloc(len + elen + 1); + if (!k) + return NULL; + + p = find_command(kernel); + + len = p - kernel; + + /* Copy just the kernel name */ + memcpy(k, kernel, len); + + /* Append the extension */ + memcpy(k + len, ext, elen); + + /* Copy the rest of the command line */ + strcpy(k + len + elen, p); + + k[len + elen] = '\0'; + + return k; } /* @@ -54,11 +135,16 @@ static enum kernel_type parse_kernel_type(char *kernel) * the the kernel. If we return the caller should call enter_cmdline() * so that the user can help us out. */ -static void load_kernel(const char *kernel) +static void load_kernel(const char *command_line) { struct menu_entry *me; enum kernel_type type; const char *cmdline; + const char *kernel; + + kernel = strdup(command_line); + if (!kernel) + goto bad_kernel; /* Virtual kernel? */ me = find_label(kernel); @@ -78,7 +164,30 @@ static void load_kernel(const char *kernel) goto bad_implicit; type = parse_kernel_type(kernel); + if (type == KT_KERNEL) { + const char *ext; + + /* + * Automatically lookup the extension if one wasn't + * supplied by the user. + */ + ext = get_extension(kernel); + if (ext) { + const char *k; + + k = apply_extension(kernel, ext); + if (!k) + goto bad_kernel; + + free((void *)kernel); + kernel = k; + + type = parse_kernel_type(kernel); + } + } + execute(kernel, type); + free((void *)kernel); bad_implicit: bad_kernel: