projects/uci: lua: use built in pkg-config support for alternatives
[project/uci.git] / file.c
diff --git a/file.c b/file.c
index be75e54..7e1e4e6 100644 (file)
--- a/file.c
+++ b/file.c
@@ -33,7 +33,6 @@
 #include "uci_internal.h"
 
 #define LINEBUF        32
-#define LINEBUF_MAX    4096
 
 /*
  * Fetch a new line from the input stream and resize buffer if necessary
@@ -69,11 +68,10 @@ __private void uci_getln(struct uci_context *ctx, int offset)
                        return;
                }
 
-               if (pctx->bufsz > LINEBUF_MAX/2)
-                       uci_parse_error(ctx, "line too long");
-
                pctx->bufsz *= 2;
                pctx->buf = uci_realloc(ctx, pctx->buf, pctx->bufsz);
+               if (!pctx->buf)
+                       UCI_THROW(ctx, UCI_ERR_MEM);
        } while (1);
 }
 
@@ -278,10 +276,11 @@ int uci_parse_argument(struct uci_context *ctx, FILE *stream, char **str, char *
                uci_alloc_parse_context(ctx);
 
        ctx->pctx->file = stream;
-       if (!*str)
+       if (!*str) {
+               ctx->pctx->pos = 0;
                uci_getln(ctx, 0);
+       }
 
-       /*FIXME do we need to skip empty lines? */
        ofs_result = next_arg(ctx, false, false, false);
        *result = pctx_str(ctx->pctx, ofs_result);
        *str = pctx_cur_str(ctx->pctx);
@@ -438,8 +437,13 @@ static void uci_parse_config(struct uci_context *ctx)
        } else {
                uci_fill_ptr(ctx, &ptr, &pctx->package->e);
                e = uci_lookup_list(&pctx->package->sections, name);
-               if (e)
+               if (e) {
                        ptr.s = uci_to_section(e);
+
+                       if ((ctx->flags & UCI_FLAG_STRICT) && strcmp(ptr.s->type, type))
+                               uci_parse_error(ctx, "section of different type overwrites prior section with same name");
+               }
+
                ptr.section = name;
                ptr.value = type;
 
@@ -736,17 +740,6 @@ static void uci_file_commit(struct uci_context *ctx, struct uci_package **packag
        if ((asprintf(&filename, "%s/.%s.uci-XXXXXX", ctx->confdir, p->e.name) < 0) || !filename)
                UCI_THROW(ctx, UCI_ERR_MEM);
 
-       if (!mktemp(filename))
-               *filename = 0;
-
-       if (!*filename) {
-               free(filename);
-               UCI_THROW(ctx, UCI_ERR_IO);
-       }
-
-       if ((stat(filename, &statbuf) == 0) && ((statbuf.st_mode & S_IFMT) != S_IFREG))
-               UCI_THROW(ctx, UCI_ERR_IO);
-
        /* open the config file for writing now, so that it is locked */
        f1 = uci_open_stream(ctx, p->path, NULL, SEEK_SET, true, true);
 
@@ -781,6 +774,17 @@ static void uci_file_commit(struct uci_context *ctx, struct uci_package **packag
                        goto done;
        }
 
+       if (!mktemp(filename))
+               *filename = 0;
+
+       if (!*filename) {
+               free(filename);
+               UCI_THROW(ctx, UCI_ERR_IO);
+       }
+
+       if ((stat(filename, &statbuf) == 0) && ((statbuf.st_mode & S_IFMT) != S_IFREG))
+               UCI_THROW(ctx, UCI_ERR_IO);
+
        f2 = uci_open_stream(ctx, filename, p->path, SEEK_SET, true, true);
        uci_export(ctx, f2, p, false);
 
@@ -796,12 +800,15 @@ done:
        free(name);
        free(path);
        uci_close_stream(f1);
-       if (do_rename && rename(filename, p->path)) {
-               unlink(filename);
-               UCI_THROW(ctx, UCI_ERR_IO);
+       if (do_rename) {
+               path = realpath(p->path, NULL);
+               if (!path || rename(filename, path)) {
+                       unlink(filename);
+                       UCI_THROW(ctx, UCI_ERR_IO);
+               }
+               free(path);
        }
        free(filename);
-       sync();
        if (ctx->err)
                UCI_THROW(ctx, ctx->err);
 }