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 15 #include <sys/types.h> 16 #include <sys/time.h> 17 #include <stdbool.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unistd.h> 21 #include <stdio.h> 22 #include <errno.h> 23 24 #include <lauxlib.h> 25 #include <uci.h> 26 27 #define MODNAME "uci" 28 #define METANAME MODNAME ".meta" 29 //#define DEBUG 1 30 31 #ifdef DEBUG 32 #define DPRINTF(...) fprintf(stderr, __VA_ARGS__) 33 #else 34 #define DPRINTF(...) do {} while (0) 35 #endif 36 37 #if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 38 39 int luaopen_uci(lua_State *L); 40 41 /* 42 * ** Adapted from Lua 5.2.0 43 * */ 44 static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { 45 luaL_checkstack(L, nup+1, "too many upvalues"); 46 for (; l->name != NULL; l++) { /* fill the table with given functions */ 47 int i; 48 lua_pushstring(L, l->name); 49 for (i = 0; i < nup; i++) /* copy upvalues to the top */ 50 lua_pushvalue(L, -(nup+1)); 51 lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ 52 lua_settable(L, -(nup + 3)); 53 } 54 lua_pop(L, nup); /* remove upvalues */ 55 } 56 57 #define lua_rawlen(L, i) lua_objlen(L, i) 58 59 #endif 60 61 static struct uci_context *global_ctx = NULL; 62 63 static struct uci_context * 64 find_context(lua_State *L, int *offset) 65 { 66 struct uci_context **ctx; 67 if (!lua_isuserdata(L, 1)) { 68 if (!global_ctx) { 69 global_ctx = uci_alloc_context(); 70 if (!global_ctx) { 71 luaL_error(L, "failed to allocate UCI context"); 72 return NULL; 73 } 74 } 75 if (offset) 76 *offset = 0; 77 return global_ctx; 78 } 79 if (offset) 80 *offset = 1; 81 ctx = luaL_checkudata(L, 1, METANAME); 82 if (!ctx || !*ctx) { 83 luaL_error(L, "failed to get UCI context"); 84 return NULL; 85 } 86 87 return *ctx; 88 } 89 90 static struct uci_package * 91 find_package(lua_State *L, struct uci_context *ctx, const char *str, bool al) 92 { 93 struct uci_package *p = NULL; 94 struct uci_element *e; 95 char *sep; 96 char *name; 97 98 sep = strchr(str, '.'); 99 if (sep) { 100 name = malloc(1 + sep - str); 101 if (!name) { 102 luaL_error(L, "out of memory"); 103 return NULL; 104 } 105 strncpy(name, str, sep - str); 106 name[sep - str] = 0; 107 } else 108 name = (char *) str; 109 110 uci_foreach_element(&ctx->root, e) { 111 if (strcmp(e->name, name) != 0) 112 continue; 113 114 p = uci_to_package(e); 115 goto done; 116 } 117 118 if (al) 119 uci_load(ctx, name, &p); 120 121 done: 122 if (name != str) 123 free(name); 124 return p; 125 } 126 127 static int 128 lookup_extended(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended) 129 { 130 int rv; 131 struct uci_ptr lookup; 132 133 /* use a copy of the passed ptr since failing lookups will 134 * clobber the state */ 135 lookup = *ptr; 136 lookup.flags |= UCI_LOOKUP_EXTENDED; 137 138 rv = uci_lookup_ptr(ctx, &lookup, str, extended); 139 140 /* copy to passed ptr on success */ 141 if (!rv) 142 *ptr = lookup; 143 144 return rv; 145 } 146 147 static int 148 lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended) 149 { 150 if (ptr && !ptr->s && ptr->section && *ptr->section == '@') 151 return lookup_extended(ctx, ptr, str, extended); 152 153 return uci_lookup_ptr(ctx, ptr, str, extended); 154 } 155 156 static int 157 lookup_args(lua_State *L, struct uci_context *ctx, int offset, struct uci_ptr *ptr, char **buf) 158 { 159 char *s = NULL; 160 int n; 161 162 n = lua_gettop(L); 163 luaL_checkstring(L, 1 + offset); 164 s = strdup(lua_tostring(L, 1 + offset)); 165 if (!s) 166 goto error; 167 168 memset(ptr, 0, sizeof(struct uci_ptr)); 169 if (!find_package(L, ctx, s, true)) 170 goto error; 171 172 switch (n - offset) { 173 case 4: 174 case 3: 175 ptr->option = luaL_checkstring(L, 3 + offset); 176 /* fall through */ 177 case 2: 178 ptr->section = luaL_checkstring(L, 2 + offset); 179 ptr->package = luaL_checkstring(L, 1 + offset); 180 if (lookup_ptr(ctx, ptr, NULL, true) != UCI_OK) 181 goto error; 182 break; 183 case 1: 184 if (lookup_ptr(ctx, ptr, s, true) != UCI_OK) 185 goto error; 186 break; 187 default: 188 luaL_error(L, "invalid argument count"); 189 goto error; 190 } 191 192 *buf = s; 193 return 0; 194 195 error: 196 if (s) 197 free(s); 198 return 1; 199 } 200 201 static int 202 uci_push_status(lua_State *L, struct uci_context *ctx, bool hasarg) 203 { 204 char *str = NULL; 205 206 if (!hasarg) 207 lua_pushboolean(L, (ctx->err == UCI_OK)); 208 if (ctx->err) { 209 uci_get_errorstr(ctx, &str, MODNAME); 210 if (str) { 211 lua_pushstring(L, str); 212 free(str); 213 return 2; 214 } 215 } 216 return 1; 217 } 218 219 static void 220 uci_push_option(lua_State *L, struct uci_option *o) 221 { 222 struct uci_element *e; 223 int i = 0; 224 225 switch(o->type) { 226 case UCI_TYPE_STRING: 227 lua_pushstring(L, o->v.string); 228 break; 229 case UCI_TYPE_LIST: 230 lua_newtable(L); 231 uci_foreach_element(&o->v.list, e) { 232 i++; 233 lua_pushstring(L, e->name); 234 lua_rawseti(L, -2, i); 235 } 236 break; 237 default: 238 lua_pushnil(L); 239 break; 240 } 241 } 242 243 static void 244 uci_push_section(lua_State *L, struct uci_section *s, int index) 245 { 246 struct uci_element *e; 247 248 lua_newtable(L); 249 lua_pushboolean(L, s->anonymous); 250 lua_setfield(L, -2, ".anonymous"); 251 lua_pushstring(L, s->type); 252 lua_setfield(L, -2, ".type"); 253 lua_pushstring(L, s->e.name); 254 lua_setfield(L, -2, ".name"); 255 if (index >= 0) { 256 lua_pushinteger(L, index); 257 lua_setfield(L, -2, ".index"); 258 } 259 260 uci_foreach_element(&s->options, e) { 261 struct uci_option *o = uci_to_option(e); 262 uci_push_option(L, o); 263 lua_setfield(L, -2, o->e.name); 264 } 265 } 266 267 static void 268 uci_push_package(lua_State *L, struct uci_package *p) 269 { 270 struct uci_element *e; 271 int i = 0; 272 273 lua_newtable(L); 274 uci_foreach_element(&p->sections, e) { 275 uci_push_section(L, uci_to_section(e), i); 276 lua_setfield(L, -2, e->name); 277 i++; 278 } 279 } 280 281 static int 282 uci_lua_unload(lua_State *L) 283 { 284 struct uci_context *ctx; 285 struct uci_package *p; 286 const char *s; 287 int offset = 0; 288 289 ctx = find_context(L, &offset); 290 luaL_checkstring(L, 1 + offset); 291 s = lua_tostring(L, 1 + offset); 292 p = find_package(L, ctx, s, false); 293 if (p) { 294 uci_unload(ctx, p); 295 return uci_push_status(L, ctx, false); 296 } else { 297 lua_pushboolean(L, 0); 298 } 299 return 1; 300 } 301 302 static int 303 uci_lua_load(lua_State *L) 304 { 305 struct uci_context *ctx; 306 struct uci_package *p = NULL; 307 const char *s; 308 int offset = 0; 309 310 ctx = find_context(L, &offset); 311 uci_lua_unload(L); 312 lua_pop(L, 1); /* bool ret value of unload */ 313 s = lua_tostring(L, -1); 314 315 uci_load(ctx, s, &p); 316 return uci_push_status(L, ctx, false); 317 } 318 319 320 static int 321 uci_lua_foreach(lua_State *L) 322 { 323 struct uci_context *ctx; 324 struct uci_package *p; 325 struct uci_element *e, *tmp; 326 const char *package, *type; 327 bool ret = false; 328 int offset = 0; 329 int i = 0; 330 331 ctx = find_context(L, &offset); 332 package = luaL_checkstring(L, 1 + offset); 333 334 if (lua_isnil(L, 2 + offset)) 335 type = NULL; 336 else 337 type = luaL_checkstring(L, 2 + offset); 338 339 if (!lua_isfunction(L, 3 + offset) || !package) 340 return luaL_error(L, "Invalid argument"); 341 342 p = find_package(L, ctx, package, true); 343 if (!p) 344 goto done; 345 346 uci_foreach_element_safe(&p->sections, tmp, e) { 347 struct uci_section *s = uci_to_section(e); 348 349 i++; 350 351 if (type && (strcmp(s->type, type) != 0)) 352 continue; 353 354 lua_pushvalue(L, 3 + offset); /* iterator function */ 355 uci_push_section(L, s, i - 1); 356 if (lua_pcall(L, 1, 1, 0) == 0) { 357 ret = true; 358 if (lua_isboolean(L, -1) && !lua_toboolean(L, -1)) 359 break; 360 } 361 else 362 { 363 lua_error(L); 364 break; 365 } 366 } 367 368 done: 369 lua_pushboolean(L, ret); 370 return 1; 371 } 372 373 static int 374 uci_lua_get_any(lua_State *L, bool all) 375 { 376 struct uci_context *ctx; 377 struct uci_ptr ptr; 378 int offset = 0; 379 int nret = 1; 380 char *s = NULL; 381 382 ctx = find_context(L, &offset); 383 384 if (lookup_args(L, ctx, offset, &ptr, &s)) 385 goto error; 386 387 if (!all && !ptr.s) { 388 ctx->err = UCI_ERR_INVAL; 389 goto error; 390 } 391 if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) { 392 ctx->err = UCI_ERR_NOTFOUND; 393 goto error; 394 } 395 396 if (ptr.o) { 397 uci_push_option(L, ptr.o); 398 } else if (ptr.s) { 399 if (all) { 400 uci_push_section(L, ptr.s, -1); 401 } 402 else { 403 lua_pushstring(L, ptr.s->type); 404 lua_pushstring(L, ptr.s->e.name); 405 nret++; 406 } 407 } else { 408 uci_push_package(L, ptr.p); 409 } 410 411 if (s) 412 free(s); 413 return nret; 414 415 error: 416 if (s) 417 free(s); 418 419 lua_pushnil(L); 420 return uci_push_status(L, ctx, true); 421 } 422 423 static int 424 uci_lua_get(lua_State *L) 425 { 426 return uci_lua_get_any(L, false); 427 } 428 429 static int 430 uci_lua_get_all(lua_State *L) 431 { 432 return uci_lua_get_any(L, true); 433 } 434 435 static int 436 uci_lua_add(lua_State *L) 437 { 438 struct uci_context *ctx; 439 struct uci_section *s = NULL; 440 struct uci_package *p; 441 const char *package; 442 const char *type; 443 const char *name = NULL; 444 int offset = 0; 445 446 ctx = find_context(L, &offset); 447 package = luaL_checkstring(L, 1 + offset); 448 type = luaL_checkstring(L, 2 + offset); 449 p = find_package(L, ctx, package, true); 450 if (!p) 451 goto fail; 452 453 if (uci_add_section(ctx, p, type, &s) || !s) 454 goto fail; 455 456 name = s->e.name; 457 lua_pushstring(L, name); 458 return 1; 459 460 fail: 461 lua_pushnil(L); 462 return uci_push_status(L, ctx, true); 463 } 464 465 static int 466 uci_lua_delete(lua_State *L) 467 { 468 struct uci_context *ctx; 469 struct uci_ptr ptr; 470 int offset = 0; 471 char *s = NULL; 472 473 ctx = find_context(L, &offset); 474 475 if (lookup_args(L, ctx, offset, &ptr, &s)) 476 goto error; 477 478 uci_delete(ctx, &ptr); 479 480 error: 481 if (s) 482 free(s); 483 return uci_push_status(L, ctx, false); 484 } 485 486 static int 487 uci_lua_rename(lua_State *L) 488 { 489 struct uci_context *ctx; 490 struct uci_ptr ptr; 491 int err = UCI_ERR_MEM; 492 char *s = NULL; 493 int nargs, offset = 0; 494 495 ctx = find_context(L, &offset); 496 nargs = lua_gettop(L); 497 if (lookup_args(L, ctx, offset, &ptr, &s)) 498 goto error; 499 500 switch(nargs - offset) { 501 case 1: 502 /* Format: uci.set("p.s.o=v") or uci.set("p.s=v") */ 503 break; 504 case 4: 505 /* Format: uci.set("p", "s", "o", "v") */ 506 ptr.value = luaL_checkstring(L, nargs); 507 break; 508 case 3: 509 /* Format: uci.set("p", "s", "v") */ 510 ptr.value = ptr.option; 511 ptr.option = NULL; 512 break; 513 default: 514 ctx->err = UCI_ERR_INVAL; 515 goto error; 516 } 517 518 err = lookup_ptr(ctx, &ptr, NULL, true); 519 if (err) 520 goto error; 521 522 if (((ptr.s == NULL) && (ptr.option != NULL)) || (ptr.value == NULL)) { 523 ctx->err = UCI_ERR_INVAL; 524 goto error; 525 } 526 527 err = uci_rename(ctx, &ptr); 528 if (err) 529 goto error; 530 531 error: 532 if (s) 533 free(s); 534 return uci_push_status(L, ctx, false); 535 } 536 537 static int 538 uci_lua_reorder(lua_State *L) 539 { 540 struct uci_context *ctx; 541 struct uci_ptr ptr; 542 int err = UCI_ERR_MEM; 543 char *s = NULL; 544 int nargs, offset = 0; 545 546 ctx = find_context(L, &offset); 547 nargs = lua_gettop(L); 548 if (lookup_args(L, ctx, offset, &ptr, &s)) 549 goto error; 550 551 switch(nargs - offset) { 552 case 1: 553 /* Format: uci.set("p.s=v") or uci.set("p.s=v") */ 554 if (ptr.option) { 555 ctx->err = UCI_ERR_INVAL; 556 goto error; 557 } 558 break; 559 case 3: 560 /* Format: uci.set("p", "s", "v") */ 561 ptr.value = ptr.option; 562 ptr.option = NULL; 563 break; 564 default: 565 ctx->err = UCI_ERR_INVAL; 566 goto error; 567 } 568 569 err = lookup_ptr(ctx, &ptr, NULL, true); 570 if (err) 571 goto error; 572 573 if ((ptr.s == NULL) || (ptr.value == NULL)) { 574 ctx->err = UCI_ERR_INVAL; 575 goto error; 576 } 577 578 err = uci_reorder_section(ctx, ptr.s, strtoul(ptr.value, NULL, 10)); 579 if (err) 580 goto error; 581 582 error: 583 if (s) 584 free(s); 585 return uci_push_status(L, ctx, false); 586 } 587 588 589 static int 590 uci_lua_set(lua_State *L) 591 { 592 struct uci_context *ctx; 593 struct uci_ptr ptr; 594 bool istable = false; 595 int err = UCI_ERR_MEM; 596 char *s = NULL; 597 const char *v; 598 unsigned int i; 599 int nargs, offset = 0; 600 601 ctx = find_context(L, &offset); 602 nargs = lua_gettop(L); 603 if (lookup_args(L, ctx, offset, &ptr, &s)) 604 goto error; 605 606 switch(nargs - offset) { 607 case 1: 608 /* Format: uci.set("p.s.o=v") or uci.set("p.s=v") */ 609 break; 610 case 4: 611 /* Format: uci.set("p", "s", "o", "v") */ 612 if (lua_istable(L, nargs)) { 613 if (lua_rawlen(L, nargs) < 1) { 614 free(s); 615 return luaL_error(L, "Cannot set an uci option to an empty table value"); 616 } 617 lua_rawgeti(L, nargs, 1); 618 ptr.value = luaL_checkstring(L, -1); 619 lua_pop(L, 1); 620 istable = true; 621 } else { 622 ptr.value = luaL_checkstring(L, nargs); 623 } 624 break; 625 case 3: 626 /* Format: uci.set("p", "s", "v") */ 627 ptr.value = ptr.option; 628 ptr.option = NULL; 629 break; 630 default: 631 ctx->err = UCI_ERR_INVAL; 632 goto error; 633 } 634 635 err = lookup_ptr(ctx, &ptr, NULL, true); 636 if (err) 637 goto error; 638 639 if (((ptr.s == NULL) && (ptr.option != NULL)) || (ptr.value == NULL)) { 640 ctx->err = UCI_ERR_INVAL; 641 goto error; 642 } 643 644 if (istable) { 645 if (lua_rawlen(L, nargs) == 1) { 646 i = 1; 647 if (ptr.o) { 648 v = ptr.value; 649 ptr.value = NULL; 650 err = uci_delete(ctx, &ptr); 651 if (err) 652 goto error; 653 ptr.value = v; 654 } 655 } else { 656 i = 2; 657 err = uci_set(ctx, &ptr); 658 if (err) 659 goto error; 660 } 661 662 for (; i <= lua_rawlen(L, nargs); i++) { 663 lua_rawgeti(L, nargs, i); 664 ptr.value = luaL_checkstring(L, -1); 665 err = uci_add_list(ctx, &ptr); 666 lua_pop(L, 1); 667 if (err) 668 goto error; 669 } 670 } else { 671 err = uci_set(ctx, &ptr); 672 if (err) 673 goto error; 674 } 675 676 677 error: 678 if (s) 679 free(s); 680 return uci_push_status(L, ctx, false); 681 } 682 683 enum pkg_cmd { 684 CMD_SAVE, 685 CMD_COMMIT, 686 CMD_REVERT 687 }; 688 689 static int 690 uci_lua_package_cmd(lua_State *L, enum pkg_cmd cmd) 691 { 692 struct uci_context *ctx; 693 struct uci_element *e, *tmp; 694 struct uci_ptr ptr; 695 char *s = NULL; 696 int nargs, offset = 0; 697 698 ctx = find_context(L, &offset); 699 nargs = lua_gettop(L); 700 if ((cmd != CMD_REVERT) && (nargs - offset > 1)) 701 goto err; 702 703 if (lookup_args(L, ctx, offset, &ptr, &s)) 704 goto err; 705 706 lookup_ptr(ctx, &ptr, NULL, true); 707 708 uci_foreach_element_safe(&ctx->root, tmp, e) { 709 struct uci_package *p = uci_to_package(e); 710 711 if (ptr.p && (ptr.p != p)) 712 continue; 713 714 ptr.p = p; 715 switch(cmd) { 716 case CMD_COMMIT: 717 uci_commit(ctx, &p, false); 718 break; 719 case CMD_SAVE: 720 uci_save(ctx, p); 721 break; 722 case CMD_REVERT: 723 uci_revert(ctx, &ptr); 724 break; 725 } 726 } 727 728 err: 729 if (s) 730 free(s); 731 return uci_push_status(L, ctx, false); 732 } 733 734 static int 735 uci_lua_save(lua_State *L) 736 { 737 return uci_lua_package_cmd(L, CMD_SAVE); 738 } 739 740 static int 741 uci_lua_commit(lua_State *L) 742 { 743 return uci_lua_package_cmd(L, CMD_COMMIT); 744 } 745 746 static int 747 uci_lua_revert(lua_State *L) 748 { 749 return uci_lua_package_cmd(L, CMD_REVERT); 750 } 751 752 static void 753 uci_lua_add_change(lua_State *L, struct uci_element *e) 754 { 755 struct uci_delta *h; 756 const char *name; 757 const char *value; 758 759 h = uci_to_delta(e); 760 if (!h->section) 761 return; 762 763 lua_getfield(L, -1, h->section); 764 if (lua_isnil(L, -1)) { 765 lua_pop(L, 1); 766 lua_newtable(L); 767 lua_pushvalue(L, -1); /* copy for setfield */ 768 lua_setfield(L, -3, h->section); 769 } 770 771 name = h->e.name; 772 value = h->value ? h->value : ""; 773 774 if (name) { 775 lua_getfield(L, -1, name); 776 777 /* this delta is a list add operation */ 778 if (h->cmd == UCI_CMD_LIST_ADD) { 779 /* there seems to be no table yet */ 780 if (!lua_istable(L, -1)) { 781 lua_newtable(L); 782 783 /* if there is a value on the stack already, add */ 784 if (!lua_isnil(L, -2)) { 785 lua_pushvalue(L, -2); 786 lua_rawseti(L, -2, 1); 787 lua_pushstring(L, value); 788 lua_rawseti(L, -2, 2); 789 790 /* this is the first table item */ 791 } else { 792 lua_pushstring(L, value); 793 lua_rawseti(L, -2, 1); 794 } 795 796 lua_setfield(L, -3, name); 797 798 /* a table is on the top of the stack and this is a subsequent, 799 * list_add, append this value to table */ 800 } else { 801 lua_pushstring(L, value); 802 lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); 803 } 804 805 /* non-list change, simply set/replace field */ 806 } else { 807 lua_pushstring(L, value); 808 lua_setfield(L, -3, name); 809 } 810 811 lua_pop(L, 1); 812 } else { 813 lua_pushstring(L, value); 814 lua_setfield(L, -2, ".type"); 815 } 816 817 lua_pop(L, 1); 818 } 819 820 static void 821 uci_lua_changes_pkg(lua_State *L, struct uci_context *ctx, const char *package) 822 { 823 struct uci_package *p = NULL; 824 struct uci_element *e; 825 bool autoload = false; 826 827 p = find_package(L, ctx, package, false); 828 if (!p) { 829 autoload = true; 830 p = find_package(L, ctx, package, true); 831 if (!p) 832 return; 833 } 834 835 if (uci_list_empty(&p->delta) && uci_list_empty(&p->saved_delta)) 836 goto done; 837 838 lua_newtable(L); 839 uci_foreach_element(&p->saved_delta, e) { 840 uci_lua_add_change(L, e); 841 } 842 uci_foreach_element(&p->delta, e) { 843 uci_lua_add_change(L, e); 844 } 845 lua_setfield(L, -2, p->e.name); 846 847 done: 848 if (autoload) 849 uci_unload(ctx, p); 850 } 851 852 static int 853 uci_lua_changes(lua_State *L) 854 { 855 struct uci_context *ctx; 856 const char *package = NULL; 857 char **config = NULL; 858 int nargs; 859 int i, offset = 0; 860 861 ctx = find_context(L, &offset); 862 nargs = lua_gettop(L); 863 switch(nargs - offset) { 864 case 1: 865 package = luaL_checkstring(L, 1 + offset); 866 case 0: 867 break; 868 default: 869 return luaL_error(L, "invalid argument count"); 870 } 871 872 lua_newtable(L); 873 if (package) { 874 uci_lua_changes_pkg(L, ctx, package); 875 return 1; 876 } 877 878 if ((uci_list_configs(ctx, &config) != UCI_OK) || !config) 879 return 1; 880 881 for (i = 0; config[i] != NULL; i++) { 882 uci_lua_changes_pkg(L, ctx, config[i]); 883 } 884 885 free(config); 886 return 1; 887 } 888 889 static int 890 uci_lua_get_confdir(lua_State *L) 891 { 892 struct uci_context *ctx = find_context(L, NULL); 893 lua_pushstring(L, ctx->confdir); 894 return 1; 895 } 896 897 static int 898 uci_lua_set_confdir(lua_State *L) 899 { 900 struct uci_context *ctx; 901 int offset = 0; 902 903 ctx = find_context(L, &offset); 904 luaL_checkstring(L, 1 + offset); 905 uci_set_confdir(ctx, lua_tostring(L, -1)); 906 return uci_push_status(L, ctx, false); 907 } 908 909 static int 910 uci_lua_get_savedir(lua_State *L) 911 { 912 struct uci_context *ctx = find_context(L, NULL); 913 lua_pushstring(L, ctx->savedir); 914 return 1; 915 } 916 917 static int 918 uci_lua_add_delta(lua_State *L) 919 { 920 struct uci_context *ctx; 921 int offset = 0; 922 923 ctx = find_context(L, &offset); 924 luaL_checkstring(L, 1 + offset); 925 uci_add_delta_path(ctx, lua_tostring(L, -1)); 926 return uci_push_status(L, ctx, false); 927 } 928 929 static int 930 uci_lua_set_savedir(lua_State *L) 931 { 932 struct uci_context *ctx; 933 int offset = 0; 934 935 ctx = find_context(L, &offset); 936 luaL_checkstring(L, 1 + offset); 937 uci_set_savedir(ctx, lua_tostring(L, -1)); 938 return uci_push_status(L, ctx, false); 939 } 940 941 static int 942 uci_lua_list_configs(lua_State *L) 943 { 944 struct uci_context *ctx; 945 char **configs = NULL; 946 char **ptr; 947 int i = 1; 948 949 ctx = find_context(L, NULL); 950 if ((uci_list_configs(ctx, &configs) != UCI_OK) || !configs) 951 return uci_push_status(L, ctx, false); 952 lua_newtable(L); 953 for (ptr = configs; *ptr; ptr++) { 954 lua_pushstring(L, *ptr); 955 lua_rawseti(L, -2, i++); 956 } 957 free(configs); 958 return 1; 959 } 960 961 static int 962 uci_lua_gc(lua_State *L) 963 { 964 struct uci_context **ctx; 965 966 if (!lua_isuserdata(L, 1)) { 967 if (!global_ctx) 968 return 0; 969 ctx = &global_ctx; 970 } else { 971 ctx = luaL_checkudata(L, 1, METANAME); 972 if (!*ctx) 973 return 0; 974 } 975 uci_free_context(*ctx); 976 *ctx = NULL; 977 return 0; 978 } 979 980 static int 981 uci_lua_cursor(lua_State *L) 982 { 983 struct uci_context **u; 984 int argc = lua_gettop(L); 985 986 u = lua_newuserdata(L, sizeof(struct uci_context *)); 987 luaL_getmetatable(L, METANAME); 988 lua_setmetatable(L, -2); 989 990 *u = uci_alloc_context(); 991 if (!*u) 992 return luaL_error(L, "Cannot allocate UCI context"); 993 switch (argc) { 994 case 2: 995 if (lua_isstring(L, 2) && 996 (uci_set_savedir(*u, luaL_checkstring(L, 2)) != UCI_OK)) 997 return luaL_error(L, "Unable to set savedir"); 998 /* fall through */ 999 case 1: 1000 if (lua_isstring(L, 1) && 1001 (uci_set_confdir(*u, luaL_checkstring(L, 1)) != UCI_OK)) 1002 return luaL_error(L, "Unable to set confdir"); 1003 break; 1004 default: 1005 break; 1006 } 1007 return 1; 1008 } 1009 1010 static const luaL_Reg uci[] = { 1011 { "__gc", uci_lua_gc }, 1012 { "close", uci_lua_gc }, 1013 { "cursor", uci_lua_cursor }, 1014 { "load", uci_lua_load }, 1015 { "unload", uci_lua_unload }, 1016 { "get", uci_lua_get }, 1017 { "get_all", uci_lua_get_all }, 1018 { "add", uci_lua_add }, 1019 { "set", uci_lua_set }, 1020 { "rename", uci_lua_rename }, 1021 { "save", uci_lua_save }, 1022 { "delete", uci_lua_delete }, 1023 { "commit", uci_lua_commit }, 1024 { "revert", uci_lua_revert }, 1025 { "reorder", uci_lua_reorder }, 1026 { "changes", uci_lua_changes }, 1027 { "foreach", uci_lua_foreach }, 1028 { "add_history", uci_lua_add_delta }, 1029 { "add_delta", uci_lua_add_delta }, 1030 { "get_confdir", uci_lua_get_confdir }, 1031 { "set_confdir", uci_lua_set_confdir }, 1032 { "get_savedir", uci_lua_get_savedir }, 1033 { "set_savedir", uci_lua_set_savedir }, 1034 { "list_configs", uci_lua_list_configs }, 1035 { NULL, NULL }, 1036 }; 1037 1038 1039 int 1040 luaopen_uci(lua_State *L) 1041 { 1042 /* create metatable */ 1043 luaL_newmetatable(L, METANAME); 1044 1045 /* metatable.__index = metatable */ 1046 lua_pushvalue(L, -1); 1047 lua_setfield(L, -2, "__index"); 1048 1049 /* fill metatable */ 1050 luaL_setfuncs(L, uci, 0); 1051 lua_pop(L, 1); 1052 1053 /* create module */ 1054 lua_newtable(L); 1055 lua_pushvalue(L, -1); 1056 luaL_setfuncs(L, uci, 0); 1057 lua_setglobal(L, MODNAME); 1058 1059 return 1; 1060 } 1061
This page was automatically generated by LXR 0.3.1. • OpenWrt