uci.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. /*
  2. * libuci plugin for Lua
  3. * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2
  7. * as published by the Free Software Foundation
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <sys/types.h>
  15. #include <sys/time.h>
  16. #include <stdbool.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <unistd.h>
  20. #include <stdio.h>
  21. #include <errno.h>
  22. #include <lauxlib.h>
  23. #include <uci.h>
  24. #define MODNAME "uci"
  25. #define METANAME MODNAME ".meta"
  26. //#define DEBUG 1
  27. #ifdef DEBUG
  28. #define DPRINTF(...) fprintf(stderr, __VA_ARGS__)
  29. #else
  30. #define DPRINTF(...) do {} while (0)
  31. #endif
  32. static struct uci_context *global_ctx = NULL;
  33. static struct uci_context *
  34. find_context(lua_State *L, int *offset)
  35. {
  36. struct uci_context **ctx;
  37. if (!lua_isuserdata(L, 1)) {
  38. if (!global_ctx) {
  39. global_ctx = uci_alloc_context();
  40. if (!global_ctx) {
  41. luaL_error(L, "failed to allocate UCI context");
  42. return NULL;
  43. }
  44. }
  45. if (offset)
  46. *offset = 0;
  47. return global_ctx;
  48. }
  49. if (offset)
  50. *offset = 1;
  51. ctx = luaL_checkudata(L, 1, METANAME);
  52. if (!ctx || !*ctx) {
  53. luaL_error(L, "failed to get UCI context");
  54. return NULL;
  55. }
  56. return *ctx;
  57. }
  58. static struct uci_package *
  59. find_package(lua_State *L, struct uci_context *ctx, const char *str, bool al)
  60. {
  61. struct uci_package *p = NULL;
  62. struct uci_element *e;
  63. char *sep;
  64. char *name;
  65. sep = strchr(str, '.');
  66. if (sep) {
  67. name = malloc(1 + sep - str);
  68. if (!name) {
  69. luaL_error(L, "out of memory");
  70. return NULL;
  71. }
  72. strncpy(name, str, sep - str);
  73. name[sep - str] = 0;
  74. } else
  75. name = (char *) str;
  76. uci_foreach_element(&ctx->root, e) {
  77. if (strcmp(e->name, name) != 0)
  78. continue;
  79. p = uci_to_package(e);
  80. goto done;
  81. }
  82. if (al == true)
  83. uci_load(ctx, name, &p);
  84. else if (al) {
  85. uci_load(ctx, name, &p);
  86. }
  87. done:
  88. if (name != str)
  89. free(name);
  90. return p;
  91. }
  92. static int
  93. lookup_args(lua_State *L, struct uci_context *ctx, int offset, struct uci_ptr *ptr, char **buf)
  94. {
  95. char *s = NULL;
  96. int n;
  97. n = lua_gettop(L);
  98. luaL_checkstring(L, 1 + offset);
  99. s = strdup(lua_tostring(L, 1 + offset));
  100. if (!s)
  101. goto error;
  102. memset(ptr, 0, sizeof(struct uci_ptr));
  103. if (!find_package(L, ctx, s, true))
  104. goto error;
  105. switch (n - offset) {
  106. case 4:
  107. case 3:
  108. ptr->option = luaL_checkstring(L, 3 + offset);
  109. /* fall through */
  110. case 2:
  111. ptr->section = luaL_checkstring(L, 2 + offset);
  112. ptr->package = luaL_checkstring(L, 1 + offset);
  113. if (uci_lookup_ptr(ctx, ptr, NULL, true) != UCI_OK)
  114. goto error;
  115. break;
  116. case 1:
  117. if (uci_lookup_ptr(ctx, ptr, s, true) != UCI_OK)
  118. goto error;
  119. break;
  120. default:
  121. luaL_error(L, "invalid argument count");
  122. goto error;
  123. }
  124. *buf = s;
  125. return 0;
  126. error:
  127. if (s)
  128. free(s);
  129. return 1;
  130. }
  131. static int
  132. uci_push_status(lua_State *L, struct uci_context *ctx, bool hasarg)
  133. {
  134. char *str = NULL;
  135. if (!hasarg)
  136. lua_pushboolean(L, (ctx->err == UCI_OK));
  137. if (ctx->err) {
  138. uci_get_errorstr(ctx, &str, MODNAME);
  139. if (str) {
  140. lua_pushstring(L, str);
  141. free(str);
  142. return 2;
  143. }
  144. }
  145. return 1;
  146. }
  147. static void
  148. uci_push_option(lua_State *L, struct uci_option *o)
  149. {
  150. struct uci_element *e;
  151. int i = 0;
  152. switch(o->type) {
  153. case UCI_TYPE_STRING:
  154. lua_pushstring(L, o->v.string);
  155. break;
  156. case UCI_TYPE_LIST:
  157. lua_newtable(L);
  158. uci_foreach_element(&o->v.list, e) {
  159. i++;
  160. lua_pushstring(L, e->name);
  161. lua_rawseti(L, -2, i);
  162. }
  163. break;
  164. default:
  165. lua_pushnil(L);
  166. break;
  167. }
  168. }
  169. static void
  170. uci_push_section(lua_State *L, struct uci_section *s, int index)
  171. {
  172. struct uci_element *e;
  173. lua_newtable(L);
  174. lua_pushboolean(L, s->anonymous);
  175. lua_setfield(L, -2, ".anonymous");
  176. lua_pushstring(L, s->type);
  177. lua_setfield(L, -2, ".type");
  178. lua_pushstring(L, s->e.name);
  179. lua_setfield(L, -2, ".name");
  180. if (index >= 0) {
  181. lua_pushinteger(L, index);
  182. lua_setfield(L, -2, ".index");
  183. }
  184. uci_foreach_element(&s->options, e) {
  185. struct uci_option *o = uci_to_option(e);
  186. uci_push_option(L, o);
  187. lua_setfield(L, -2, o->e.name);
  188. }
  189. }
  190. static void
  191. uci_push_package(lua_State *L, struct uci_package *p)
  192. {
  193. struct uci_element *e;
  194. int i = 0;
  195. lua_newtable(L);
  196. uci_foreach_element(&p->sections, e) {
  197. uci_push_section(L, uci_to_section(e), i);
  198. lua_setfield(L, -2, e->name);
  199. i++;
  200. }
  201. }
  202. static int
  203. uci_lua_unload(lua_State *L)
  204. {
  205. struct uci_context *ctx;
  206. struct uci_package *p;
  207. const char *s;
  208. int offset = 0;
  209. ctx = find_context(L, &offset);
  210. luaL_checkstring(L, 1 + offset);
  211. s = lua_tostring(L, 1 + offset);
  212. p = find_package(L, ctx, s, false);
  213. if (p) {
  214. uci_unload(ctx, p);
  215. return uci_push_status(L, ctx, false);
  216. } else {
  217. lua_pushboolean(L, 0);
  218. }
  219. return 1;
  220. }
  221. static int
  222. uci_lua_load(lua_State *L)
  223. {
  224. struct uci_context *ctx;
  225. struct uci_package *p = NULL;
  226. const char *s;
  227. int offset = 0;
  228. ctx = find_context(L, &offset);
  229. uci_lua_unload(L);
  230. lua_pop(L, 1); /* bool ret value of unload */
  231. s = lua_tostring(L, -1);
  232. uci_load(ctx, s, &p);
  233. return uci_push_status(L, ctx, false);
  234. }
  235. static int
  236. uci_lua_foreach(lua_State *L)
  237. {
  238. struct uci_context *ctx;
  239. struct uci_package *p;
  240. struct uci_element *e, *tmp;
  241. const char *package, *type;
  242. bool ret = false;
  243. int offset = 0;
  244. int i = 0;
  245. ctx = find_context(L, &offset);
  246. package = luaL_checkstring(L, 1 + offset);
  247. if (lua_isnil(L, 2))
  248. type = NULL;
  249. else
  250. type = luaL_checkstring(L, 2 + offset);
  251. if (!lua_isfunction(L, 3 + offset) || !package)
  252. return luaL_error(L, "Invalid argument");
  253. p = find_package(L, ctx, package, true);
  254. if (!p)
  255. goto done;
  256. uci_foreach_element_safe(&p->sections, tmp, e) {
  257. struct uci_section *s = uci_to_section(e);
  258. i++;
  259. if (type && (strcmp(s->type, type) != 0))
  260. continue;
  261. lua_pushvalue(L, 3 + offset); /* iterator function */
  262. uci_push_section(L, s, i - 1);
  263. if (lua_pcall(L, 1, 1, 0) == 0) {
  264. ret = true;
  265. if (lua_isboolean(L, -1) && !lua_toboolean(L, -1))
  266. break;
  267. }
  268. else
  269. {
  270. lua_error(L);
  271. break;
  272. }
  273. }
  274. done:
  275. lua_pushboolean(L, ret);
  276. return 1;
  277. }
  278. static int
  279. uci_lua_get_any(lua_State *L, bool all)
  280. {
  281. struct uci_context *ctx;
  282. struct uci_element *e = NULL;
  283. struct uci_ptr ptr;
  284. int offset = 0;
  285. char *s = NULL;
  286. int err = UCI_ERR_NOTFOUND;
  287. ctx = find_context(L, &offset);
  288. if (lookup_args(L, ctx, offset, &ptr, &s))
  289. goto error;
  290. uci_lookup_ptr(ctx, &ptr, NULL, true);
  291. if (!all && !ptr.s) {
  292. err = UCI_ERR_INVAL;
  293. goto error;
  294. }
  295. if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
  296. err = UCI_ERR_NOTFOUND;
  297. goto error;
  298. }
  299. err = UCI_OK;
  300. e = ptr.last;
  301. switch(e->type) {
  302. case UCI_TYPE_PACKAGE:
  303. uci_push_package(L, ptr.p);
  304. break;
  305. case UCI_TYPE_SECTION:
  306. if (all)
  307. uci_push_section(L, ptr.s, -1);
  308. else
  309. lua_pushstring(L, ptr.s->type);
  310. break;
  311. case UCI_TYPE_OPTION:
  312. uci_push_option(L, ptr.o);
  313. break;
  314. default:
  315. err = UCI_ERR_INVAL;
  316. goto error;
  317. }
  318. if (!err)
  319. return 1;
  320. error:
  321. if (s)
  322. free(s);
  323. lua_pushnil(L);
  324. return uci_push_status(L, ctx, true);
  325. }
  326. static int
  327. uci_lua_get(lua_State *L)
  328. {
  329. return uci_lua_get_any(L, false);
  330. }
  331. static int
  332. uci_lua_get_all(lua_State *L)
  333. {
  334. return uci_lua_get_any(L, true);
  335. }
  336. static int
  337. uci_lua_add(lua_State *L)
  338. {
  339. struct uci_context *ctx;
  340. struct uci_section *s = NULL;
  341. struct uci_package *p;
  342. const char *package;
  343. const char *type;
  344. const char *name = NULL;
  345. int offset = 0;
  346. ctx = find_context(L, &offset);
  347. package = luaL_checkstring(L, 1 + offset);
  348. type = luaL_checkstring(L, 2 + offset);
  349. p = find_package(L, ctx, package, true);
  350. if (!p)
  351. goto fail;
  352. if (uci_add_section(ctx, p, type, &s) || !s)
  353. goto fail;
  354. name = s->e.name;
  355. lua_pushstring(L, name);
  356. return 1;
  357. fail:
  358. lua_pushnil(L);
  359. return uci_push_status(L, ctx, true);
  360. }
  361. static int
  362. uci_lua_delete(lua_State *L)
  363. {
  364. struct uci_context *ctx;
  365. struct uci_ptr ptr;
  366. int offset = 0;
  367. char *s = NULL;
  368. ctx = find_context(L, &offset);
  369. if (lookup_args(L, ctx, offset, &ptr, &s))
  370. goto error;
  371. uci_delete(ctx, &ptr);
  372. error:
  373. if (s)
  374. free(s);
  375. return uci_push_status(L, ctx, false);
  376. }
  377. static int
  378. uci_lua_rename(lua_State *L)
  379. {
  380. struct uci_context *ctx;
  381. struct uci_ptr ptr;
  382. int err = UCI_ERR_MEM;
  383. char *s = NULL;
  384. int nargs, offset = 0;
  385. ctx = find_context(L, &offset);
  386. nargs = lua_gettop(L);
  387. if (lookup_args(L, ctx, offset, &ptr, &s))
  388. goto error;
  389. switch(nargs - offset) {
  390. case 1:
  391. /* Format: uci.set("p.s.o=v") or uci.set("p.s=v") */
  392. break;
  393. case 4:
  394. /* Format: uci.set("p", "s", "o", "v") */
  395. ptr.value = luaL_checkstring(L, nargs);
  396. break;
  397. case 3:
  398. /* Format: uci.set("p", "s", "v") */
  399. ptr.value = ptr.option;
  400. ptr.option = NULL;
  401. break;
  402. default:
  403. err = UCI_ERR_INVAL;
  404. goto error;
  405. }
  406. err = uci_lookup_ptr(ctx, &ptr, NULL, true);
  407. if (err)
  408. goto error;
  409. if (((ptr.s == NULL) && (ptr.option != NULL)) || (ptr.value == NULL)) {
  410. err = UCI_ERR_INVAL;
  411. goto error;
  412. }
  413. err = uci_rename(ctx, &ptr);
  414. if (err)
  415. goto error;
  416. error:
  417. return uci_push_status(L, ctx, false);
  418. }
  419. static int
  420. uci_lua_reorder(lua_State *L)
  421. {
  422. struct uci_context *ctx;
  423. struct uci_ptr ptr;
  424. int err = UCI_ERR_MEM;
  425. char *s = NULL;
  426. int nargs, offset = 0;
  427. ctx = find_context(L, &offset);
  428. nargs = lua_gettop(L);
  429. if (lookup_args(L, ctx, offset, &ptr, &s))
  430. goto error;
  431. switch(nargs - offset) {
  432. case 1:
  433. /* Format: uci.set("p.s=v") or uci.set("p.s=v") */
  434. if (ptr.option) {
  435. err = UCI_ERR_INVAL;
  436. goto error;
  437. }
  438. break;
  439. case 3:
  440. /* Format: uci.set("p", "s", "v") */
  441. ptr.value = ptr.option;
  442. ptr.option = NULL;
  443. break;
  444. default:
  445. err = UCI_ERR_INVAL;
  446. goto error;
  447. }
  448. err = uci_lookup_ptr(ctx, &ptr, NULL, true);
  449. if (err)
  450. goto error;
  451. if ((ptr.s == NULL) || (ptr.value == NULL)) {
  452. err = UCI_ERR_INVAL;
  453. goto error;
  454. }
  455. err = uci_reorder_section(ctx, ptr.s, strtoul(ptr.value, NULL, 10));
  456. if (err)
  457. goto error;
  458. error:
  459. return uci_push_status(L, ctx, false);
  460. }
  461. static int
  462. uci_lua_set(lua_State *L)
  463. {
  464. struct uci_context *ctx;
  465. struct uci_ptr ptr;
  466. bool istable = false;
  467. int err = UCI_ERR_MEM;
  468. char *s = NULL;
  469. int i, nargs, offset = 0;
  470. ctx = find_context(L, &offset);
  471. nargs = lua_gettop(L);
  472. if (lookup_args(L, ctx, offset, &ptr, &s))
  473. goto error;
  474. switch(nargs - offset) {
  475. case 1:
  476. /* Format: uci.set("p.s.o=v") or uci.set("p.s=v") */
  477. break;
  478. case 4:
  479. /* Format: uci.set("p", "s", "o", "v") */
  480. if (lua_istable(L, nargs)) {
  481. if (lua_objlen(L, nargs) < 1)
  482. return luaL_error(L, "Cannot set an uci option to an empty table value");
  483. lua_rawgeti(L, nargs, 1);
  484. ptr.value = luaL_checkstring(L, -1);
  485. lua_pop(L, 1);
  486. istable = true;
  487. } else {
  488. ptr.value = luaL_checkstring(L, nargs);
  489. }
  490. break;
  491. case 3:
  492. /* Format: uci.set("p", "s", "v") */
  493. ptr.value = ptr.option;
  494. ptr.option = NULL;
  495. break;
  496. default:
  497. err = UCI_ERR_INVAL;
  498. goto error;
  499. }
  500. err = uci_lookup_ptr(ctx, &ptr, NULL, true);
  501. if (err)
  502. goto error;
  503. if (((ptr.s == NULL) && (ptr.option != NULL)) || (ptr.value == NULL)) {
  504. err = UCI_ERR_INVAL;
  505. goto error;
  506. }
  507. if (istable) {
  508. if (lua_objlen(L, nargs) == 1) {
  509. i = 1;
  510. if (ptr.o)
  511. err = uci_delete(ctx, &ptr);
  512. } else {
  513. i = 2;
  514. err = uci_set(ctx, &ptr);
  515. if (err)
  516. goto error;
  517. }
  518. for (; i <= lua_objlen(L, nargs); i++) {
  519. lua_rawgeti(L, nargs, i);
  520. ptr.value = luaL_checkstring(L, -1);
  521. err = uci_add_list(ctx, &ptr);
  522. lua_pop(L, 1);
  523. if (err)
  524. goto error;
  525. }
  526. } else {
  527. err = uci_set(ctx, &ptr);
  528. if (err)
  529. goto error;
  530. }
  531. error:
  532. return uci_push_status(L, ctx, false);
  533. }
  534. enum pkg_cmd {
  535. CMD_SAVE,
  536. CMD_COMMIT,
  537. CMD_REVERT
  538. };
  539. static int
  540. uci_lua_package_cmd(lua_State *L, enum pkg_cmd cmd)
  541. {
  542. struct uci_context *ctx;
  543. struct uci_element *e, *tmp;
  544. struct uci_ptr ptr;
  545. char *s = NULL;
  546. int nargs, offset = 0;
  547. ctx = find_context(L, &offset);
  548. nargs = lua_gettop(L);
  549. if ((cmd != CMD_REVERT) && (nargs - offset > 1))
  550. goto err;
  551. if (lookup_args(L, ctx, offset, &ptr, &s))
  552. goto err;
  553. uci_lookup_ptr(ctx, &ptr, NULL, true);
  554. uci_foreach_element_safe(&ctx->root, tmp, e) {
  555. struct uci_package *p = uci_to_package(e);
  556. if (ptr.p && (ptr.p != p))
  557. continue;
  558. ptr.p = p;
  559. switch(cmd) {
  560. case CMD_COMMIT:
  561. uci_commit(ctx, &p, false);
  562. break;
  563. case CMD_SAVE:
  564. uci_save(ctx, p);
  565. break;
  566. case CMD_REVERT:
  567. uci_revert(ctx, &ptr);
  568. break;
  569. }
  570. }
  571. err:
  572. return uci_push_status(L, ctx, false);
  573. }
  574. static int
  575. uci_lua_save(lua_State *L)
  576. {
  577. return uci_lua_package_cmd(L, CMD_SAVE);
  578. }
  579. static int
  580. uci_lua_commit(lua_State *L)
  581. {
  582. return uci_lua_package_cmd(L, CMD_COMMIT);
  583. }
  584. static int
  585. uci_lua_revert(lua_State *L)
  586. {
  587. return uci_lua_package_cmd(L, CMD_REVERT);
  588. }
  589. static void
  590. uci_lua_add_change(lua_State *L, struct uci_element *e)
  591. {
  592. struct uci_delta *h;
  593. const char *name;
  594. const char *value;
  595. h = uci_to_delta(e);
  596. if (!h->section)
  597. return;
  598. lua_getfield(L, -1, h->section);
  599. if (lua_isnil(L, -1)) {
  600. lua_pop(L, 1);
  601. lua_newtable(L);
  602. lua_pushvalue(L, -1); /* copy for setfield */
  603. lua_setfield(L, -3, h->section);
  604. }
  605. name = h->e.name;
  606. value = h->value ? h->value : "";
  607. if (name) {
  608. lua_getfield(L, -1, name);
  609. /* this delta is a list add operation */
  610. if (h->cmd == UCI_CMD_LIST_ADD) {
  611. /* there seems to be no table yet */
  612. if (!lua_istable(L, -1)) {
  613. lua_newtable(L);
  614. /* if there is a value on the stack already, add */
  615. if (!lua_isnil(L, -2)) {
  616. lua_pushvalue(L, -2);
  617. lua_rawseti(L, -2, 1);
  618. lua_pushstring(L, value);
  619. lua_rawseti(L, -2, 2);
  620. /* this is the first table item */
  621. } else {
  622. lua_pushstring(L, value);
  623. lua_rawseti(L, -2, 1);
  624. }
  625. lua_setfield(L, -3, name);
  626. /* a table is on the top of the stack and this is a subsequent,
  627. * list_add, append this value to table */
  628. } else {
  629. lua_pushstring(L, value);
  630. lua_rawseti(L, -2, lua_objlen(L, -2) + 1);
  631. }
  632. /* non-list change, simply set/replace field */
  633. } else {
  634. lua_pushstring(L, value);
  635. lua_setfield(L, -3, name);
  636. }
  637. lua_pop(L, 1);
  638. } else {
  639. lua_pushstring(L, value);
  640. lua_setfield(L, -2, ".type");
  641. }
  642. lua_pop(L, 1);
  643. }
  644. static void
  645. uci_lua_changes_pkg(lua_State *L, struct uci_context *ctx, const char *package)
  646. {
  647. struct uci_package *p = NULL;
  648. struct uci_element *e;
  649. bool autoload = false;
  650. p = find_package(L, ctx, package, false);
  651. if (!p) {
  652. autoload = true;
  653. p = find_package(L, ctx, package, true);
  654. if (!p)
  655. return;
  656. }
  657. if (uci_list_empty(&p->delta) && uci_list_empty(&p->saved_delta))
  658. goto done;
  659. lua_newtable(L);
  660. uci_foreach_element(&p->saved_delta, e) {
  661. uci_lua_add_change(L, e);
  662. }
  663. uci_foreach_element(&p->delta, e) {
  664. uci_lua_add_change(L, e);
  665. }
  666. lua_setfield(L, -2, p->e.name);
  667. done:
  668. if (autoload)
  669. uci_unload(ctx, p);
  670. }
  671. static int
  672. uci_lua_changes(lua_State *L)
  673. {
  674. struct uci_context *ctx;
  675. const char *package = NULL;
  676. char **config = NULL;
  677. int nargs;
  678. int i, offset = 0;
  679. ctx = find_context(L, &offset);
  680. nargs = lua_gettop(L);
  681. switch(nargs - offset) {
  682. case 1:
  683. package = luaL_checkstring(L, 1 + offset);
  684. case 0:
  685. break;
  686. default:
  687. return luaL_error(L, "invalid argument count");
  688. }
  689. lua_newtable(L);
  690. if (package) {
  691. uci_lua_changes_pkg(L, ctx, package);
  692. } else {
  693. if (uci_list_configs(ctx, &config) != 0)
  694. goto done;
  695. for(i = 0; config[i] != NULL; i++) {
  696. uci_lua_changes_pkg(L, ctx, config[i]);
  697. }
  698. }
  699. done:
  700. return 1;
  701. }
  702. static int
  703. uci_lua_get_confdir(lua_State *L)
  704. {
  705. struct uci_context *ctx = find_context(L, NULL);
  706. lua_pushstring(L, ctx->confdir);
  707. return 1;
  708. }
  709. static int
  710. uci_lua_set_confdir(lua_State *L)
  711. {
  712. struct uci_context *ctx;
  713. int offset = 0;
  714. ctx = find_context(L, &offset);
  715. luaL_checkstring(L, 1 + offset);
  716. uci_set_confdir(ctx, lua_tostring(L, -1));
  717. return uci_push_status(L, ctx, false);
  718. }
  719. static int
  720. uci_lua_get_savedir(lua_State *L)
  721. {
  722. struct uci_context *ctx = find_context(L, NULL);
  723. lua_pushstring(L, ctx->savedir);
  724. return 1;
  725. }
  726. static int
  727. uci_lua_add_delta(lua_State *L)
  728. {
  729. struct uci_context *ctx;
  730. int offset = 0;
  731. ctx = find_context(L, &offset);
  732. luaL_checkstring(L, 1 + offset);
  733. uci_add_delta_path(ctx, lua_tostring(L, -1));
  734. return uci_push_status(L, ctx, false);
  735. }
  736. static int
  737. uci_lua_set_savedir(lua_State *L)
  738. {
  739. struct uci_context *ctx;
  740. int offset = 0;
  741. ctx = find_context(L, &offset);
  742. luaL_checkstring(L, 1 + offset);
  743. uci_set_savedir(ctx, lua_tostring(L, -1));
  744. return uci_push_status(L, ctx, false);
  745. }
  746. static int
  747. uci_lua_gc(lua_State *L)
  748. {
  749. struct uci_context *ctx = find_context(L, NULL);
  750. uci_free_context(ctx);
  751. return 0;
  752. }
  753. static int
  754. uci_lua_cursor(lua_State *L)
  755. {
  756. struct uci_context **u;
  757. int argc = lua_gettop(L);
  758. u = lua_newuserdata(L, sizeof(struct uci_context *));
  759. luaL_getmetatable(L, METANAME);
  760. lua_setmetatable(L, -2);
  761. *u = uci_alloc_context();
  762. if (!*u)
  763. return luaL_error(L, "Cannot allocate UCI context");
  764. switch (argc) {
  765. case 2:
  766. if (lua_isstring(L, 2) &&
  767. (uci_set_savedir(*u, luaL_checkstring(L, 2)) != UCI_OK))
  768. return luaL_error(L, "Unable to set savedir");
  769. /* fall through */
  770. case 1:
  771. if (lua_isstring(L, 1) &&
  772. (uci_set_confdir(*u, luaL_checkstring(L, 1)) != UCI_OK))
  773. return luaL_error(L, "Unable to set savedir");
  774. break;
  775. default:
  776. break;
  777. }
  778. return 1;
  779. }
  780. static const luaL_Reg uci[] = {
  781. { "__gc", uci_lua_gc },
  782. { "cursor", uci_lua_cursor },
  783. { "load", uci_lua_load },
  784. { "unload", uci_lua_unload },
  785. { "get", uci_lua_get },
  786. { "get_all", uci_lua_get_all },
  787. { "add", uci_lua_add },
  788. { "set", uci_lua_set },
  789. { "rename", uci_lua_rename },
  790. { "save", uci_lua_save },
  791. { "delete", uci_lua_delete },
  792. { "commit", uci_lua_commit },
  793. { "revert", uci_lua_revert },
  794. { "reorder", uci_lua_reorder },
  795. { "changes", uci_lua_changes },
  796. { "foreach", uci_lua_foreach },
  797. { "add_history", uci_lua_add_delta },
  798. { "add_delta", uci_lua_add_delta },
  799. { "get_confdir", uci_lua_get_confdir },
  800. { "set_confdir", uci_lua_set_confdir },
  801. { "get_savedir", uci_lua_get_savedir },
  802. { "set_savedir", uci_lua_set_savedir },
  803. { NULL, NULL },
  804. };
  805. int
  806. luaopen_uci(lua_State *L)
  807. {
  808. /* create metatable */
  809. luaL_newmetatable(L, METANAME);
  810. /* metatable.__index = metatable */
  811. lua_pushvalue(L, -1);
  812. lua_setfield(L, -2, "__index");
  813. /* fill metatable */
  814. luaL_register(L, NULL, uci);
  815. lua_pop(L, 1);
  816. /* create module */
  817. luaL_register(L, MODNAME, uci);
  818. return 0;
  819. }