fix a stupid duplicate value checking bug (patch by Frédéric Moulins)
[project/uci.git] / file.c
diff --git a/file.c b/file.c
index 5360ef7..c513c87 100644 (file)
--- a/file.c
+++ b/file.c
@@ -128,7 +128,7 @@ static void uci_parse_config(struct uci_context *ctx, char **str)
                UCI_TRAP_RESTORE(ctx);
                return;
 error:
-               UCI_THROW(ctx, ctx->errno);
+               UCI_THROW(ctx, ctx->err);
        } else
                pctx->section = uci_alloc_section(pctx->package, type, name);
 }
@@ -158,7 +158,7 @@ static void uci_parse_option(struct uci_context *ctx, char **str)
                UCI_TRAP_RESTORE(ctx);
                return;
 error:
-               UCI_THROW(ctx, ctx->errno);
+               UCI_THROW(ctx, ctx->err);
        } else
                uci_alloc_option(pctx->section, name, value);
 }
@@ -208,42 +208,47 @@ static void uci_parse_line(struct uci_context *ctx, bool single)
 /*
  * escape an uci string for export
  */
-static char *uci_escape(struct uci_context *ctx, char *str)
+static char *uci_escape(struct uci_context *ctx, const char *str)
 {
-       char *s, *p;
-       int pos = 0;
+       const char *end;
+       int ofs = 0;
 
        if (!ctx->buf) {
                ctx->bufsz = LINEBUF;
                ctx->buf = malloc(LINEBUF);
        }
 
-       s = str;
-       p = strchr(str, '\'');
-       if (!p)
-               return str;
+       while (1) {
+               int len;
 
-       do {
-               int len = p - s;
-               if (len > 0) {
-                       if (p + sizeof(UCI_QUOTE_ESCAPE) - str >= ctx->bufsz) {
-                               ctx->bufsz *= 2;
-                               ctx->buf = realloc(ctx->buf, ctx->bufsz);
-                               if (!ctx->buf)
-                                       UCI_THROW(ctx, UCI_ERR_MEM);
-                       }
-                       memcpy(&ctx->buf[pos], s, len);
-                       pos += len;
+               end = strchr(str, '\'');
+               if (!end)
+                       end = str + strlen(str);
+               len = end - str;
+
+               /* make sure that we have enough room in the buffer */
+               while (ofs + len + sizeof(UCI_QUOTE_ESCAPE) + 1 > ctx->bufsz) {
+                       ctx->bufsz *= 2;
+                       ctx->buf = uci_realloc(ctx, ctx->buf, ctx->bufsz);
                }
-               strcpy(&ctx->buf[pos], UCI_QUOTE_ESCAPE);
-               pos += sizeof(UCI_QUOTE_ESCAPE);
-               s = p + 1;
-       } while ((p = strchr(s, '\'')));
 
+               /* copy the string until the character before the quote */
+               memcpy(&ctx->buf[ofs], str, len);
+               ofs += len;
+
+               /* end of string? return the buffer */
+               if (*end == 0)
+                       break;
+
+               memcpy(&ctx->buf[ofs], UCI_QUOTE_ESCAPE, sizeof(UCI_QUOTE_ESCAPE));
+               ofs += strlen(&ctx->buf[ofs]);
+               str = end + 1;
+       }
+
+       ctx->buf[ofs] = 0;
        return ctx->buf;
 }
 
-
 /*
  * export a single config package to a file stream
  */
@@ -309,7 +314,7 @@ int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct u
         * NB: the config file can still override the package name
         */
        if (name) {
-               UCI_ASSERT(ctx, uci_validate_name(name));
+               UCI_ASSERT(ctx, uci_validate_str(name, false));
                pctx->name = name;
        }
 
@@ -323,9 +328,9 @@ int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct u
 error:
                if (ctx->flags & UCI_FLAG_PERROR)
                        uci_perror(ctx, NULL);
-               if ((ctx->errno != UCI_ERR_PARSE) ||
+               if ((ctx->err != UCI_ERR_PARSE) ||
                        (ctx->flags & UCI_FLAG_STRICT))
-                       UCI_THROW(ctx, ctx->errno);
+                       UCI_THROW(ctx, ctx->err);
        }
 
        uci_fixup_section(ctx, ctx->pctx->section);
@@ -350,7 +355,7 @@ static char *uci_config_path(struct uci_context *ctx, const char *name)
 {
        char *filename;
 
-       UCI_ASSERT(ctx, uci_validate_name(name));
+       UCI_ASSERT(ctx, uci_validate_str(name, false));
        filename = uci_malloc(ctx, strlen(name) + strlen(ctx->confdir) + 2);
        sprintf(filename, "%s/%s", ctx->confdir, name);
 
@@ -421,8 +426,8 @@ done:
        if (path)
                free(path);
        uci_close_stream(f);
-       if (ctx->errno)
-               UCI_THROW(ctx, ctx->errno);
+       if (ctx->err)
+               UCI_THROW(ctx, ctx->err);
 }
 
 
@@ -511,7 +516,7 @@ static struct uci_package *uci_file_load(struct uci_context *ctx, const char *na
        }
 
        file = uci_open_stream(ctx, filename, SEEK_SET, false, false);
-       ctx->errno = 0;
+       ctx->err = 0;
        UCI_TRAP_SAVE(ctx, done);
        UCI_INTERNAL(uci_import, ctx, file, name, &package, true);
        UCI_TRAP_RESTORE(ctx);
@@ -524,8 +529,8 @@ static struct uci_package *uci_file_load(struct uci_context *ctx, const char *na
 
 done:
        uci_close_stream(file);
-       if (ctx->errno)
-               UCI_THROW(ctx, ctx->errno);
+       if (ctx->err)
+               UCI_THROW(ctx, ctx->err);
        return package;
 }