]> git.proxmox.com Git - grub2.git/commitdiff
2009-07-05 Bean <bean123ch@gmail.com>
authorbean <bean@localhost>
Sun, 5 Jul 2009 09:59:27 +0000 (09:59 +0000)
committerbean <bean@localhost>
Sun, 5 Jul 2009 09:59:27 +0000 (09:59 +0000)
* conf/common.rmk (lua_mode_SOURCES): Add script/lua/lstrlib.c.

* script/lua/grub_lib.c (grub_lua_run): Check input parameter.
(grub_lua_getenv): Likewise.
(grub_lua_setenv): Likewise.
(save_errno): New function.
(push_result): Likewise.
(grub_lua_enum_device): Likewise.
(grub_lua_enum_file): Likewise.
(grub_lua_file_open): Likewise.
(grub_lua_file_close): Likewise.
(grub_lua_file_seek): Likewise.
(grub_lua_file_read): Likewise.
(grub_lua_file_getline): Likewise.
(grub_lua_file_getsize): Likewise.
(grub_lua_file_getpos): Likewise.
(grub_lua_file_eof): Likewise.
(grub_lua_file_exist): Likewise.
(grub_lua_add_menu): Likewise.

* script/lua/grub_lua.h (isupper): New inline function.
(islower): Likewise.
(ispunct): Likewise.
(isxdigit): Likewise.
(strcspn): Change to normal function.
(strpbkr): New function declaration.
(memchr): Likewise.

* script/lua/grub_main.c (scan_str): New function.
(strcspn): Likewise.
(strpbrk): Likewise.
(memchr): Likewise.

* script/lua/linit.c (lualibs): Enable the string library.

* util/osdetect.lua: New file.

ChangeLog
conf/common.rmk
script/lua/grub_lib.c
script/lua/grub_lua.h
script/lua/grub_main.c
script/lua/linit.c
util/osdetect.lua [new file with mode: 0644]

index b7fb17535179c0dff1ae7912f39179ded49d2517..d081eccd02a9cb30d8061c44fbc223cb96566416 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2009-07-05  Bean  <bean123ch@gmail.com>
+
+       * conf/common.rmk (lua_mode_SOURCES): Add script/lua/lstrlib.c.
+
+       * script/lua/grub_lib.c (grub_lua_run): Check input parameter.
+       (grub_lua_getenv): Likewise.
+       (grub_lua_setenv): Likewise.
+       (save_errno): New function.
+       (push_result): Likewise.
+       (grub_lua_enum_device): Likewise.
+       (grub_lua_enum_file): Likewise.
+       (grub_lua_file_open): Likewise.
+       (grub_lua_file_close): Likewise.
+       (grub_lua_file_seek): Likewise.
+       (grub_lua_file_read): Likewise.
+       (grub_lua_file_getline): Likewise.
+       (grub_lua_file_getsize): Likewise.
+       (grub_lua_file_getpos): Likewise.
+       (grub_lua_file_eof): Likewise.
+       (grub_lua_file_exist): Likewise.
+       (grub_lua_add_menu): Likewise.
+
+       * script/lua/grub_lua.h (isupper): New inline function.
+       (islower): Likewise.
+       (ispunct): Likewise.
+       (isxdigit): Likewise.
+       (strcspn): Change to normal function.
+       (strpbkr): New function declaration.
+       (memchr): Likewise.
+
+       * script/lua/grub_main.c (scan_str): New function.
+       (strcspn): Likewise.
+       (strpbrk): Likewise.
+       (memchr): Likewise.
+
+       * script/lua/linit.c (lualibs): Enable the string library.
+
+       * util/osdetect.lua: New file.
+
 2009-07-04  Robert Millan  <rmh.grub@aybabtu.com>
 
        * include/grub/i386/linux.h (struct linux_kernel_params): Add
index 9cd4b93a4ea8d4684ae614dff7c373d627be29e9..07ff04e4da04fa9918b0b4eba53036150b883b0b 100644 (file)
@@ -519,15 +519,14 @@ lua_mod_SOURCES = script/lua/lapi.c script/lua/lcode.c script/lua/ldebug.c \
        script/lua/lstate.c script/lua/lstring.c script/lua/ltable.c \
        script/lua/ltm.c script/lua/lundump.c script/lua/lvm.c \
        script/lua/lzio.c script/lua/lauxlib.c script/lua/lbaselib.c \
