Remove doubles
[grub-extras.git] / grub_lib.c
blob8e5186db11202bdf4d59fe96b140cf07cbaf5543
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2009 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include "lua.h"
20 #include "lauxlib.h"
21 #include "lualib.h"
22 #include "grub_lib.h"
24 #include <grub/env.h>
25 #include <grub/parser.h>
26 #include <grub/command.h>
27 #include <grub/normal.h>
28 #include <grub/file.h>
29 #include <grub/device.h>
31 #ifdef ENABLE_LUA_PCI
32 #include <grub/pci.h>
33 #endif
35 /* Updates the globals grub_errno and grub_msg, leaving their values on the
36 top of the stack, and clears grub_errno. When grub_errno is zero, grub_msg
37 is not left on the stack. The value returned is the number of values left on
38 the stack. */
39 static int
40 push_result (lua_State *state)
42 int saved_errno;
43 int num_results;
45 saved_errno = grub_errno;
46 grub_errno = 0;
48 /* Push once for setfield, and again to leave on the stack */
49 lua_pushinteger (state, saved_errno);
50 lua_pushinteger (state, saved_errno);
51 lua_setfield (state, LUA_GLOBALSINDEX, "grub_errno");
53 if (saved_errno)
55 /* Push once for setfield, and again to leave on the stack */
56 lua_pushstring (state, grub_errmsg);
57 lua_pushstring (state, grub_errmsg);
58 num_results = 2;
60 else
62 lua_pushnil (state);
63 num_results = 1;
66 lua_setfield (state, LUA_GLOBALSINDEX, "grub_errmsg");
68 return num_results;
71 /* Updates the globals grub_errno and grub_msg ( without leaving them on the
72 stack ), clears grub_errno, and returns the value of grub_errno before it
73 was cleared. */
74 static int
75 save_errno (lua_State *state)
77 int saved_errno;
79 saved_errno = grub_errno;
80 lua_pop(state, push_result(state));
82 return saved_errno;
85 static int
86 grub_lua_run (lua_State *state)
88 int n;
89 char **args;
90 const char *s;
92 s = luaL_checkstring (state, 1);
93 if ((! grub_parser_split_cmdline (s, 0, 0, &n, &args))
94 && (n >= 0))
96 grub_command_t cmd;
98 cmd = grub_command_find (args[0]);
99 if (cmd)
100 (cmd->func) (cmd, n-1, &args[1]);
101 else
102 grub_error (GRUB_ERR_FILE_NOT_FOUND, "command not found");
104 grub_free (args[0]);
105 grub_free (args);
108 return push_result (state);
111 static int
112 grub_lua_getenv (lua_State *state)
114 int n, i;
116 n = lua_gettop (state);
117 for (i = 1; i <= n; i++)
119 const char *name, *value;
121 name = luaL_checkstring (state, i);
122 value = grub_env_get (name);
123 if (value)
124 lua_pushstring (state, value);
125 else
126 lua_pushnil (state);
129 return n;
132 static int
133 grub_lua_setenv (lua_State *state)
135 const char *name, *value;
137 name = luaL_checkstring (state, 1);
138 value = luaL_checkstring (state, 2);
140 if (name[0])
141 grub_env_set (name, value);
143 return 0;
146 /* Helper for grub_lua_enum_device. */
147 static int
148 grub_lua_enum_device_iter (const char *name, void *data)
150 lua_State *state = data;
151 int result;
152 grub_device_t dev;
154 result = 0;
155 dev = grub_device_open (name);
156 if (dev)
158 grub_fs_t fs;
160 fs = grub_fs_probe (dev);
161 if (fs)
163 lua_pushvalue (state, 1);
164 lua_pushstring (state, name);
165 lua_pushstring (state, fs->name);
166 if (! fs->uuid)
167 lua_pushnil (state);
168 else
170 int err;
171 char *uuid;
173 err = fs->uuid (dev, &uuid);
174 if (err)
176 grub_errno = 0;
177 lua_pushnil (state);
179 else
181 lua_pushstring (state, uuid);
182 grub_free (uuid);
186 lua_call (state, 3, 1);
187 result = lua_tointeger (state, -1);
188 lua_pop (state, 1);
190 else
191 grub_errno = 0;
192 grub_device_close (dev);
194 else
195 grub_errno = 0;
197 return result;
200 static int
201 grub_lua_enum_device (lua_State *state)
203 luaL_checktype (state, 1, LUA_TFUNCTION);
204 grub_device_iterate (grub_lua_enum_device_iter, state);
205 return push_result (state);
208 static int
209 enum_file (const char *name, const struct grub_dirhook_info *info,
210 void *data)
212 int result;
213 lua_State *state = data;
215 lua_pushvalue (state, 1);
216 lua_pushstring (state, name);
217 lua_pushinteger (state, info->dir != 0);
218 lua_call (state, 2, 1);
219 result = lua_tointeger (state, -1);
220 lua_pop (state, 1);
222 return result;
225 static int
226 grub_lua_enum_file (lua_State *state)
228 char *device_name;
229 const char *arg;
230 grub_device_t dev;
232 luaL_checktype (state, 1, LUA_TFUNCTION);
233 arg = luaL_checkstring (state, 2);
234 device_name = grub_file_get_device_name (arg);
235 dev = grub_device_open (device_name);
236 if (dev)
238 grub_fs_t fs;
239 const char *path;
241 fs = grub_fs_probe (dev);
242 path = grub_strchr (arg, ')');
243 if (! path)
244 path = arg;
245 else
246 path++;
248 if (fs)
250 (fs->dir) (dev, path, enum_file, state);
253 grub_device_close (dev);
256 grub_free (device_name);
258 return push_result (state);
261 #ifdef ENABLE_LUA_PCI
262 /* Helper for grub_lua_enum_pci. */
263 static int
264 grub_lua_enum_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
266 lua_State *state = data;
267 int result;
268 grub_pci_address_t addr;
269 grub_uint32_t class;
271 lua_pushvalue (state, 1);
272 lua_pushinteger (state, grub_pci_get_bus (dev));
273 lua_pushinteger (state, grub_pci_get_device (dev));
274 lua_pushinteger (state, grub_pci_get_function (dev));
275 lua_pushinteger (state, pciid);
277 addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
278 class = grub_pci_read (addr);
279 lua_pushinteger (state, class);
281 lua_call (state, 5, 1);
282 result = lua_tointeger (state, -1);
283 lua_pop (state, 1);
285 return result;
288 static int
289 grub_lua_enum_pci (lua_State *state)
291 luaL_checktype (state, 1, LUA_TFUNCTION);
292 grub_pci_iterate (grub_lua_enum_pci_iter, state);
293 return push_result (state);
295 #endif
297 static int
298 grub_lua_file_open (lua_State *state)
300 grub_file_t file;
301 const char *name;
303 name = luaL_checkstring (state, 1);
304 file = grub_file_open (name);
305 save_errno (state);
307 if (! file)
308 return 0;
310 lua_pushlightuserdata (state, file);
311 return 1;
314 static int
315 grub_lua_file_close (lua_State *state)
317 grub_file_t file;
319 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
320 file = lua_touserdata (state, 1);
321 grub_file_close (file);
323 return push_result (state);
326 static int
327 grub_lua_file_seek (lua_State *state)
329 grub_file_t file;
330 grub_off_t offset;
332 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
333 file = lua_touserdata (state, 1);
334 offset = luaL_checkinteger (state, 2);
336 offset = grub_file_seek (file, offset);
337 save_errno (state);
339 lua_pushinteger (state, offset);
340 return 1;
343 static int
344 grub_lua_file_read (lua_State *state)
346 grub_file_t file;
347 luaL_Buffer b;
348 int n;
350 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
351 file = lua_touserdata (state, 1);
352 n = luaL_checkinteger (state, 2);
354 luaL_buffinit (state, &b);
355 while (n)
357 char *p;
358 int nr;
360 nr = (n > LUAL_BUFFERSIZE) ? LUAL_BUFFERSIZE : n;
361 p = luaL_prepbuffer (&b);
363 nr = grub_file_read (file, p, nr);
364 if (nr <= 0)
365 break;
367 luaL_addsize (&b, nr);
368 n -= nr;
371 save_errno (state);
372 luaL_pushresult (&b);
373 return 1;
376 static int
377 grub_lua_file_getline (lua_State *state)
379 grub_file_t file;
380 char *line;
382 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
383 file = lua_touserdata (state, 1);
385 line = grub_file_getline (file);
386 save_errno (state);
388 if (! line)
389 return 0;
391 lua_pushstring (state, line);
392 grub_free (line);
393 return 1;
396 static int
397 grub_lua_file_getsize (lua_State *state)
399 grub_file_t file;
401 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
402 file = lua_touserdata (state, 1);
404 lua_pushinteger (state, file->size);
405 return 1;
408 static int
409 grub_lua_file_getpos (lua_State *state)
411 grub_file_t file;
413 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
414 file = lua_touserdata (state, 1);
416 lua_pushinteger (state, file->offset);
417 return 1;
420 static int
421 grub_lua_file_eof (lua_State *state)
423 grub_file_t file;
425 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
426 file = lua_touserdata (state, 1);
428 lua_pushboolean (state, file->offset >= file->size);
429 return 1;
432 static int
433 grub_lua_file_exist (lua_State *state)
435 grub_file_t file;
436 const char *name;
437 int result;
439 result = 0;
440 name = luaL_checkstring (state, 1);
441 file = grub_file_open (name);
442 if (file)
444 result++;
445 grub_file_close (file);
447 else
448 grub_errno = 0;
450 lua_pushboolean (state, result);
451 return 1;
454 static int
455 grub_lua_add_menu (lua_State *state)
457 int n;
458 const char *source;
460 source = luaL_checklstring (state, 1, 0);
461 n = lua_gettop (state) - 1;
462 if (n > 0)
464 const char *args[sizeof (char *) * n];
465 char *p;
466 int i;
468 for (i = 0; i < n; i++)
469 args[i] = luaL_checkstring (state, 2 + i);
471 p = grub_strdup (source);
472 if (! p)
473 return push_result (state);
475 grub_normal_add_menu_entry (n, args, NULL, NULL, NULL, NULL, NULL, p, 0);
477 else
479 lua_pushstring (state, "not enough parameter");
480 lua_error (state);
483 return push_result (state);
486 luaL_Reg grub_lua_lib[] =
488 {"run", grub_lua_run},
489 {"getenv", grub_lua_getenv},
490 {"setenv", grub_lua_setenv},
491 {"enum_device", grub_lua_enum_device},
492 {"enum_file", grub_lua_enum_file},
493 #ifdef ENABLE_LUA_PCI
494 {"enum_pci", grub_lua_enum_pci},
495 #endif
496 {"file_open", grub_lua_file_open},
497 {"file_close", grub_lua_file_close},
498 {"file_seek", grub_lua_file_seek},
499 {"file_read", grub_lua_file_read},
500 {"file_getline", grub_lua_file_getline},
501 {"file_getsize", grub_lua_file_getsize},
502 {"file_getpos", grub_lua_file_getpos},
503 {"file_eof", grub_lua_file_eof},
504 {"file_exist", grub_lua_file_exist},
505 {"add_menu", grub_lua_add_menu},
506 {0, 0}