* [PATCH] File access library for lua @ 2009-06-21 11:33 Bean 2009-06-22 0:42 ` Pavel Roskin 0 siblings, 1 reply; 31+ messages in thread From: Bean @ 2009-06-21 11:33 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 1065 bytes --] Hi, I've added a few function in the lua grub library to access files: enum_device - enumerate devices enum_file - enumerate files file_open - open file file_close - close file file_seek - seek file file_read - read n bytes file_getline - read a line file_getsize - get file size file_getpos - get current read position Here is an example: #!lua function enum_device (name) print (name) return 0 end function enum_file (name, is_dir) print (is_dir, name) return 0 end grub.enum_device (enum_device) grub.enum_file ("/boot/grub", enum_file) f = grub.file_open ("/boot/grub/grub.cfg") print (grub.file_getsize (f)) print (grub.file_getline (f)) print (grub.file_getline (f)) print (grub.file_seek (f, 0)) print (grub.file_read (f, 10)) print (grub.file_getpos (f)) grub.file_close (f); And now after file operation, the result is saved in global variable grub_errno and grub_errmsg (lua variable), for example: f = grub.file_open ("/abcde") if (f == nil) then print (grub_errno, grub_errmsg) fi I also enable the string library from lua. -- Bean [-- Attachment #2: lua_file.diff --] [-- Type: text/x-diff, Size: 9256 bytes --] diff --git a/conf/common.rmk b/conf/common.rmk index fbca2e4..dc78df9 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -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 \ diff --git a/script/lua/grub_lib.c b/script/lua/grub_lib.c index 0295f0d..f3c8812 100644 --- a/script/lua/grub_lib.c +++ b/script/lua/grub_lib.c @@ -24,13 +24,43 @@ #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; @@ -50,15 +80,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 @@ -99,10 +121,236 @@ 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; + + lua_pushvalue (state, -1); + lua_pushstring (state, name); + lua_call (state, 1, 1); + result = lua_tointeger (state, -1); + lua_pop (state, 1); + + return result; + } + + if (lua_gettop (state) != 1) + return 0; + + grub_device_iterate (enum_device); + return push_result (state); +} + +static int +grub_lua_enum_file (lua_State *state) +{ + + 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; + } + + if (lua_gettop (state) != 2) + return 0; + else + { + char *device_name, *arg; + grub_device_t dev; + + arg = (char *) lua_tostring (state, 1); + device_name = grub_file_get_device_name (arg); + dev = grub_device_open (device_name); + if (dev) + { + grub_fs_t fs; + 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; + + if (lua_gettop(state) != 1) + return 0; + + name = lua_tostring (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; + + if (lua_gettop(state) != 1) + return 0; + + 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; + + if (lua_gettop(state) != 2) + return 0; + + file = lua_touserdata (state, 1); + offset = lua_tointeger (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; + + if (lua_gettop(state) != 2) + return 0; + + file = lua_touserdata (state, 1); + n = lua_tointeger (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; + + if (lua_gettop(state) != 1) + return 0; + + 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; + + if (lua_gettop(state) != 1) + return 0; + + 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; + + if (lua_gettop(state) != 1) + return 0; + + file = lua_touserdata (state, 1); + + lua_pushinteger (state, file->offset); + return 1; +} + 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}, {0, 0} }; diff --git a/script/lua/grub_lua.h b/script/lua/grub_lua.h index a181b52..d5181f1 100644 --- a/script/lua/grub_lua.h +++ b/script/lua/grub_lua.h @@ -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 diff --git a/script/lua/grub_main.c b/script/lua/grub_main.c index 03f890a..b6d496d 100644 --- a/script/lua/grub_main.c +++ b/script/lua/grub_main.c @@ -24,6 +24,61 @@ #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 diff --git a/script/lua/linit.c b/script/lua/linit.c index d034a2f..f920a0b 100644 --- a/script/lua/linit.c +++ b/script/lua/linit.c @@ -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} ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-21 11:33 [PATCH] File access library for lua Bean @ 2009-06-22 0:42 ` Pavel Roskin 2009-06-22 3:38 ` Bean 0 siblings, 1 reply; 31+ messages in thread From: Pavel Roskin @ 2009-06-22 0:42 UTC (permalink / raw) To: The development of GRUB 2 On Sun, 2009-06-21 at 19:33 +0800, Bean wrote: > I've added a few function in the lua grub library to access files: ... > I also enable the string library from lua. The patch doesn't introduce any compiler warnings, and that's good. It makes lua.mod bigger by about 10%, but it's very little compared to the added functionality. Please don't add trailing whitespace. STGit detects it in two places. There are several cases of missing spaces before parentheses. We probably need NESTED_FUNC_ATTR in the dir definition in struct grub_fs, as it takes two arguments. But is a separate issue. I'm feeling uneasy about having a parser in GRUB that is not used by default, but it's not related to the quality of the patch. -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 0:42 ` Pavel Roskin @ 2009-06-22 3:38 ` Bean 2009-06-22 3:45 ` Pavel Roskin 2009-06-22 9:44 ` Robert Millan 0 siblings, 2 replies; 31+ messages in thread From: Bean @ 2009-06-22 3:38 UTC (permalink / raw) To: The development of GRUB 2 Hi, On Mon, Jun 22, 2009 at 8:42 AM, Pavel Roskin<proski@gnu.org> wrote: > On Sun, 2009-06-21 at 19:33 +0800, Bean wrote: > >> I've added a few function in the lua grub library to access files: > ... >> I also enable the string library from lua. > > The patch doesn't introduce any compiler warnings, and that's good. > > It makes lua.mod bigger by about 10%, but it's very little compared to > the added functionality. This is probably due to the enable of string library, the file access function itself should be quite small. > > Please don't add trailing whitespace. STGit detects it in two places. > > There are several cases of missing spaces before parentheses. > > We probably need NESTED_FUNC_ATTR in the dir definition in struct > grub_fs, as it takes two arguments. But is a separate issue. > > I'm feeling uneasy about having a parser in GRUB that is not used by > default, but it's not related to the quality of the patch. Actually, this is about to change. The file function here can be used in a script osdetect.lua to generate menu items at runtime, and I also plans to integrate lua with menu viewer. > > -- > Regards, > Pavel Roskin > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel > -- Bean ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 3:38 ` Bean @ 2009-06-22 3:45 ` Pavel Roskin 2009-06-22 9:44 ` Robert Millan 1 sibling, 0 replies; 31+ messages in thread From: Pavel Roskin @ 2009-06-22 3:45 UTC (permalink / raw) To: The development of GRUB 2 On Mon, 2009-06-22 at 11:38 +0800, Bean wrote: > Actually, this is about to change. The file function here can be used > in a script osdetect.lua to generate menu items at runtime, and I also > plans to integrate lua with menu viewer. OK, that sounds interesting! -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 3:38 ` Bean 2009-06-22 3:45 ` Pavel Roskin @ 2009-06-22 9:44 ` Robert Millan 2009-06-22 10:26 ` Bean 1 sibling, 1 reply; 31+ messages in thread From: Robert Millan @ 2009-06-22 9:44 UTC (permalink / raw) To: The development of GRUB 2 On Mon, Jun 22, 2009 at 11:38:35AM +0800, Bean wrote: > > > > I'm feeling uneasy about having a parser in GRUB that is not used by > > default, but it's not related to the quality of the patch. > > Actually, this is about to change. I don't mind LUA being supported if it's useful for some users, but I'm not satisfied with ditching GRUB scripting engine with something external. We really should discuss it with Marco or Okuji before changing the default parser to something else. -- Robert Millan The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and how) you may access your data; but nobody's threatening your freedom: we still allow you to remove your data and not access it at all." ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 9:44 ` Robert Millan @ 2009-06-22 10:26 ` Bean 2009-06-22 10:59 ` Robert Millan 0 siblings, 1 reply; 31+ messages in thread From: Bean @ 2009-06-22 10:26 UTC (permalink / raw) To: The development of GRUB 2 On Mon, Jun 22, 2009 at 5:44 PM, Robert Millan<rmh@aybabtu.com> wrote: > On Mon, Jun 22, 2009 at 11:38:35AM +0800, Bean wrote: >> > >> > I'm feeling uneasy about having a parser in GRUB that is not used by >> > default, but it's not related to the quality of the patch. >> >> Actually, this is about to change. > > I don't mind LUA being supported if it's useful for some users, but I'm > not satisfied with ditching GRUB scripting engine with something external. > > We really should discuss it with Marco or Okuji before changing the > default parser to something else. Hi, No need to change the default parser, with the #! syntax, we can call the lua script from main grub.cfg, and the parser will switch back to sh on return, something like this: grub.cfg: source osdetect.lua ... osdetect.lua: #!lua ... > > -- > Robert Millan > > The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and > how) you may access your data; but nobody's threatening your freedom: we > still allow you to remove your data and not access it at all." > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel > -- Bean ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 10:26 ` Bean @ 2009-06-22 10:59 ` Robert Millan 2009-06-22 17:37 ` Bean 0 siblings, 1 reply; 31+ messages in thread From: Robert Millan @ 2009-06-22 10:59 UTC (permalink / raw) To: The development of GRUB 2 On Mon, Jun 22, 2009 at 06:26:02PM +0800, Bean wrote: > On Mon, Jun 22, 2009 at 5:44 PM, Robert Millan<rmh@aybabtu.com> wrote: > > On Mon, Jun 22, 2009 at 11:38:35AM +0800, Bean wrote: > >> > > >> > I'm feeling uneasy about having a parser in GRUB that is not used by > >> > default, but it's not related to the quality of the patch. > >> > >> Actually, this is about to change. > > > > I don't mind LUA being supported if it's useful for some users, but I'm > > not satisfied with ditching GRUB scripting engine with something external. > > > > We really should discuss it with Marco or Okuji before changing the > > default parser to something else. > > Hi, > > No need to change the default parser, with the #! syntax, we can call > the lua script from main grub.cfg, and the parser will switch back to > sh on return, something like this: Ok, that's nice. I was more thinking about our grub.cfg-generation scripts though. I think those should stay with the current parser. -- Robert Millan The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and how) you may access your data; but nobody's threatening your freedom: we still allow you to remove your data and not access it at all." ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 10:59 ` Robert Millan @ 2009-06-22 17:37 ` Bean 2009-06-22 18:31 ` Pavel Roskin 2009-07-31 8:07 ` Marco Gerards 0 siblings, 2 replies; 31+ messages in thread From: Bean @ 2009-06-22 17:37 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 506 bytes --] Hi, Update for this patch: 1, enum_device now pass fs and uuid as well 2, enum_file change parameter order, now the callback function is the first, path is the second 3, add parameter checking for library function 4, add three function file_eof - test if eof is encounter for a file file_exist - test if a file exists add_menu - add menu item I also add a script osdetect.lua which can detect Windows 2K/NT/XP/Vista and linux at runtime, to use it, add this in grub.cfg: source osdetect.lua -- Bean [-- Attachment #2: lua_file_2.diff --] [-- Type: text/x-patch, Size: 14857 bytes --] diff --git a/conf/common.rmk b/conf/common.rmk index fbca2e4..dc78df9 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -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 \ diff --git a/script/lua/grub_lib.c b/script/lua/grub_lib.c index 0295f0d..8561dd0 100644 --- a/script/lua/grub_lib.c +++ b/script/lua/grub_lib.c @@ -24,18 +24,47 @@ #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); + } + grub_device_close (dev); + } + else + save_errno (state); + + 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; + + name = luaL_checkstring (state, 1); + file = grub_file_open (name); + if (file) + { + result = 1; + grub_file_close (file); + } + else + { + result = 0; + grub_errno = 0; + } + + lua_pushboolean (state, result); + return 1; +} + +static int +grub_lua_add_menu (lua_State *state) +{ + int len, n; + const char *source; + + source = luaL_checklstring (state, 1, &len); + 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} }; diff --git a/script/lua/grub_lua.h b/script/lua/grub_lua.h index a181b52..d5181f1 100644 --- a/script/lua/grub_lua.h +++ b/script/lua/grub_lua.h @@ -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 diff --git a/script/lua/grub_main.c b/script/lua/grub_main.c index 03f890a..b39141f 100644 --- a/script/lua/grub_main.c +++ b/script/lua/grub_main.c @@ -24,6 +24,61 @@ #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 diff --git a/script/lua/linit.c b/script/lua/linit.c index d034a2f..f920a0b 100644 --- a/script/lua/linit.c +++ b/script/lua/linit.c @@ -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 index 0000000..ff6b613 --- /dev/null +++ b/util/osdetect.lua @@ -0,0 +1,84 @@ +#!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 = "Other OS" + 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" + 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.img-" .. kernels[i]) then + initrd = "\ninird /boot/initrd.img-" .. 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 + + grub.add_menu (source, title) + return 0 +end + +grub.enum_device (enum_device) ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 17:37 ` Bean @ 2009-06-22 18:31 ` Pavel Roskin 2009-06-22 18:49 ` Bean 2009-07-31 8:07 ` Marco Gerards 1 sibling, 1 reply; 31+ messages in thread From: Pavel Roskin @ 2009-06-22 18:31 UTC (permalink / raw) To: The development of GRUB 2 On Tue, 2009-06-23 at 01:37 +0800, Bean wrote: > Hi, > > Update for this patch: > > 1, enum_device now pass fs and uuid as well > 2, enum_file change parameter order, now the callback function is the > first, path is the second > 3, add parameter checking for library function > 4, add three function > > file_eof - test if eof is encounter for a file > file_exist - test if a file exists > add_menu - add menu item The new patch introduces a warning: script/lua/grub_lib.c: In function 'grub_lua_add_menu': script/lua/grub_lib.c:394: warning: pointer targets in passing argument 3 of 'luaL_checklstring' differ in signedness script/lua/lauxlib.h:51: note: expected 'size_t *' but argument is of type 'int *' Fix: diff --git a/script/lua/grub_lib.c b/script/lua/grub_lib.c index 8561dd0..bcff3db 100644 --- a/script/lua/grub_lib.c +++ b/script/lua/grub_lib.c @@ -388,7 +388,8 @@ grub_lua_file_exist (lua_State *state) static int grub_lua_add_menu (lua_State *state) { - int len, n; + int n; + size_t len; const char *source; source = luaL_checklstring (state, 1, &len); > I also add a script osdetect.lua which can detect Windows > 2K/NT/XP/Vista and linux at runtime, to use it, add this in grub.cfg: > > source osdetect.lua It didn't find Linux for me, but it found the "Other OS", which is actually FreeDOS. -- Regards, Pavel Roskin ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 18:31 ` Pavel Roskin @ 2009-06-22 18:49 ` Bean 2009-06-22 18:59 ` Pavel Roskin 0 siblings, 1 reply; 31+ messages in thread From: Bean @ 2009-06-22 18:49 UTC (permalink / raw) To: The development of GRUB 2 On Tue, Jun 23, 2009 at 2:31 AM, Pavel Roskin<proski@gnu.org> wrote: > On Tue, 2009-06-23 at 01:37 +0800, Bean wrote: >> Hi, >> >> Update for this patch: >> >> 1, enum_device now pass fs and uuid as well >> 2, enum_file change parameter order, now the callback function is the >> first, path is the second >> 3, add parameter checking for library function >> 4, add three function >> >> file_eof - test if eof is encounter for a file >> file_exist - test if a file exists >> add_menu - add menu item > > The new patch introduces a warning: > > script/lua/grub_lib.c: In function 'grub_lua_add_menu': > script/lua/grub_lib.c:394: warning: pointer targets in passing argument > 3 of 'luaL_checklstring' differ in signedness > script/lua/lauxlib.h:51: note: expected 'size_t *' but argument is of > type 'int *' > > Fix: > > diff --git a/script/lua/grub_lib.c b/script/lua/grub_lib.c > index 8561dd0..bcff3db 100644 > --- a/script/lua/grub_lib.c > +++ b/script/lua/grub_lib.c > @@ -388,7 +388,8 @@ grub_lua_file_exist (lua_State *state) > static int > grub_lua_add_menu (lua_State *state) > { > - int len, n; > + int n; > + size_t len; > const char *source; > > source = luaL_checklstring (state, 1, &len); > >> I also add a script osdetect.lua which can detect Windows >> 2K/NT/XP/Vista and linux at runtime, to use it, add this in grub.cfg: >> >> source osdetect.lua > > It didn't find Linux for me, but it found the "Other OS", which is > actually FreeDOS. What's the name of kernel and initrd.img ? > > -- > Regards, > Pavel Roskin > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel > -- Bean ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 18:49 ` Bean @ 2009-06-22 18:59 ` Pavel Roskin 2009-06-22 19:15 ` Bean 0 siblings, 1 reply; 31+ messages in thread From: Pavel Roskin @ 2009-06-22 18:59 UTC (permalink / raw) To: The development of GRUB 2 On Tue, 2009-06-23 at 02:49 +0800, Bean wrote: > What's the name of kernel and initrd.img ? vmlinuz-2.6.30-wl and initrd-2.6.30-wl.img -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 18:59 ` Pavel Roskin @ 2009-06-22 19:15 ` Bean 2009-06-22 19:28 ` Pavel Roskin 0 siblings, 1 reply; 31+ messages in thread From: Bean @ 2009-06-22 19:15 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 455 bytes --] On Tue, Jun 23, 2009 at 2:59 AM, Pavel Roskin<proski@gnu.org> wrote: > On Tue, 2009-06-23 at 02:49 +0800, Bean wrote: > >> What's the name of kernel and initrd.img ? > > vmlinuz-2.6.30-wl and initrd-2.6.30-wl.img Hi, Oh, find the bug now, try this one. > > -- > Regards, > Pavel Roskin > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel > -- Bean [-- Attachment #2: lua_file_2.diff --] [-- Type: text/x-patch, Size: 15071 bytes --] diff --git a/conf/common.rmk b/conf/common.rmk index fbca2e4..dc78df9 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -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 \ diff --git a/script/lua/grub_lib.c b/script/lua/grub_lib.c index 0295f0d..7f738c9 100644 --- a/script/lua/grub_lib.c +++ b/script/lua/grub_lib.c @@ -24,18 +24,47 @@ #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,324 @@ 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 + save_errno (state); + + 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; + + name = luaL_checkstring (state, 1); + file = grub_file_open (name); + if (file) + { + result = 1; + grub_file_close (file); + } + else + { + result = 0; + 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} }; diff --git a/script/lua/grub_lua.h b/script/lua/grub_lua.h index a181b52..d5181f1 100644 --- a/script/lua/grub_lua.h +++ b/script/lua/grub_lua.h @@ -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 diff --git a/script/lua/grub_main.c b/script/lua/grub_main.c index 03f890a..b39141f 100644 --- a/script/lua/grub_main.c +++ b/script/lua/grub_main.c @@ -24,6 +24,61 @@ #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 diff --git a/script/lua/linit.c b/script/lua/linit.c index d034a2f..f920a0b 100644 --- a/script/lua/linit.c +++ b/script/lua/linit.c @@ -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 index 0000000..af1d491 --- /dev/null +++ b/util/osdetect.lua @@ -0,0 +1,94 @@ +#!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" + 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.img-" .. kernels[i]) then + initrd = "\ninird /boot/initrd.img-" .. 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) ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 19:15 ` Bean @ 2009-06-22 19:28 ` Pavel Roskin 2009-06-22 19:50 ` Bean 0 siblings, 1 reply; 31+ messages in thread From: Pavel Roskin @ 2009-06-22 19:28 UTC (permalink / raw) To: The development of GRUB 2 On Tue, 2009-06-23 at 03:15 +0800, Bean wrote: > Oh, find the bug now, try this one. This one fails to find anything: sh:grub> source /boot/grub/osdetect.lua error: Lua: grub:1: attempt to call field 'enum_device' (a nil value) sh:grub> -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 19:28 ` Pavel Roskin @ 2009-06-22 19:50 ` Bean 2009-06-22 20:06 ` Pavel Roskin 0 siblings, 1 reply; 31+ messages in thread From: Bean @ 2009-06-22 19:50 UTC (permalink / raw) To: The development of GRUB 2 On Tue, Jun 23, 2009 at 3:28 AM, Pavel Roskin<proski@gnu.org> wrote: > On Tue, 2009-06-23 at 03:15 +0800, Bean wrote: > >> Oh, find the bug now, try this one. > > This one fails to find anything: > > sh:grub> source /boot/grub/osdetect.lua > error: Lua: grub:1: attempt to call field 'enum_device' (a nil value) > sh:grub> Hi, strange, it's working here, what's the device list ? > > -- > Regards, > Pavel Roskin > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel > -- Bean ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 19:50 ` Bean @ 2009-06-22 20:06 ` Pavel Roskin 2009-06-23 9:27 ` Bean 2009-06-25 22:39 ` Vladimir 'phcoder' Serbinenko 0 siblings, 2 replies; 31+ messages in thread From: Pavel Roskin @ 2009-06-22 20:06 UTC (permalink / raw) To: The development of GRUB 2 On Tue, 2009-06-23 at 03:50 +0800, Bean wrote: > strange, it's working here, what's the device list ? My mistake. I installed an unpatched GRUB. The entries are created now. However, the initrd is not picked up. The old kernel (vmlinuz-2.6.30-wl.old) goes before the new one (vmlinuz-2.6.30-wl). And most importantly, the syntax for the root command is wrong. "root hd0,3" has not effect. "root (hd0,3)" and "root=hd0,3" work. Yes, that's a bug in the root command. -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 20:06 ` Pavel Roskin @ 2009-06-23 9:27 ` Bean 2009-06-23 22:10 ` Pavel Roskin 2009-06-25 22:39 ` Vladimir 'phcoder' Serbinenko 1 sibling, 1 reply; 31+ messages in thread From: Bean @ 2009-06-23 9:27 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 1015 bytes --] Hi, Some bug fix for osdetect.lua, it also detect windows 98/me, freedos, msdos and freebsd. Extend the function of grub.file_exist to allow testing multiple names at the same time, this simplify osdetect.lua. On Tue, Jun 23, 2009 at 4:06 AM, Pavel Roskin<proski@gnu.org> wrote: > On Tue, 2009-06-23 at 03:50 +0800, Bean wrote: > >> strange, it's working here, what's the device list ? > > My mistake. I installed an unpatched GRUB. > > The entries are created now. However, the initrd is not picked up. The > old kernel (vmlinuz-2.6.30-wl.old) goes before the new one > (vmlinuz-2.6.30-wl). And most importantly, the syntax for the root > command is wrong. > > "root hd0,3" has not effect. "root (hd0,3)" and "root=hd0,3" work. > Yes, that's a bug in the root command. > > -- > Regards, > Pavel Roskin > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel > -- Bean [-- Attachment #2: lua_file_3.diff --] [-- Type: text/x-diff, Size: 15646 bytes --] diff --git a/conf/common.rmk b/conf/common.rmk index fbca2e4..dc78df9 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -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 \ diff --git a/script/lua/grub_lib.c b/script/lua/grub_lib.c index 0295f0d..9875e8b 100644 --- a/script/lua/grub_lib.c +++ b/script/lua/grub_lib.c @@ -24,18 +24,47 @@ #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,330 @@ 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 + save_errno (state); + + 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) +{ + int result, i, n; + + result = 1; + n = lua_gettop (state); + for (i = 1; i <= n; i++) + { + grub_file_t file; + const char *name; + + name = luaL_checkstring (state, i); + file = grub_file_open (name); + if (file) + { + grub_file_close (file); + } + else + { + result = 0; + grub_errno = 0; + break; + } + } + + 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} }; diff --git a/script/lua/grub_lua.h b/script/lua/grub_lua.h index a181b52..d5181f1 100644 --- a/script/lua/grub_lua.h +++ b/script/lua/grub_lua.h @@ -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 diff --git a/script/lua/grub_main.c b/script/lua/grub_main.c index 03f890a..b39141f 100644 --- a/script/lua/grub_main.c +++ b/script/lua/grub_main.c @@ -24,6 +24,61 @@ #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 diff --git a/script/lua/linit.c b/script/lua/linit.c index d034a2f..f920a0b 100644 --- a/script/lua/linit.c +++ b/script/lua/linit.c @@ -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 index 0000000..33d86d7 --- /dev/null +++ b/util/osdetect.lua @@ -0,0 +1,105 @@ +#!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 roo + 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", root .. "boot/bcd") then + title = "Windows Vista bootmgr" + elseif grub.file_exist (root .. "ntldr", root .. "ntdetect.com", + 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", root .. "command.com") then + title = "MSDOS" + elseif grub.file_exist (root .. "kernel.sys") then + title = "FressDOS" + elseif grub.file_exist (root .. "boot/loader", + root .. "boot/devices.hints") then + source = "root (" .. device .. ")\nfreebsd /boot/loader" .. + "\nfreebsd_loadenv /boot/device.hints" + title = "FressBSD" + 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.img-" .. kernels[i]) then + initrd = "\ninird /boot/initrd.img-" .. kernels[i] + elseif grub.file_exist (root .. "boot/initrd-" .. kernels[i]) then + initrd = "\ninird /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) ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-23 9:27 ` Bean @ 2009-06-23 22:10 ` Pavel Roskin 2009-06-23 22:50 ` Robert Millan 2009-06-24 4:41 ` Bean 0 siblings, 2 replies; 31+ messages in thread From: Pavel Roskin @ 2009-06-23 22:10 UTC (permalink / raw) To: The development of GRUB 2 On Tue, 2009-06-23 at 17:27 +0800, Bean wrote: > Hi, > > Some bug fix for osdetect.lua, it also detect windows 98/me, freedos, > msdos and freebsd. Why FressDOS and FressBSD? I assume it's typos. Why isn't Linux capitalized? MS-DOS is written with a dash. "Windows Vista bootmgr" should be "Windows Vista" and "Windows NT/2000/XP loader" should be "Windows NT/2000/XP". It's not like we are just booting the loaders. inird should be initrd. Please add check for the Fedora style names for initrd, namely "initrd-KVER.img". Or maybe you just missed ".img" in the second check? > Extend the function of grub.file_exist to allow testing multiple names > at the same time, this simplify osdetect.lua. The change to grub_lua_file_exist() is dubious. It's not clear why the requirement is that all files exist. Maybe I don't know the style of lua, but I think it's wrong to hardcode the AND logic just because one script would benefit from it. If we consider e.g. the wildcard expansion in make, it will return a non-empty value if any file exists, i.e. the OR logic is used. I suggest that you split the lua.mod changes and osdetect.lua. The later is obviously a bikeshed issue that can be discussed for a long time. The former needs a more technical consideration. -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-23 22:10 ` Pavel Roskin @ 2009-06-23 22:50 ` Robert Millan 2009-06-26 23:25 ` Pavel Roskin 2009-06-24 4:41 ` Bean 1 sibling, 1 reply; 31+ messages in thread From: Robert Millan @ 2009-06-23 22:50 UTC (permalink / raw) To: The development of GRUB 2 On Tue, Jun 23, 2009 at 06:10:36PM -0400, Pavel Roskin wrote: > On Tue, 2009-06-23 at 17:27 +0800, Bean wrote: > > Hi, > > > > Some bug fix for osdetect.lua, it also detect windows 98/me, freedos, > > msdos and freebsd. > > Why FressDOS and FressBSD? I assume it's typos. Why isn't Linux > capitalized? MS-DOS is written with a dash. "Windows Vista bootmgr" > should be "Windows Vista" and "Windows NT/2000/XP loader" should be > "Windows NT/2000/XP". It's not like we are just booting the loaders. But when we're booting a kernel (Linux) we just say that. Shouldn't we be consistent and say "bootmgr" and "ntldr" too? Btw, to make this even more interesting, there's also freeldr, which can be used to boot either Windows NT/2000/XP or ReactOS. -- Robert Millan The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and how) you may access your data; but nobody's threatening your freedom: we still allow you to remove your data and not access it at all." ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-23 22:50 ` Robert Millan @ 2009-06-26 23:25 ` Pavel Roskin 0 siblings, 0 replies; 31+ messages in thread From: Pavel Roskin @ 2009-06-26 23:25 UTC (permalink / raw) To: The development of GRUB 2 On Wed, 2009-06-24 at 00:50 +0200, Robert Millan wrote: > On Tue, Jun 23, 2009 at 06:10:36PM -0400, Pavel Roskin wrote: > > On Tue, 2009-06-23 at 17:27 +0800, Bean wrote: > > > Hi, > > > > > > Some bug fix for osdetect.lua, it also detect windows 98/me, freedos, > > > msdos and freebsd. > > > > Why FressDOS and FressBSD? I assume it's typos. Why isn't Linux > > capitalized? MS-DOS is written with a dash. "Windows Vista bootmgr" > > should be "Windows Vista" and "Windows NT/2000/XP loader" should be > > "Windows NT/2000/XP". It's not like we are just booting the loaders. > > But when we're booting a kernel (Linux) we just say that. Shouldn't we > be consistent and say "bootmgr" and "ntldr" too? The difference is that we are using chainloader to boot Windows, so we treat is as one system. If we were loading ntldr from GRUB, then it would be appropriate to mention it. -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-23 22:10 ` Pavel Roskin 2009-06-23 22:50 ` Robert Millan @ 2009-06-24 4:41 ` Bean 2009-06-24 5:58 ` Bean 2009-06-27 0:22 ` Pavel Roskin 1 sibling, 2 replies; 31+ messages in thread From: Bean @ 2009-06-24 4:41 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 2401 bytes --] On Wed, Jun 24, 2009 at 6:10 AM, Pavel Roskin<proski@gnu.org> wrote: > On Tue, 2009-06-23 at 17:27 +0800, Bean wrote: >> Hi, >> >> Some bug fix for osdetect.lua, it also detect windows 98/me, freedos, >> msdos and freebsd. > > Why FressDOS and FressBSD? I assume it's typos. Why isn't Linux > capitalized? MS-DOS is written with a dash. "Windows Vista bootmgr" > should be "Windows Vista" and "Windows NT/2000/XP loader" should be > "Windows NT/2000/XP". It's not like we are just booting the loaders. > Oh, fixed typos now. As for "Windows Vista bootmgr" and "Windows NT/2000/XP loader", I just copy them from 10_windows.in, I guess there is a reason for it there. > inird should be initrd. Please add check for the Fedora style names for > initrd, namely "initrd-KVER.img". Or maybe you just missed ".img" in > the second check? > Add the test for initrd-KVER.img. Is there any distro that uses initrd-KVER ? if not, I can just remove the second test. >> Extend the function of grub.file_exist to allow testing multiple names >> at the same time, this simplify osdetect.lua. > > The change to grub_lua_file_exist() is dubious. It's not clear why the > requirement is that all files exist. Maybe I don't know the style of > lua, but I think it's wrong to hardcode the AND logic just because one > script would benefit from it. As lua can detect the number of parameter quite easily, I just think it'd be a waste not to utilize it. If you always call it with one parameter, then it's equivalent to the previous file_exist. It's just a little more code in c, but it can reduce the number of calls between c and lua. > > If we consider e.g. the wildcard expansion in make, it will return a > non-empty value if any file exists, i.e. the OR logic is used. > We can add a new function that uses OR logic instead of AND, for example, grub.file_exist_any, and the current AND version can be called grub.file_exist_all. > I suggest that you split the lua.mod changes and osdetect.lua. The > later is obviously a bikeshed issue that can be discussed for a long > time. The former needs a more technical consideration. Ok. > > -- > Regards, > Pavel Roskin > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel > -- Bean [-- Attachment #2: lua_file_3.diff --] [-- Type: text/x-diff, Size: 12205 bytes --] diff --git a/conf/common.rmk b/conf/common.rmk index fbca2e4..dc78df9 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -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 \ diff --git a/script/lua/grub_lib.c b/script/lua/grub_lib.c index 0295f0d..9875e8b 100644 --- a/script/lua/grub_lib.c +++ b/script/lua/grub_lib.c @@ -24,18 +24,47 @@ #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,330 @@ 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 + save_errno (state); + + 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) +{ + int result, i, n; + + result = 1; + n = lua_gettop (state); + for (i = 1; i <= n; i++) + { + grub_file_t file; + const char *name; + + name = luaL_checkstring (state, i); + file = grub_file_open (name); + if (file) + { + grub_file_close (file); + } + else + { + result = 0; + grub_errno = 0; + break; + } + } + + 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} }; diff --git a/script/lua/grub_lua.h b/script/lua/grub_lua.h index a181b52..d5181f1 100644 --- a/script/lua/grub_lua.h +++ b/script/lua/grub_lua.h @@ -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 diff --git a/script/lua/grub_main.c b/script/lua/grub_main.c index 03f890a..b39141f 100644 --- a/script/lua/grub_main.c +++ b/script/lua/grub_main.c @@ -24,6 +24,61 @@ #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 diff --git a/script/lua/linit.c b/script/lua/linit.c index d034a2f..f920a0b 100644 --- a/script/lua/linit.c +++ b/script/lua/linit.c @@ -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} [-- Attachment #3: osdetect.gz --] [-- Type: application/x-gzip, Size: 1249 bytes --] ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-24 4:41 ` Bean @ 2009-06-24 5:58 ` Bean 2009-06-27 0:22 ` Pavel Roskin 1 sibling, 0 replies; 31+ messages in thread From: Bean @ 2009-06-24 5:58 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 95 bytes --] Hi, Oh, found a small bug in the previous osdetect.lua, here is an updated version. -- Bean [-- Attachment #2: osdetect.gz --] [-- Type: application/x-gzip, Size: 1249 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-24 4:41 ` Bean 2009-06-24 5:58 ` Bean @ 2009-06-27 0:22 ` Pavel Roskin 2009-06-27 3:53 ` Bean 1 sibling, 1 reply; 31+ messages in thread From: Pavel Roskin @ 2009-06-27 0:22 UTC (permalink / raw) To: The development of GRUB 2 On Wed, 2009-06-24 at 12:41 +0800, Bean wrote: > Oh, fixed typos now. As for "Windows Vista bootmgr" and "Windows > NT/2000/XP loader", I just copy them from 10_windows.in, I guess there > is a reason for it there. I don't think so. > > inird should be initrd. Please add check for the Fedora style names for > > initrd, namely "initrd-KVER.img". Or maybe you just missed ".img" in > > the second check? > > > > Add the test for initrd-KVER.img. Is there any distro that uses > initrd-KVER ? if not, I can just remove the second test. Actually, I think SUSE uses initrd-KVER (no SUSE around, but Google seems to confirm it), Fedora uses initrd-KVER.img and Debian uses initrd.img-KVER, so we need to support all three. > >> Extend the function of grub.file_exist to allow testing multiple names > >> at the same time, this simplify osdetect.lua. > > > > The change to grub_lua_file_exist() is dubious. It's not clear why the > > requirement is that all files exist. Maybe I don't know the style of > > lua, but I think it's wrong to hardcode the AND logic just because one > > script would benefit from it. > > As lua can detect the number of parameter quite easily, I just think > it'd be a waste not to utilize it. If you always call it with one > parameter, then it's equivalent to the previous file_exist. It's just > a little more code in c, but it can reduce the number of calls between > c and lua. I think it's not nice to add bells and whistles to a basic function checking existence of a file. Imagine if libc did is, and stat() would take a list of files. > > If we consider e.g. the wildcard expansion in make, it will return a > > non-empty value if any file exists, i.e. the OR logic is used. > > > > We can add a new function that uses OR logic instead of AND, for > example, grub.file_exist_any, and the current AND version can be > called grub.file_exist_all. Can we implement them in lua? I think it would be better than to implement them in C. -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-27 0:22 ` Pavel Roskin @ 2009-06-27 3:53 ` Bean 2009-06-27 4:04 ` Pavel Roskin 0 siblings, 1 reply; 31+ messages in thread From: Bean @ 2009-06-27 3:53 UTC (permalink / raw) To: The development of GRUB 2 On Sat, Jun 27, 2009 at 8:22 AM, Pavel Roskin<proski@gnu.org> wrote: > On Wed, 2009-06-24 at 12:41 +0800, Bean wrote: > >> Oh, fixed typos now. As for "Windows Vista bootmgr" and "Windows >> NT/2000/XP loader", I just copy them from 10_windows.in, I guess there >> is a reason for it there. > > I don't think so. Fine with me. > Can we implement them in lua? I think it would be better than to > implement them in C. Yes, actually it's just a bunch of file_exist AND or OR together, but I think if we use this kind of test often enough, implement it in c would be more efficient. -- Bean ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-27 3:53 ` Bean @ 2009-06-27 4:04 ` Pavel Roskin 2009-06-27 4:14 ` Bean 0 siblings, 1 reply; 31+ messages in thread From: Pavel Roskin @ 2009-06-27 4:04 UTC (permalink / raw) To: The development of GRUB 2 On Sat, 2009-06-27 at 11:53 +0800, Bean wrote: > Yes, actually it's just a bunch of file_exist AND or OR together, but > I think if we use this kind of test often enough, implement it in c > would be more efficient. So far, we only have one file. I checked the Lua reference manual, and no file related functions take lists of filenames: http://www.lua.org/manual/5.1/ If it was ineffective, I think Lua developers would have designed the file access differently. -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-27 4:04 ` Pavel Roskin @ 2009-06-27 4:14 ` Bean 2009-07-05 9:59 ` Bean 0 siblings, 1 reply; 31+ messages in thread From: Bean @ 2009-06-27 4:14 UTC (permalink / raw) To: The development of GRUB 2 On Sat, Jun 27, 2009 at 12:04 PM, Pavel Roskin<proski@gnu.org> wrote: > On Sat, 2009-06-27 at 11:53 +0800, Bean wrote: > >> Yes, actually it's just a bunch of file_exist AND or OR together, but >> I think if we use this kind of test often enough, implement it in c >> would be more efficient. > > So far, we only have one file. > > I checked the Lua reference manual, and no file related functions take > lists of filenames: > > http://www.lua.org/manual/5.1/ > > If it was ineffective, I think Lua developers would have designed the > file access differently. All right then, I'd change it back to single parameter. Actually it's not a big deal, but I just hate long lines, :) -- Bean ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-27 4:14 ` Bean @ 2009-07-05 9:59 ` Bean 2009-07-05 13:11 ` Duboucher Thomas 0 siblings, 1 reply; 31+ messages in thread From: Bean @ 2009-07-05 9:59 UTC (permalink / raw) To: The development of GRUB 2 Committed. On Sat, Jun 27, 2009 at 12:14 PM, Bean<bean123ch@gmail.com> wrote: > On Sat, Jun 27, 2009 at 12:04 PM, Pavel Roskin<proski@gnu.org> wrote: >> On Sat, 2009-06-27 at 11:53 +0800, Bean wrote: >> >>> Yes, actually it's just a bunch of file_exist AND or OR together, but >>> I think if we use this kind of test often enough, implement it in c >>> would be more efficient. >> >> So far, we only have one file. >> >> I checked the Lua reference manual, and no file related functions take >> lists of filenames: >> >> http://www.lua.org/manual/5.1/ >> >> If it was ineffective, I think Lua developers would have designed the >> file access differently. > > All right then, I'd change it back to single parameter. Actually it's > not a big deal, but I just hate long lines, :) > > -- > Bean > -- Bean ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-07-05 9:59 ` Bean @ 2009-07-05 13:11 ` Duboucher Thomas 2009-07-05 14:28 ` Bean 0 siblings, 1 reply; 31+ messages in thread From: Duboucher Thomas @ 2009-07-05 13:11 UTC (permalink / raw) To: The development of GRUB 2 -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I was reading the code and now I have a question. You are creating a grub librairy writen in C including useful functions such as 'grub.file_open'. But in your implementation, you removed base libraries such as 'os' and 'io'. So why don't you just rewrite 'io.open' instead of creating 'grub.file_open'? Thomas. Bean a écrit : > Committed. > > On Sat, Jun 27, 2009 at 12:14 PM, Bean<bean123ch@gmail.com> wrote: >> On Sat, Jun 27, 2009 at 12:04 PM, Pavel Roskin<proski@gnu.org> wrote: >>> On Sat, 2009-06-27 at 11:53 +0800, Bean wrote: >>> >>>> Yes, actually it's just a bunch of file_exist AND or OR together, but >>>> I think if we use this kind of test often enough, implement it in c >>>> would be more efficient. >>> So far, we only have one file. >>> >>> I checked the Lua reference manual, and no file related functions take >>> lists of filenames: >>> >>> http://www.lua.org/manual/5.1/ >>> >>> If it was ineffective, I think Lua developers would have designed the >>> file access differently. >> All right then, I'd change it back to single parameter. Actually it's >> not a big deal, but I just hate long lines, :) >> >> -- >> Bean >> > > > -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkpQpmcACgkQBV7eXqefhqjZkgCfdigjl2N7DFu3xxNCLDbyMerP AyEAoKzDcOW6ebJtdEIUcNSB9q57q64G =fJix -----END PGP SIGNATURE----- ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-07-05 13:11 ` Duboucher Thomas @ 2009-07-05 14:28 ` Bean 0 siblings, 0 replies; 31+ messages in thread From: Bean @ 2009-07-05 14:28 UTC (permalink / raw) To: The development of GRUB 2 On Sun, Jul 5, 2009 at 9:11 PM, Duboucher Thomas<thomas@duboucher.eu> wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > I was reading the code and now I have a question. You are creating a > grub librairy writen in C including useful functions such as > 'grub.file_open'. But in your implementation, you removed base libraries > such as 'os' and 'io'. So why don't you just rewrite 'io.open' instead > of creating 'grub.file_open'? Hi, The io library uses many stdio function, such as fopen, which doesn't exist in grub. -- Bean ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 20:06 ` Pavel Roskin 2009-06-23 9:27 ` Bean @ 2009-06-25 22:39 ` Vladimir 'phcoder' Serbinenko 2009-06-26 23:45 ` Pavel Roskin 1 sibling, 1 reply; 31+ messages in thread From: Vladimir 'phcoder' Serbinenko @ 2009-06-25 22:39 UTC (permalink / raw) To: The development of GRUB 2 On Mon, Jun 22, 2009 at 10:06 PM, Pavel Roskin<proski@gnu.org> wrote: > On Tue, 2009-06-23 at 03:50 +0800, Bean wrote: > >> strange, it's working here, what's the device list ? > > My mistake. I installed an unpatched GRUB. > > The entries are created now. However, the initrd is not picked up. The > old kernel (vmlinuz-2.6.30-wl.old) goes before the new one > (vmlinuz-2.6.30-wl). And most importantly, the syntax for the root > command is wrong. > > "root hd0,3" has not effect. "root (hd0,3)" and "root=hd0,3" work. > Yes, that's a bug in the root command. Can't root command be ditched altogether? It sounds like completely redundant to me and just taking precious kernel space > > -- > Regards, > Pavel Roskin > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel > -- Regards Vladimir 'phcoder' Serbinenko Personal git repository: http://repo.or.cz/w/grub2/phcoder.git ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-25 22:39 ` Vladimir 'phcoder' Serbinenko @ 2009-06-26 23:45 ` Pavel Roskin 0 siblings, 0 replies; 31+ messages in thread From: Pavel Roskin @ 2009-06-26 23:45 UTC (permalink / raw) To: The development of GRUB 2 On Fri, 2009-06-26 at 00:39 +0200, Vladimir 'phcoder' Serbinenko wrote: > On Mon, Jun 22, 2009 at 10:06 PM, Pavel Roskin<proski@gnu.org> wrote: > > "root hd0,3" has not effect. "root (hd0,3)" and "root=hd0,3" work. > > Yes, that's a bug in the root command. > Can't root command be ditched altogether? It sounds like completely > redundant to me and just taking precious kernel space Fine with me. -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH] File access library for lua 2009-06-22 17:37 ` Bean 2009-06-22 18:31 ` Pavel Roskin @ 2009-07-31 8:07 ` Marco Gerards 1 sibling, 0 replies; 31+ messages in thread From: Marco Gerards @ 2009-07-31 8:07 UTC (permalink / raw) To: The development of GRUB 2 Bean <bean123ch@gmail.com> writes: > Hi, > > Update for this patch: > > 1, enum_device now pass fs and uuid as well > 2, enum_file change parameter order, now the callback function is the > first, path is the second > 3, add parameter checking for library function > 4, add three function > > file_eof - test if eof is encounter for a file > file_exist - test if a file exists > add_menu - add menu item > > I also add a script osdetect.lua which can detect Windows > 2K/NT/XP/Vista and linux at runtime, to use it, add this in grub.cfg: > > source osdetect.lua Can you please comment on what Robert said? Personally, I do not mind supporting lua. But I prefer that scripts included with GRUB are written using the default scripting language. Some good reasons for this: - I do not know lua, I assume Okuji doesn't either. - Only using one script already requires the user to use lua: slowdown - Personally, I hope people improve on the default scripting language -- Marco ^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2009-07-31 8:07 UTC | newest] Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-06-21 11:33 [PATCH] File access library for lua Bean 2009-06-22 0:42 ` Pavel Roskin 2009-06-22 3:38 ` Bean 2009-06-22 3:45 ` Pavel Roskin 2009-06-22 9:44 ` Robert Millan 2009-06-22 10:26 ` Bean 2009-06-22 10:59 ` Robert Millan 2009-06-22 17:37 ` Bean 2009-06-22 18:31 ` Pavel Roskin 2009-06-22 18:49 ` Bean 2009-06-22 18:59 ` Pavel Roskin 2009-06-22 19:15 ` Bean 2009-06-22 19:28 ` Pavel Roskin 2009-06-22 19:50 ` Bean 2009-06-22 20:06 ` Pavel Roskin 2009-06-23 9:27 ` Bean 2009-06-23 22:10 ` Pavel Roskin 2009-06-23 22:50 ` Robert Millan 2009-06-26 23:25 ` Pavel Roskin 2009-06-24 4:41 ` Bean 2009-06-24 5:58 ` Bean 2009-06-27 0:22 ` Pavel Roskin 2009-06-27 3:53 ` Bean 2009-06-27 4:04 ` Pavel Roskin 2009-06-27 4:14 ` Bean 2009-07-05 9:59 ` Bean 2009-07-05 13:11 ` Duboucher Thomas 2009-07-05 14:28 ` Bean 2009-06-25 22:39 ` Vladimir 'phcoder' Serbinenko 2009-06-26 23:45 ` Pavel Roskin 2009-07-31 8:07 ` Marco Gerards
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.