aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2012-03-30 10:57:22 +0100
committerMatt Fleming <matt.fleming@intel.com>2012-04-16 15:23:46 +0100
commit42c79110981c7117d6f337305c90dfdc6fb8d645 (patch)
tree8710c652fb96610cd0f64da895ba0baef06c88a7
parent66955aa0dcc3c6c28788a49764342580870009b8 (diff)
downloadsyslinux-42c79110981c7117d6f337305c90dfdc6fb8d645.tar.gz
syslinux-42c79110981c7117d6f337305c90dfdc6fb8d645.tar.xz
syslinux-42c79110981c7117d6f337305c90dfdc6fb8d645.zip
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 <hpa@zytor.com> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r--com32/elflink/ldlinux/ldlinux.c157
1 files changed, 133 insertions, 24 deletions
diff --git a/com32/elflink/ldlinux/ldlinux.c b/com32/elflink/ldlinux/ldlinux.c
index 6c306ad5..fcb30701 100644
--- a/com32/elflink/ldlinux/ldlinux.c
+++ b/com32/elflink/ldlinux/ldlinux.c
@@ -1,7 +1,9 @@
#include <linux/list.h>
#include <sys/times.h>
+#include <fcntl.h>
#include <stdbool.h>
#include <core.h>
+#include <fs.h>
#include "cli.h"
#include "console.h"
#include "com32.h"
@@ -11,40 +13,119 @@
#include <sys/module.h>
-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: