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_element *e = NULL; 378 struct uci_ptr ptr; 379 int offset = 0; 380 int nret = 1; 381 char *s = NULL; 382 int err = UCI_ERR_NOTFOUND; 383 384 ctx = find_context(L, &offset); 385 386 if (lookup_args(L, ctx, offset, &ptr, &s)) 387 goto error; 388 389 lookup_ptr(ctx, &ptr, NULL, true); 390 if (!all && !ptr.s) { 391 ctx->err = UCI_ERR_INVAL; 392 goto error; 393 } 394 if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) { 395 ctx->err = UCI_ERR_NOTFOUND; 396 goto error; 397 } 398 399 err = UCI_OK; 400 e = ptr.last; 401 switch(e->type) { 402 case UCI_TYPE_PACKAGE: 403 uci_push_package(L, ptr.p); 404 break; 405 case UCI_TYPE_SECTION: 406 if (all) { 407 uci_push_section(L, ptr.s, -1); 408 } 409 else { 410 lua_pushstring(L, ptr.s->type); 411 lua_pushstring(L, ptr.s->e.name); 412 nret++; 413 } 414 break; 415 case UCI_TYPE_OPTION: 416 uci_push_option(L, ptr.o); 417 break; 418 default: 419 ctx->err = UCI_ERR_INVAL; 420 goto error; 421 } 422 if (s) 423 free(s); 424 if (!err) 425 return nret; 426 427 error: 428 if (s) 429 free(s); 430 431 lua_pushnil(L); 432 return uci_push_status(L, ctx, true); 433 } 434 435 static int 436 uci_lua_get(lua_State *L) 437 { 438 return uci_lua_get_any(L, false); 439 } 440 441 static int 442 uci_lua_get_all(lua_State *L) 443 { 444 return uci_lua_get_any(L, true); 445 } 446 447 static int 448 uci_lua_add(lua_State *L) 449 { 450 struct uci_context *ctx; 451 struct uci_section *s = NULL; 452 struct uci_package *p; 453 const char *package; 454 const char *type; 455 const char *name = NULL; 456 int offset = 0; 457 458 ctx = find_context(L, &offset); 459 package = luaL_checkstring(L, 1 + offset); 460 type = luaL_checkstring(L, 2 + offset); 461 p = find_package(L, ctx, package, true); 462 if (!p) 463 goto fail; 464 465 if (uci_add_section(ctx, p, type, &s) || !s) 466 goto fail; 467 468 name = s->e.name; 469 lua_pushstring(L, name); 470 return 1; 471 472 fail: 473 lua_pushnil(L); 474 return uci_push_status(L, ctx, true); 475 } 476 477 static int 478 uci_lua_delete(lua_State *L) 479 { 480 struct uci_context *ctx; 481 struct uci_ptr ptr; 482 int offset = 0; 483 char *s = NULL; 484 485 ctx = find_context(L, &offset); 486 487 if (lookup_args(L, ctx, offset, &ptr, &s)) 488 goto error; 489 490 uci_delete(ctx, &ptr); 491 492 error: 493 if (s) 494 free(s); 495 return uci_push_status(L, ctx, false); 496 } 497 498 static int 499 uci_lua_rename(lua_State *L) 500 { 501 struct uci_context *ctx; 502 struct uci_ptr ptr; 503 int err = UCI_ERR_MEM; 504 char *s = NULL; 505 int nargs, offset = 0; 506 507 ctx = find_context(L, &offset); 508 nargs = lua_gettop(L); 509 if (lookup_args(L, ctx, offset, &ptr, &s)) 510 goto error; 511 512 switch(nargs - offset) { 513 case 1: 514 /* Format: uci.set("p.s.o=v") or uci.set("p.s=v") */ 515 break; 516 case 4: 517 /* Format: uci.set("p", "s", "o", "v") */ 518 ptr.value = luaL_checkstring(L, nargs); 519 break; 520 case 3: 521 /* Format: uci.set("p", "s", "v") */ 522 ptr.value = ptr.option; 523 ptr.option = NULL; 524 break; 525 default: 526 ctx->err = UCI_ERR_INVAL; 527 goto error; 528 } 529 530 err = lookup_ptr(ctx, &ptr, NULL, true); 531 if (err) 532 goto error; 533 534 if (((ptr.s == NULL) && (ptr.option != NULL)) || (ptr.value == NULL)) { 535 ctx->err = UCI_ERR_INVAL; 536 goto error; 537 } 538 539 err = uci_rename(ctx, &ptr); 540 if (err) 541 goto error; 542 543 error: 544 if (s) 545 free(s); 546 return uci_push_status(L, ctx, false); 547 } 548 549 static int 550 uci_lua_reorder(lua_State *L) 551 { 552 struct uci_context *ctx; 553 struct uci_ptr ptr; 554 int err = UCI_ERR_MEM; 555 char *s = NULL; 556 int nargs, offset = 0; 557 558 ctx = find_context(L, &offset); 559 nargs = lua_gettop(L); 560 if (lookup_args(L, ctx, offset, &ptr, &s)) 561 goto error; 562 563 switch(nargs - offset) { 564 case 1: 565 /* Format: uci.set("p.s=v") or uci.set("p.s=v") */ 566 if (ptr.option) { 567 ctx->err = UCI_ERR_INVAL; 568 goto error; 569 } 570 break; 571 case 3: 572 /* Format: uci.set("p", "s", "v") */ 573 ptr.value = ptr.option; 574 ptr.option = NULL; 575 break; 576 default: 577 ctx->err = UCI_ERR_INVAL; 578 goto error; 579 } 580 581 err = lookup_ptr(ctx, &ptr, NULL, true); 582 if (err) 583 goto error; 584 585 if ((ptr.s == NULL) || (ptr.value == NULL)) { 586 ctx->err = UCI_ERR_INVAL; 587 goto error; 588 } 589 590 err = uci_reorder_section(ctx, ptr.s, strtoul(ptr.value, NULL, 10)); 591 if (err) 592 goto error; 593 594 error: 595 if (s) 596 free(s); 597 return uci_push_status(L, ctx, false); 598 } 599 600 601 static int 602 uci_lua_set(lua_State *L) 603 { 604 struct uci_context *ctx; 605 struct uci_ptr ptr; 606 bool istable = false; 607 int err = UCI_ERR_MEM; 608 char *s = NULL; 609 const char *v; 610 unsigned int i; 611 int nargs, offset = 0; 612 613 ctx = find_context(L, &offset); 614 nargs = lua_gettop(L); 615 if (lookup_args(L, ctx, offset, &ptr, &s)) 616 goto error; 617 618 switch(nargs - offset) { 619 case 1: 620 /* Format: uci.set("p.s.o=v") or uci.set("p.s=v") */ 621 break; 622 case 4: 623 /* Format: uci.set("p", "s", "o", "v") */ 624 if (lua_istable(L, nargs)) { 625 if (lua_rawlen(L, nargs) < 1) { 626 free(s); 627 return luaL_error(L, "Cannot set an uci option to an empty table value"); 628 } 629 lua_rawgeti(L, nargs, 1); 630 ptr.value = luaL_checkstring(L, -1); 631 lua_pop(L, 1); 632 istable = true; 633 } else { 634 ptr.value = luaL_checkstring(L, nargs); 635 } 636 break; 637 case 3: 638 /* Format: uci.set("p", "s", "v") */ 639 ptr.value = ptr.option; 640 ptr.option = NULL; 641 break; 642 default: 643 ctx->err = UCI_ERR_INVAL; 644 goto error; 645 } 646 647 err = lookup_ptr(ctx, &ptr, NULL, true); 648 if (err) 649 goto error; 650 651 if (((ptr.s == NULL) && (ptr.option != NULL)) || (ptr.value == NULL)) { 652 ctx->err = UCI_ERR_INVAL; 653 goto error; 654 } 655 656 if (istable) { 657 if (lua_rawlen(L, nargs) == 1) { 658 i = 1; 659 if (ptr.o) { 660 v = ptr.value; 661 ptr.value = NULL; 662 err = uci_delete(ctx, &ptr); 663 if (err) 664 goto error; 665 ptr.value = v; 666 } 667 } else { 668 i = 2; 669 err = uci_set(ctx, &ptr); 670 if (err) 671 goto error; 672 } 673 674 for (; i <= lua_rawlen(L, nargs); i++) { 675 lua_rawgeti(L, nargs, i); 676 ptr.value = luaL_checkstring(L, -1); 677 err = uci_add_list(ctx, &ptr); 678 lua_pop(L, 1); 679 if (err) 680 goto error; 681 } 682 } else { 683 err = uci_set(ctx, &ptr); 684 if (err) 685 goto error; 686 } 687 688 689 error: 690 if (s) 691 free(s); 692 return uci_push_status(L, ctx, false); 693 } 694 695 enum pkg_cmd { 696 CMD_SAVE, 697 CMD_COMMIT, 698 CMD_REVERT 699 }; 700 701 static int 702 uci_lua_package_cmd(lua_State *L, enum pkg_cmd cmd) 703 { 704 struct uci_context *ctx; 705 struct uci_element *e, *tmp; 706 struct uci_ptr ptr; 707 char *s = NULL; 708 int nargs, offset = 0; 709 710 ctx = find_context(L, &offset); 711 nargs = lua_gettop(L); 712 if ((cmd != CMD_REVERT) && (nargs - offset > 1)) 713 goto err; 714 715 if (lookup_args(L, ctx, offset, &ptr, &s)) 716 goto err; 717 718 lookup_ptr(ctx, &ptr, NULL, true); 719 720 uci_foreach_element_safe(&ctx->root, tmp, e) { 721 struct uci_package *p = uci_to_package(e); 722 723 if (ptr.p && (ptr.p != p)) 724 continue; 725 726 ptr.p = p; 727 switch(cmd) { 728 case CMD_COMMIT: 729 uci_commit(ctx, &p, false); 730 break; 731 case CMD_SAVE: 732 uci_save(ctx, p); 733 break; 734 case CMD_REVERT: 735 uci_revert(ctx, &ptr); 736 break; 737 } 738 } 739 740 err: 741 if (s) 742 free(s); 743 return uci_push_status(L, ctx, false); 744 } 745 746 static int 747 uci_lua_save(lua_State *L) 748 { 749 return uci_lua_package_cmd(L, CMD_SAVE); 750 } 751 752 static int 753 uci_lua_commit(lua_State *L) 754 { 755 return uci_lua_package_cmd(L, CMD_COMMIT); 756 } 757 758 static int 759 uci_lua_revert(lua_State *L) 760 { 761 return uci_lua_package_cmd(L, CMD_REVERT); 762 } 763 764 static void 765 uci_lua_add_change(lua_State *L, struct uci_element *e) 766 { 767 struct uci_delta *h; 768 const char *name; 769 const char *value; 770 771 h = uci_to_delta(e); 772 if (!h->section) 773 return; 774 775 lua_getfield(L, -1, h->section); 776 if (lua_isnil(L, -1)) { 777 lua_pop(L, 1); 778 lua_newtable(L); 779 lua_pushvalue(L, -1); /* copy for setfield */ 780 lua_setfield(L, -3, h->section); 781 } 782 783 name = h->e.name; 784 value = h->value ? h->value : ""; 785 786 if (name) { 787 lua_getfield(L, -1, name); 788 789 /* this delta is a list add operation */ 790 if (h->cmd == UCI_CMD_LIST_ADD) { 791 /* there seems to be no table yet */ 792 if (!lua_istable(L, -1)) { 793 lua_newtable(L); 794 795 /* if there is a value on the stack already, add */ 796 if (!lua_isnil(L, -2)) { 797 lua_pushvalue(L, -2); 798 lua_rawseti(L, -2, 1); 799 lua_pushstring(L, value); 800 lua_rawseti(L, -2, 2); 801 802 /* this is the first table item */ 803 } else { 804 lua_pushstring(L, value); 805 lua_rawseti(L, -2, 1); 806 } 807 808 lua_setfield(L, -3, name); 809 810 /* a table is on the top of the stack and this is a subsequent, 811 * list_add, append this value to table */ 812 } else { 813 lua_pushstring(L, value); 814 lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); 815 } 816 817 /* non-list change, simply set/replace field */ 818 } else { 819 lua_pushstring(L, value); 820 lua_setfield(L, -3, name); 821 } 822 823 lua_pop(L, 1); 824 } else { 825 lua_pushstring(L, value); 826 lua_setfield(L, -2, ".type"); 827 } 828 829 lua_pop(L, 1); 830 } 831 832 static void 833 uci_lua_changes_pkg(lua_State *L, struct uci_context *ctx, const char *package) 834 { 835 struct uci_package *p = NULL; 836 struct uci_element *e; 837 bool autoload = false; 838 839 p = find_package(L, ctx, package, false); 840 if (!p) { 841 autoload = true; 842 p = find_package(L, ctx, package, true); 843 if (!p) 844 return; 845 } 846 847 if (uci_list_empty(&p->delta) && uci_list_empty(&p->saved_delta)) 848 goto done; 849 850 lua_newtable(L); 851 uci_foreach_element(&p->saved_delta, e) { 852 uci_lua_add_change(L, e); 853 } 854 uci_foreach_element(&p->delta, e) { 855 uci_lua_add_change(L, e); 856 } 857 lua_setfield(L, -2, p->e.name); 858 859 done: 860 if (autoload) 861 uci_unload(ctx, p); 862 } 863 864 static int 865 uci_lua_changes(lua_State *L) 866 { 867 struct uci_context *ctx; 868 const char *package = NULL; 869 char **config = NULL; 870 int nargs; 871 int i, offset = 0; 872 873 ctx = find_context(L, &offset); 874 nargs = lua_gettop(L); 875 switch(nargs - offset) { 876 case 1: 877 package = luaL_checkstring(L, 1 + offset); 878 case 0: 879 break; 880 default: 881 return luaL_error(L, "invalid argument count"); 882 } 883 884 lua_newtable(L); 885 if (package) { 886 uci_lua_changes_pkg(L, ctx, package); 887 return 1; 888 } 889 890 if ((uci_list_configs(ctx, &config) != UCI_OK) || !config) 891 return 1; 892 893 for (i = 0; config[i] != NULL; i++) { 894 uci_lua_changes_pkg(L, ctx, config[i]); 895 } 896 897 free(config); 898 return 1; 899 } 900 901 static int 902 uci_lua_get_confdir(lua_State *L) 903 { 904 struct uci_context *ctx = find_context(L, NULL); 905 lua_pushstring(L, ctx->confdir); 906 return 1; 907 } 908 909 static int 910 uci_lua_set_confdir(lua_State *L) 911 { 912 struct uci_context *ctx; 913 int offset = 0; 914 915 ctx = find_context(L, &offset); 916 luaL_checkstring(L, 1 + offset); 917 uci_set_confdir(ctx, lua_tostring(L, -1)); 918 return uci_push_status(L, ctx, false); 919 } 920 921 static int 922 uci_lua_get_savedir(lua_State *L) 923 { 924 struct uci_context *ctx = find_context(L, NULL); 925 lua_pushstring(L, ctx->savedir); 926 return 1; 927 } 928 929 static int 930 uci_lua_add_delta(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_add_delta_path(ctx, lua_tostring(L, -1)); 938 return uci_push_status(L, ctx, false); 939 } 940 941 static int 942 uci_lua_set_savedir(lua_State *L) 943 { 944 struct uci_context *ctx; 945 int offset = 0; 946 947 ctx = find_context(L, &offset); 948 luaL_checkstring(L, 1 + offset); 949 uci_set_savedir(ctx, lua_tostring(L, -1)); 950 return uci_push_status(L, ctx, false); 951 } 952 953 static int 954 uci_lua_list_configs(lua_State *L) 955 { 956 struct uci_context *ctx; 957 char **configs = NULL; 958 char **ptr; 959 int i = 1; 960 961 ctx = find_context(L, NULL); 962 if ((uci_list_configs(ctx, &configs) != UCI_OK) || !configs) 963 return uci_push_status(L, ctx, false); 964 lua_newtable(L); 965 for (ptr = configs; *ptr; ptr++) { 966 lua_pushstring(L, *ptr); 967 lua_rawseti(L, -2, i++); 968 } 969 free(configs); 970 return 1; 971 } 972 973 static int 974 uci_lua_gc(lua_State *L) 975 { 976 struct uci_context **ctx; 977 978 if (!lua_isuserdata(L, 1)) { 979 if (!global_ctx) 980 return 0; 981 ctx = &global_ctx; 982 } else { 983 ctx = luaL_checkudata(L, 1, METANAME); 984 if (!*ctx) 985 return 0; 986 } 987 uci_free_context(*ctx); 988 *ctx = NULL; 989 return 0; 990 } 991 992 static int 993 uci_lua_cursor(lua_State *L) 994 { 995 struct uci_context **u; 996 int argc = lua_gettop(L); 997 998 u = lua_newuserdata(L, sizeof(struct uci_context *)); 999 luaL_getmetatable(L, METANAME); 1000 lua_setmetatable(L, -2); 1001 1002 *u = uci_alloc_context(); 1003 if (!*u) 1004 return luaL_error(L, "Cannot allocate UCI context"); 1005 switch (argc) { 1006 case 2: 1007 if (lua_isstring(L, 2) && 1008 (uci_set_savedir(*u, luaL_checkstring(L, 2)) != UCI_OK)) 1009 return luaL_error(L, "Unable to set savedir"); 1010 /* fall through */ 1011 case 1: 1012 if (lua_isstring(L, 1) && 1013 (uci_set_confdir(*u, luaL_checkstring(L, 1)) != UCI_OK)) 1014 return luaL_error(L, "Unable to set confdir"); 1015 break; 1016 default: 1017 break; 1018 } 1019 return 1; 1020 } 1021 1022 static const luaL_Reg uci[] = { 1023 { "__gc", uci_lua_gc }, 1024 { "close", uci_lua_gc }, 1025 { "cursor", uci_lua_cursor }, 1026 { "load", uci_lua_load }, 1027 { "unload", uci_lua_unload }, 1028 { "get", uci_lua_get }, 1029 { "get_all", uci_lua_get_all }, 1030 { "add", uci_lua_add }, 1031 { "set", uci_lua_set }, 1032 { "rename", uci_lua_rename }, 1033 { "save", uci_lua_save }, 1034 { "delete", uci_lua_delete }, 1035 { "commit", uci_lua_commit }, 1036 { "revert", uci_lua_revert }, 1037 { "reorder", uci_lua_reorder }, 1038 { "changes", uci_lua_changes }, 1039 { "foreach", uci_lua_foreach }, 1040 { "add_history", uci_lua_add_delta }, 1041 { "add_delta", uci_lua_add_delta }, 1042 { "get_confdir", uci_lua_get_confdir }, 1043 { "set_confdir", uci_lua_set_confdir }, 1044 { "get_savedir", uci_lua_get_savedir }, 1045 { "set_savedir", uci_lua_set_savedir }, 1046 { "list_configs", uci_lua_list_configs }, 1047 { NULL, NULL }, 1048 }; 1049 1050 1051 int 1052 luaopen_uci(lua_State *L) 1053 { 1054 /* create metatable */ 1055 luaL_newmetatable(L, METANAME); 1056 1057 /* metatable.__index = metatable */ 1058 lua_pushvalue(L, -1); 1059 lua_setfield(L, -2, "__index"); 1060 1061 /* fill metatable */ 1062 luaL_setfuncs(L, uci, 0); 1063 lua_pop(L, 1); 1064 1065 /* create module */ 1066 lua_newtable(L); 1067 lua_pushvalue(L, -1); 1068 luaL_setfuncs(L, uci, 0); 1069 lua_setglobal(L, MODNAME); 1070 1071 return 1; 1072 } 1073
This page was automatically generated by LXR 0.3.1. • OpenWrt