• 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_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