Port to new grub_pci_iterate signature as of 2013-01-13, removing nested functions.
[grub-extras.git] / grub_lib.c
blob328a18d35119abfb69c464d36534516d2c35dcbc
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, &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 static int
147 grub_lua_enum_device (lua_State *state)
149 auto int enum_device (const char *name);
150 int enum_device (const char *name)
152 int result;
153 grub_device_t dev;
155 result = 0;
156 dev = grub_device_open (name);
157 if (dev)
159 grub_fs_t fs;
161 fs = grub_fs_probe (dev);
162 if (fs)
164 lua_pushvalue (state, 1);
165 lua_pushstring (state, name);
166 lua_pushstring (state, fs->name);
167 if (! fs->uuid)
168 lua_pushnil (state);
169 else
171 int err;
172 char *uuid;
174 err = fs->uuid (dev, &uuid);
175 if (err)
177 grub_errno = 0;
178 lua_pushnil (state);
180 else
182 lua_pushstring (state, uuid);
183 grub_free (uuid);
187 lua_call (state, 3, 1);
188 result = lua_tointeger (state, -1);
189 lua_pop (state, 1);
191 else
192 grub_errno = 0;
193 grub_device_close (dev);
195 else
196 grub_errno = 0;
198 return result;
201 luaL_checktype (state, 1, LUA_TFUNCTION);
202 grub_device_iterate (enum_device);
203 return push_result (state);
206 static int
207 grub_lua_enum_file (lua_State *state)
209 char *device_name;
210 const char *arg;
211 grub_device_t dev;
213 auto int enum_file (const char *name, const struct grub_dirhook_info *info);
214 int enum_file (const char *name, const struct grub_dirhook_info *info)
216 int result;
218 lua_pushvalue (state, 1);
219 lua_pushstring (state, name);
220 lua_pushinteger (state, info->dir != 0);
221 lua_call (state, 2, 1);
222 result = lua_tointeger (state, -1);
223 lua_pop (state, 1);
225 return result;
228 luaL_checktype (state, 1, LUA_TFUNCTION);
229 arg = luaL_checkstring (state, 2);
230 device_name = grub_file_get_device_name (arg);
231 dev = grub_device_open (device_name);
232 if (dev)
234 grub_fs_t fs;
235 const char *path;
237 fs = grub_fs_probe (dev);
238 path = grub_strchr (arg, ')');
239 if (! path)
240 path = arg;
241 else
242 path++;
244 if (fs)
246 (fs->dir) (dev, path, enum_file);
249 grub_device_close (dev);
252 grub_free (device_name);
254 return push_result (state);
257 #ifdef ENABLE_LUA_PCI
258 /* Helper for grub_lua_enum_pci. */
259 static int
260 grub_lua_enum_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
262 lua_State *state = data;
263 int result;
264 grub_pci_address_t addr;
265 grub_uint32_t class;
267 lua_pushvalue (state, 1);
268 lua_pushinteger (state, grub_pci_get_bus (dev));
269 lua_pushinteger (state, grub_pci_get_device (dev));
270 lua_pushinteger (state, grub_pci_get_function (dev));
271 lua_pushinteger (state, pciid);
273 addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
274 class = grub_pci_read (addr);
275 lua_pushinteger (state, class);
277 lua_call (state, 5, 1);
278 result = lua_tointeger (state, -1);
279 lua_pop (state, 1);
281 return result;
284 static int
285 grub_lua_enum_pci (lua_State *state)
287 luaL_checktype (state, 1, LUA_TFUNCTION);
288 grub_pci_iterate (grub_lua_enum_pci_iter, state);
289 return push_result (state);
291 #endif
293 static int
294 grub_lua_file_open (lua_State *state)
296 grub_file_t file;
297 const char *name;
299 name = luaL_checkstring (state, 1);
300 file = grub_file_open (name);
301 save_errno (state);
303 if (! file)
304 return 0;
306 lua_pushlightuserdata (state, file);
307 return 1;
310 static int
311 grub_lua_file_close (lua_State *state)
313 grub_file_t file;
315 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
316 file = lua_touserdata (state, 1);
317 grub_file_close (file);
319 return push_result (state);
322 static int
323 grub_lua_file_seek (lua_State *state)
325 grub_file_t file;
326 grub_off_t offset;
328 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
329 file = lua_touserdata (state, 1);
330 offset = luaL_checkinteger (state, 2);
332 offset = grub_file_seek (file, offset);
333 save_errno (state);
335 lua_pushinteger (state, offset);
336 return 1;
339 static int
340 grub_lua_file_read (lua_State *state)
342 grub_file_t file;
343 luaL_Buffer b;
344 int n;
346 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
347 file = lua_touserdata (state, 1);
348 n = luaL_checkinteger (state, 2);
350 luaL_buffinit (state, &b);
351 while (n)
353 char *p;
354 int nr;
356 nr = (n > LUAL_BUFFERSIZE) ? LUAL_BUFFERSIZE : n;
357 p = luaL_prepbuffer (&b);
359 nr = grub_file_read (file, p, nr);
360 if (nr <= 0)
361 break;
363 luaL_addsize (&b, nr);
364 n -= nr;
367 save_errno (state);
368 luaL_pushresult (&b);
369 return 1;
372 static int
373 grub_lua_file_getline (lua_State *state)
375 grub_file_t file;
376 char *line;
378 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
379 file = lua_touserdata (state, 1);
381 line = grub_file_getline (file);
382 save_errno (state);
384 if (! line)
385 return 0;
387 lua_pushstring (state, line);
388 grub_free (line);
389 return 1;
392 static int
393 grub_lua_file_getsize (lua_State *state)
395 grub_file_t file;
397 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
398 file = lua_touserdata (state, 1);
400 lua_pushinteger (state, file->size);
401 return 1;
404 static int
405 grub_lua_file_getpos (lua_State *state)
407 grub_file_t file;
409 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
410 file = lua_touserdata (state, 1);
412 lua_pushinteger (state, file->offset);
413 return 1;
416 static int
417 grub_lua_file_eof (lua_State *state)
419 grub_file_t file;
421 luaL_checktype (state, 1, LUA_TLIGHTUSERDATA);
422 file = lua_touserdata (state, 1);
424 lua_pushboolean (state, file->offset >= file->size);
425 return 1;
428 static int
429 grub_lua_file_exist (lua_State *state)
431 grub_file_t file;
432 const char *name;
433 int result;
435 result = 0;
436 name = luaL_checkstring (state, 1);
437 file = grub_file_open (name);
438 if (file)
440 result++;
441 grub_file_close (file);
443 else
444 grub_errno = 0;
446 lua_pushboolean (state, result);
447 return 1;
450 static int
451 grub_lua_add_menu (lua_State *state)
453 int n;
454 const char *source;
456 source = luaL_checklstring (state, 1, 0);
457 n = lua_gettop (state) - 1;
458 if (n > 0)
460 const char *args[sizeof (char *) * n];
461 char *p;
462 int i;
464 for (i = 0; i < n; i++)
465 args[i] = luaL_checkstring (state, 2 + i);
467 p = grub_strdup (source);
468 if (! p)
469 return push_result (state);
471 grub_normal_add_menu_entry (n, args, NULL, NULL, NULL, NULL, NULL, p, 0);
473 else
475 lua_pushstring (state, "not enough parameter");
476 lua_error (state);
479 return push_result (state);
482 luaL_Reg grub_lua_lib[] =
484 {"run", grub_lua_run},
485 {"getenv", grub_lua_getenv},
486 {"setenv", grub_lua_setenv},
487 {"enum_device", grub_lua_enum_device},
488 {"enum_file", grub_lua_enum_file},
489 #ifdef ENABLE_LUA_PCI
490 {"enum_pci", grub_lua_enum_pci},
491 #endif
492 {"file_open", grub_lua_file_open},
493 {"file_close", grub_lua_file_close},
494 {"file_seek", grub_lua_file_seek},
495 {"file_read", grub_lua_file_read},
496 {"file_getline", grub_lua_file_getline},
497 {"file_getsize", grub_lua_file_getsize},
498 {"file_getpos", grub_lua_file_getpos},
499 {"file_eof", grub_lua_file_eof},
500 {"file_exist", grub_lua_file_exist},
501 {"add_menu", grub_lua_add_menu},
502 {0, 0}