remove internal usage of redundant uci_ptr.last
[project/uci.git] / util.c
diff --git a/util.c b/util.c
index 812a3a3a64b296ad335ff0919102eef4d2ece59f..61e42cd3b061c5e17f9950339e815ebbac96b68d 100644 (file)
--- a/util.c
+++ b/util.c
@@ -36,10 +36,9 @@ __private void *uci_malloc(struct uci_context *ctx, size_t size)
 {
        void *ptr;
 
-       ptr = malloc(size);
+       ptr = calloc(1, size);
        if (!ptr)
                UCI_THROW(ctx, UCI_ERR_MEM);
-       memset(ptr, 0, size);
 
        return ptr;
 }
@@ -69,18 +68,22 @@ __private char *uci_strdup(struct uci_context *ctx, const char *str)
  * for names, only alphanum and _ is allowed (shell compatibility)
  * for types, we allow more characters
  */
-__private bool uci_validate_str(const char *str, bool name)
+__private bool uci_validate_str(const char *str, bool name, bool package)
 {
        if (!*str)
                return false;
 
-       while (*str) {
+       for (; *str; str++) {
                unsigned char c = *str;
-               if (!isalnum(c) && c != '_') {
-                       if (name || (c < 33) || (c > 126))
-                               return false;
-               }
-               str++;
+
+               if (isalnum(c) || c == '_')
+                       continue;
+
+               if (c == '-' && package)
+                       continue;
+
+               if (name || (c < 33) || (c > 126))
+                       return false;
        }
        return true;
 }
@@ -89,9 +92,10 @@ bool uci_validate_text(const char *str)
 {
        while (*str) {
                unsigned char c = *str;
-               if ((c == '\r') || (c == '\n') ||
-                       ((c < 32) && (c != '\t')))
+
+               if (c < 32 && c != '\t' && c != '\n' && c != '\r')
                        return false;
+
                str++;
        }
        return true;
@@ -161,12 +165,12 @@ error:
 }
 
 
-__private void uci_parse_error(struct uci_context *ctx, char *pos, char *reason)
+__private void uci_parse_error(struct uci_context *ctx, char *reason)
 {
        struct uci_parse_context *pctx = ctx->pctx;
 
        pctx->reason = reason;
-       pctx->byte = pos - pctx->buf;
+       pctx->byte = pctx_pos(pctx);
        UCI_THROW(ctx, UCI_ERR_PARSE);
 }
 
@@ -178,7 +182,7 @@ __private void uci_parse_error(struct uci_context *ctx, char *pos, char *reason)
  * note: when opening for write and seeking to the beginning of
  * the stream, truncate the file
  */
-__private FILE *uci_open_stream(struct uci_context *ctx, const char *filename, int pos, bool write, bool create)
+__private FILE *uci_open_stream(struct uci_context *ctx, const char *filename, const char *origfilename, int pos, bool write, bool create)
 {
        struct stat statbuf;
        FILE *file = NULL;
@@ -190,11 +194,15 @@ __private FILE *uci_open_stream(struct uci_context *ctx, const char *filename, i
 
        if (create) {
                flags |= O_CREAT;
-               name = basename((char *) filename);
+               if (origfilename) {
+                       name = basename((char *) origfilename);
+               } else {
+                       name = basename((char *) filename);
+               }
                if ((asprintf(&filename2, "%s/%s", ctx->confdir, name) < 0) || !filename2) {
                        UCI_THROW(ctx, UCI_ERR_MEM);
                } else {
-                       if (stat(filename2,&statbuf) == 0)
+                       if (stat(filename2, &statbuf) == 0)
                                mode = statbuf.st_mode;
 
                        free(filename2);
@@ -202,7 +210,7 @@ __private FILE *uci_open_stream(struct uci_context *ctx, const char *filename, i
        }
 
        if (!write && ((stat(filename, &statbuf) < 0) ||
-               ((statbuf.st_mode &  S_IFMT) != S_IFREG))) {
+               ((statbuf.st_mode & S_IFMT) != S_IFREG))) {
                UCI_THROW(ctx, UCI_ERR_NOTFOUND);
        }
 
@@ -212,17 +220,21 @@ __private FILE *uci_open_stream(struct uci_context *ctx, const char *filename, i
 
        ret = flock(fd, (write ? LOCK_EX : LOCK_SH));
        if ((ret < 0) && (errno != ENOSYS))
-               goto error;
+               goto error_close;
 
        ret = lseek(fd, 0, pos);
 
        if (ret < 0)
-               goto error;
+               goto error_unlock;
 
        file = fdopen(fd, (write ? "w+" : "r"));
        if (file)
                goto done;
 
+error_unlock:
+       flock(fd, LOCK_UN);
+error_close:
+       close(fd);
 error:
        UCI_THROW(ctx, UCI_ERR_IO);
 done: