uci: fix excessive reorder delta entry duplication
[project/uci.git] / file.c
diff --git a/file.c b/file.c
index 0120505..d104933 100644 (file)
--- a/file.c
+++ b/file.c
@@ -9,7 +9,7 @@
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * GNU Lesser General Public License for more details.
  */
 
 /*
@@ -60,7 +60,10 @@ __private void uci_getln(struct uci_context *ctx, int offset)
                ofs += strlen(p);
                if (pctx->buf[ofs - 1] == '\n') {
                        pctx->line++;
-                       pctx->buf[ofs - 1] = 0;
+                       if (ofs >= 2 && pctx->buf[ofs - 2] == '\r')
+                               pctx->buf[ofs - 2] = 0;
+                       else
+                               pctx->buf[ofs - 1] = 0;
                        return;
                }
 
@@ -266,7 +269,7 @@ int uci_parse_argument(struct uci_context *ctx, FILE *stream, char **str, char *
 }
 
 static int
-uci_fill_ptr(struct uci_context *ctx, struct uci_ptr *ptr, struct uci_element *e, bool complete)
+uci_fill_ptr(struct uci_context *ctx, struct uci_ptr *ptr, struct uci_element *e)
 {
        UCI_ASSERT(ctx, ptr != NULL);
        UCI_ASSERT(ctx, e != NULL);
@@ -296,8 +299,6 @@ fill_package:
        ptr->package = ptr->p->e.name;
 
        ptr->flags |= UCI_LOOKUP_DONE;
-       if (complete)
-               ptr->flags |= UCI_LOOKUP_COMPLETE;
 
        return 0;
 }
@@ -400,11 +401,11 @@ static void uci_parse_config(struct uci_context *ctx, char **str)
        name = next_arg(ctx, str, false, true);
        assert_eol(ctx, str);
 
-       if (!name) {
+       if (!name || !name[0]) {
                ctx->internal = !pctx->merge;
                UCI_NESTED(uci_add_section, ctx, pctx->package, type, &pctx->section);
        } else {
-               uci_fill_ptr(ctx, &ptr, &pctx->package->e, false);
+               uci_fill_ptr(ctx, &ptr, &pctx->package->e);
                e = uci_lookup_list(&pctx->package->sections, name);
                if (e)
                        ptr.s = uci_to_section(e);
@@ -438,7 +439,7 @@ static void uci_parse_option(struct uci_context *ctx, char **str, bool list)
        value = next_arg(ctx, str, false, false);
        assert_eol(ctx, str);
 
-       uci_fill_ptr(ctx, &ptr, &pctx->section->e, false);
+       uci_fill_ptr(ctx, &ptr, &pctx->section->e);
        e = uci_lookup_list(&pctx->section->options, name);
        if (e)
                ptr.o = uci_to_option(e);
@@ -510,7 +511,7 @@ invalid:
 /*
  * escape an uci string for export
  */
-static char *uci_escape(struct uci_context *ctx, const char *str)
+static const char *uci_escape(struct uci_context *ctx, const char *str)
 {
        const char *end;
        int ofs = 0;
@@ -518,6 +519,9 @@ static char *uci_escape(struct uci_context *ctx, const char *str)
        if (!ctx->buf) {
                ctx->bufsz = LINEBUF;
                ctx->buf = malloc(LINEBUF);
+
+               if (!ctx->buf)
+                       return str;
        }
 
        while (1) {
@@ -560,10 +564,10 @@ static void uci_export_package(struct uci_package *p, FILE *stream, bool header)
        struct uci_element *s, *o, *i;
 
        if (header)
-               fprintf(stream, "package '%s'\n", uci_escape(ctx, p->e.name));
+               fprintf(stream, "package %s\n", uci_escape(ctx, p->e.name));
        uci_foreach_element(&p->sections, s) {
                struct uci_section *sec = uci_to_section(s);
-               fprintf(stream, "\nconfig '%s'", uci_escape(ctx, sec->type));
+               fprintf(stream, "\nconfig %s", uci_escape(ctx, sec->type));
                if (!sec->anonymous || (ctx->flags & UCI_FLAG_EXPORT_NAME))
                        fprintf(stream, " '%s'", uci_escape(ctx, sec->e.name));
                fprintf(stream, "\n");
@@ -571,12 +575,12 @@ static void uci_export_package(struct uci_package *p, FILE *stream, bool header)
                        struct uci_option *opt = uci_to_option(o);
                        switch(opt->type) {
                        case UCI_TYPE_STRING:
-                               fprintf(stream, "\toption '%s'", uci_escape(ctx, opt->e.name));
+                               fprintf(stream, "\toption %s", uci_escape(ctx, opt->e.name));
                                fprintf(stream, " '%s'\n", uci_escape(ctx, opt->v.string));
                                break;
                        case UCI_TYPE_LIST:
                                uci_foreach_element(&opt->v.list, i) {
-                                       fprintf(stream, "\tlist '%s'", uci_escape(ctx, opt->e.name));
+                                       fprintf(stream, "\tlist %s", uci_escape(ctx, opt->e.name));
                                        fprintf(stream, " '%s'\n", uci_escape(ctx, i->name));
                                }
                                break;
@@ -618,7 +622,7 @@ int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct u
        uci_alloc_parse_context(ctx);
        pctx = ctx->pctx;
        pctx->file = stream;
-       if (*package && single) {
+       if (package && *package && single) {
                pctx->package = *package;
                pctx->merge = true;
        }
@@ -677,7 +681,7 @@ static char *uci_config_path(struct uci_context *ctx, const char *name)
        return filename;
 }
 
-void uci_file_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite)
+static void uci_file_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite)
 {
        struct uci_package *p = *package;
        FILE *f = NULL;
@@ -833,9 +837,9 @@ static struct uci_package *uci_file_load(struct uci_context *ctx, const char *na
                break;
        }
 
+       UCI_TRAP_SAVE(ctx, done);
        file = uci_open_stream(ctx, filename, SEEK_SET, false, false);
        ctx->err = 0;
-       UCI_TRAP_SAVE(ctx, done);
        UCI_INTERNAL(uci_import, ctx, file, name, &package, true);
        UCI_TRAP_RESTORE(ctx);
 
@@ -847,8 +851,10 @@ static struct uci_package *uci_file_load(struct uci_context *ctx, const char *na
 
 done:
        uci_close_stream(file);
-       if (ctx->err)
+       if (ctx->err) {
+               free(filename);
                UCI_THROW(ctx, ctx->err);
+       }
        return package;
 }