[syslinux:elflink] ldlinux: Automatically lookup file extension

syslinux-bot for Matt Fleming matt.fleming at intel.com
Tue Apr 17 11:24:07 PDT 2012


Commit-ID:  42c79110981c7117d6f337305c90dfdc6fb8d645
Gitweb:     http://www.syslinux.org/commit/42c79110981c7117d6f337305c90dfdc6fb8d645
Author:     Matt Fleming <matt.fleming at intel.com>
AuthorDate: Fri, 30 Mar 2012 10:57:22 +0100
Committer:  Matt Fleming <matt.fleming at intel.com>
CommitDate: Mon, 16 Apr 2012 15:23:46 +0100

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 at zytor.com>
Signed-off-by: Matt Fleming <matt.fleming at intel.com>

---
 com32/elflink/ldlinux/ldlinux.c |  157 +++++++++++++++++++++++++++++++++------
 1 files changed, 133 insertions(+), 24 deletions(-)

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 <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:


More information about the Syslinux-commits mailing list