• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/uci/lua/uci.c

  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