-       script/lua/linit.c script/lua/ltablib.c \
+       script/lua/linit.c script/lua/ltablib.c script/lua/lstrlib.c \
        script/lua/grub_main.c script/lua/grub_lib.c
 lua_mod_CFLAGS = $(COMMON_CFLAGS)
 lua_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # Extra libraries for lua
 # script/lua/lmathlib.c script/lua/loslib.c script/lua/liolib.c
-# script/lua/lstrlib.c script/lua/ldblib.c script/lua/ltablib.c
-# script/lua/loadlib.c
+# script/lua/ldblib.c script/lua/loadlib.c
 
 # Common Video Subsystem specific modules.
 pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod  \
index 0295f0dccdbe298d96660b3d3e73e5f905ce4d59..d26f19337e6ad65e2c80addd928a30866af41f5c 100644 (file)
 #include <grub/env.h>
 #include <grub/parser.h>
 #include <grub/command.h>
+#include <grub/normal.h>
+#include <grub/file.h>
+#include <grub/device.h>
+
+static int
+save_errno (lua_State *state)
+{
+  int saved_errno;
+
+  saved_errno = grub_errno;
+  grub_errno = 0;
+
+  lua_pushinteger (state, saved_errno);
+  lua_setfield (state, LUA_GLOBALSINDEX, "grub_errno");
+
+  if (saved_errno)
+    lua_pushstring (state, grub_errmsg);
+  else
+    lua_pushnil (state);
+
+  lua_setfield (state, LUA_GLOBALSINDEX, "grub_errmsg");
+
+  return saved_errno;
+}
+
+static int
+push_result (lua_State *state)
+{
+  lua_pushinteger (state, save_errno (state));
+  return 1;
+}
 
 static int
 grub_lua_run (lua_State *state)
 {
   int n;
   char **args;
-  grub_err_t result;
-
-  if (! lua_gettop(state))
-    return 0;
+  const char *s;
 
-  if ((! grub_parser_split_cmdline (lua_tostring (state, 1), 0, &n, &args))
+  s = luaL_checkstring (state, 1);
+  if ((! grub_parser_split_cmdline (s, 0, &n, &args))
       && (n >= 0))
     {
       grub_command_t cmd;
@@ -50,15 +79,7 @@ grub_lua_run (lua_State *state)
       grub_free (args);
     }
 
-  result = grub_errno;
-  grub_errno = 0;
-
-  lua_pushinteger(state, result);
-
-  if (result)
-    lua_pushstring (state, grub_errmsg);
-
-  return (result) ? 2 : 1;
+  return push_result (state);
 }
 
 static int
@@ -66,12 +87,12 @@ grub_lua_getenv (lua_State *state)
 {
   int n, i;
 
-  n = lua_gettop(state);
+  n = lua_gettop (state);
   for (i = 1; i <= n; i++)
     {
       const char *name, *value;
 
-      name = lua_tostring (state, i);
+      name = luaL_checkstring (state, i);
       value = grub_env_get (name);
       if (value)
        lua_pushstring (state, value);
@@ -87,11 +108,8 @@ grub_lua_setenv (lua_State *state)
 {
   const char *name, *value;
 
-  if (lua_gettop(state) != 2)
-    return 0;
-
-  name = lua_tostring (state, 1);
-  value = lua_tostring (state, 2);
+  name = luaL_checkstring (state, 1);
+  value = luaL_checkstring (state, 2);
 
   if (name[0])
     grub_env_set (name, value);
@@ -99,10 +117,322 @@ grub_lua_setenv (lua_State *state)
   return 0;
 }
 
+static int
+grub_lua_enum_device (lua_State *state)
+{
+  auto int enum_device (const char *name);
+  int enum_device (const char *name)
+  {
+    int result;
+    grub_device_t dev;
+
+    result = 0;
+    dev = grub_device_open (name);
+    if (dev)
+      {
+       grub_fs_t fs;
+
+       fs = grub_fs_probe (dev);
+       if (fs)
+         {
+           lua_pushvalue (state, 1);
+           lua_pushstring (state, name);
+           lua_pushstring (state, fs->name);
+           if (! fs->uuid)
+             lua_pushnil (state);
+           else
+             {
+               int err;
+               char *uuid;
+
+               err = fs->uuid (dev, &uuid);
+               if (err)
+                 {
+                   grub_errno = 0;
+                   lua_pushnil (state);
+                 }
+               else
+                 {
+                   lua_pushstring (state, uuid);
+                   grub_free (uuid);
+                 }
+             }
+
+           lua_call (state, 3, 1);
+           result = lua_tointeger (state, -1);
+           lua_pop (state, 1);
+         }
+       else
+         grub_errno = 0;
+       grub_device_close (dev);
+      }
+    else
+      grub_errno = 0;
+
+    return result;
+  }
+
+  luaL_checktype (state, 1, LUA_TFUNCTION);
+  grub_device_iterate (enum_device);
+  return push_result (state);
+}
+
+static int
+grub_lua_enum_file (lua_State *state)
+{
+  char *device_name;
+  const char *arg;
+  grub_device_t dev;
+
+  auto int enum_file (const char *name, const struct grub_dirhook_info *info);
+  int enum_file (const char *name, const struct grub_dirhook_info *info)
+  {
+    int result;
+
+    lua_pushvalue (state, 1);
+    lua_pushstring (state, name);
+    lua_pushinteger (state, info->dir != 0);
+    lua_call (state, 2, 1);
+    result = lua_tointeger (state, -1);
+    lua_pop (state, 1);
+
+    return result;
+  }
+
+  luaL_checktype (state, 1, LUA_TFUNCTION);
+  arg = luaL_checkstring (state, 2);
+  device_name = grub_file_get_device_name (arg);
+  dev = grub_device_open (device_name);
+  if (dev)
+    {
+      grub_fs_t fs;
+      const char *path;
+
+      fs = grub_fs_probe (dev);
+      path = grub_strchr (arg, ')');
+      if (! path)
+       path = arg;
+      else
+       path++;
+
+      if (fs)
+       {
+         (fs->dir) (dev, path, enum_file);
+       }
+
+      grub_device_close (dev);
+    }
+
+  grub_free (device_name);
+
+  return push_result (state);
+}
+
+static int
+grub_lua_file_open (lua_State *state)
+{
+  grub_file_t file;
+  const char *name;
+
+  name = luaL_checkstring (state, 1);
+  file = grub_file_open (name);
+  save_errno (state);
+
+  if (! file)
+    return 0;
+
+  lua_pushlightuserdata (state, file);
+  return 1;
+}
+
+static int
+grub_lua_file_close (lua_State *state)
+{
+  grub_file_t file;
+
+  luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+  file = lua_touserdata (state, 1);
+  grub_file_close (file);
+
+  return push_result (state);
+}
+
+static int
+grub_lua_file_seek (lua_State *state)
+{
+  grub_file_t file;
+  grub_off_t offset;
+
+  luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+  file = lua_touserdata (state, 1);
+  offset = luaL_checkinteger (state, 2);
+
+  offset = grub_file_seek (file, offset);
+  save_errno (state);
+
+  lua_pushinteger (state, offset);
+  return 1;
+}
+
+static int
+grub_lua_file_read (lua_State *state)
+{
+  grub_file_t file;
+  luaL_Buffer b;
+  int n;
+
+  luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+  file = lua_touserdata (state, 1);
+  n = luaL_checkinteger (state, 2);
+
+  luaL_buffinit (state, &b);
+  while (n)
+    {
+      char *p;
+      int nr;
+
+      nr = (n > LUAL_BUFFERSIZE) ? LUAL_BUFFERSIZE : n;
+      p = luaL_prepbuffer (&b);
+
+      nr = grub_file_read (file, p, nr);
+      if (nr <= 0)
+       break;
+
+      luaL_addsize (&b, nr);
+      n -= nr;
+    }
+
+  save_errno (state);
+  luaL_pushresult (&b);
+  return 1;
+}
+
+static int
+grub_lua_file_getline (lua_State *state)
+{
+  grub_file_t file;
+  char *line;
+
+  luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+  file = lua_touserdata (state, 1);
+
+  line = grub_file_getline (file);
+  save_errno (state);
+
+  if (! line)
+    return 0;
+
+  lua_pushstring (state, line);
+  grub_free (line);
+  return 1;
+}
+
+static int
+grub_lua_file_getsize (lua_State *state)
+{
+  grub_file_t file;
+
+  luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+  file = lua_touserdata (state, 1);
+
+  lua_pushinteger (state, file->size);
+  return 1;
+}
+
+static int
+grub_lua_file_getpos (lua_State *state)
+{
+  grub_file_t file;
+
+  luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+  file = lua_touserdata (state, 1);
+
+  lua_pushinteger (state, file->offset);
+  return 1;
+}
+
+static int
+grub_lua_file_eof (lua_State *state)
+{
+  grub_file_t file;
+
+  luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
+  file = lua_touserdata (state, 1);
+
+  lua_pushboolean (state, file->offset >= file->size);
+  return 1;
+}
+
+static int
+grub_lua_file_exist (lua_State *state)
+{
+  grub_file_t file;
+  const char *name;
+  int result;
+
+  result = 0;
+  name = luaL_checkstring (state, 1);
+  file = grub_file_open (name);
+  if (file)
+    {
+      result++;
+      grub_file_close (file);
+    }
+  else
+    grub_errno = 0;
+
+  lua_pushboolean (state, result);
+  return 1;
+}
+
+static int
+grub_lua_add_menu (lua_State *state)
+{
+  int n;
+  const char *source;
+
+  source = luaL_checklstring (state, 1, 0);
+  n = lua_gettop (state) - 1;
+  if (n > 0)
+    {
+      const char *args[sizeof (char *) * n];
+      char *p;
+      int i;
+
+      for (i = 0; i < n; i++)
+       args[i] = luaL_checkstring (state, 2 + i);
+
+      p = grub_strdup (source);
+      if (! p)
+       return push_result (state);
+
+      grub_normal_add_menu_entry (n, args, p);
+    }
+  else
+    {
+      lua_pushstring (state, "not enough parameter");
+      lua_error (state);
+    }
+
+  return push_result (state);
+}
+
 luaL_Reg grub_lua_lib[] =
   {
     {"run", grub_lua_run},
     {"getenv", grub_lua_getenv},
     {"setenv", grub_lua_setenv},
+    {"enum_device", grub_lua_enum_device},
+    {"enum_file", grub_lua_enum_file},
+    {"file_open", grub_lua_file_open},
+    {"file_close", grub_lua_file_close},
+    {"file_seek", grub_lua_file_seek},
+    {"file_read", grub_lua_file_read},
+    {"file_getline", grub_lua_file_getline},
+    {"file_getsize", grub_lua_file_getsize},
+    {"file_getpos", grub_lua_file_getpos},
+    {"file_eof", grub_lua_file_eof},
+    {"file_exist", grub_lua_file_exist},
+    {"add_menu", grub_lua_add_menu},
     {0, 0}
   };
index a181b52f1fe3a641e3bfa574c63c8dbcfc056405..d5181f147d747bb0a4d628afdebd4b1f152ed0bc 100644 (file)
@@ -77,26 +77,28 @@ iscntrl (int c)
 }
 
 static inline int
-strcspn(const char *s1, const char *s2)
+isupper (int c)
 {
-  int size = 0;
-
-  while (*s1)
-    {
-      const char *p = s2;
+  return ((c >= 'A') && (c <= 'Z'));
+}
 
-      while (*p)
-       {
-         if (*s1 == *p)
-           return size;
-         p++;
-       }
+static inline int
+islower (int c)
+{
+  return ((c >= 'a') && (c <= 'z'));
+}
 
-      s1++;
-      size++;
-    }
+static inline int
+ispunct (int c)
+{
+  return ((! isspace (c)) && (! isalnum (c)));
+}
 
-  return size;
+static inline int
+isxdigit (int c)
+{
+  return (isdigit (c) || ((c >= 'a') && (c <= 'f')) ||
+         ((c >= 'A') && (c <= 'F')));
 }
 
 static inline int
@@ -105,4 +107,8 @@ abs (int c)
   return (c >= 0) ? : -c;
 }
 
+int strcspn (const char *s1, const char *s2);
+char *strpbrk (const char *s1, const char *s2);
+void *memchr (const void *s, int c, size_t n);
+
 #endif
index 03f890a9a4b9aee69116672a34c63f15436b975a..b39141f75d8e6ae1dd5151d8cddb93f415ebebfe 100644 (file)
 #include <grub/dl.h>
 #include <grub/parser.h>
 
+static const char *
+scan_str (const char *s1, const char *s2)
+{
+  while (*s1)
+    {
+      const char *p = s2;
+
+      while (*p)
+       {
+         if (*s1 == *p)
+           return s1;
+         p++;
+       }
+
+      s1++;
+    }
+
+  return s1;
+}
+
+int
+strcspn (const char *s1, const char *s2)
+{
+  const char *r;
+
+  r = scan_str (s1, s2);
+  return r - s1;
+}
+
+char *
+strpbrk (const char *s1, const char *s2)
+{
+  const char *r;
+
+  r = scan_str (s1, s2);
+  return (*r) ? (char *) r : 0;
+}
+
+void *
+memchr (const void *s, int c, size_t n)
+{
+  const unsigned char *p = s;
+
+  while (n)
+    {
+      if (*p == c)
+       return (void *) p;
+
+      n--;
+      p++;
+    }
+
+  return 0;
+}
+
 static lua_State *state;
 
 /* Call `grub_error' to report a Lua error.  The error message string must be
index d034a2fbeda7669743b26548fbedcac1e496708e..f920a0b081f508d86e8f427b8dc238225c4f98e0 100644 (file)
@@ -20,7 +20,7 @@ static const luaL_Reg lualibs[] = {
   {LUA_TABLIBNAME, luaopen_table},
 //  {LUA_IOLIBNAME, luaopen_io},
 //  {LUA_OSLIBNAME, luaopen_os},
-//  {LUA_STRLIBNAME, luaopen_string},
+  {LUA_STRLIBNAME, luaopen_string},
 //  {LUA_MATHLIBNAME, luaopen_math},
 //  {LUA_DBLIBNAME, luaopen_debug},
   {NULL, NULL}
diff --git a/util/osdetect.lua b/util/osdetect.lua
new file mode 100644 (file)
index 0000000..c57d612
--- /dev/null
@@ -0,0 +1,111 @@
+#!lua
+--
+-- Copyright (C) 2009  Free Software Foundation, Inc.
+--
+-- GRUB is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- GRUB is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+--
+
+function enum_device (device, fs, uuid)
+  local root
+  local title
+  local source
+  local kernels = {}
+  local kernel_num = 0
+
+  local function enum_file (name)
+    local version
+
+    version = string.match (name, "vmlinuz%-(.*)")
+    if (version ~= nil) then
+      table.insert (kernels, version)
+      kernel_num = kernel_num + 1
+    end
+  end
+
+  local function sort_kernel (first, second)
+    local a1, a2, a3, a4, b1, b2, b3, b4
+
+    a1, a2, a3, a4 = string.match (first, "(%d+)%.?(%d*).?(%d*)%-?(%d*)")
+    b1, b2, b3, b4 = string.match (second, "(%d+)%.?(%d*).?(%d*)%-?(%d*)")
+    return (a1 > b1) or (a2 > b2) or (a3 > b3) or (a4 < b4);
+  end
+
+  root = "(" .. device .. ")/"
+  source = "root (" .. device .. ")\nchainloader +1"
+  title = nil
+  if (grub.file_exist (root .. "bootmgr") and
+      grub.file_exist (root .. "boot/bcd")) then
+    title = "Windows Vista bootmgr"
+  elseif (grub.file_exist (root .. "ntldr") and
+         grub.file_exist (root .. "ntdetect.com") and
+         grub.file_exist (root .. "boot.ini")) then
+    title = "Windows NT/2000/XP loader"
+  elseif (grub.file_exist (root .. "windows/win.com")) then
+    title = "Windows 98/ME"
+  elseif (grub.file_exist (root .. "io.sys") and
+         grub.file_exist (root .. "command.com")) then
+    title = "MS-DOS"
+  elseif (grub.file_exist (root .. "kernel.sys")) then
+    title = "FreeDOS"
+  elseif (grub.file_exist (root .. "boot/loader") and
+         grub.file_exist (root .. "boot/devices.hints")) then
+    source = "root (" .. device .. ")\nfreebsd /boot/loader" ..
+      "\nfreebsd_loadenv /boot/device.hints"
+    title = "FreeBSD"
+  else
+    grub.enum_file (enum_file, root .. "boot")
+    if kernel_num ~= 0 then
+      table.sort (kernels, sort_kernel)
+      for i = 1, kernel_num do
+       local initrd
+
+       title = "Linux " .. kernels[i]
+       source = "root (" .. device ..
+         ")\nlinux /boot/vmlinuz-" .. kernels[i] ..
+         " root=UUID=" .. uuid .. " ro"
+
+       if grub.file_exist (root .. "boot/initrd-" ..
+                           kernels[i] .. ".img") then
+         initrd = "\ninitrd /boot/initrd-" .. kernels[i] .. ".img"
+       elseif grub.file_exist (root .. "boot/initrd.img-" .. kernels[i]) then
+         initrd = "\ninitrd /boot/initrd.img-" .. kernels[i]
+       elseif grub.file_exist (root .. "boot/initrd-" .. kernels[i]) then
+         initrd = "\ninitrd /boot/initrd-" .. kernels[i]
+       else
+         initrd = ""
+       end
+
+       grub.add_menu (source .. initrd, title)
+       grub.add_menu (source .. " single" .. initrd,
+                      title .. " (single-user mode)")
+      end
+      return 0
+    end
+  end
+
+  if title == nil then
+    local partition = string.match (device, ".*,(%d+)")
+
+    if (partition ~= nil) and (tonumber (partition) > 4) then
+      return 0
+    end
+
+    title = "Other OS"
+  end
+
+  grub.add_menu (source, title)
+  return 0
+end
+
+grub.enum_device (enum_device)