summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2008-02-03 05:10:21 +0100
committerFelix Fietkau <nbd@openwrt.org>2008-02-03 05:10:21 +0100
commit818f7b8433ae369c20fc56cccbb55b22043b9024 (patch)
tree072384a2c276661bcf31328d4df41d46df1300ff /util.c
parentf2520c27cd7942dc01d3386b4083b128648343c0 (diff)
downloaduci-818f7b8433ae369c20fc56cccbb55b22043b9024.tar.gz
move history code into history.c
Diffstat (limited to 'util.c')
-rw-r--r--util.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/util.c b/util.c
index c0f4451..e76ff6b 100644
--- a/util.c
+++ b/util.c
@@ -16,8 +16,16 @@
* This file contains wrappers to standard functions, which
* throw exceptions upon failure.
*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
#include <stdbool.h>
+#include <unistd.h>
#include <ctype.h>
+#include <fcntl.h>
+
+#define LINEBUF 32
+#define LINEBUF_MAX 4096
static void *uci_malloc(struct uci_context *ctx, size_t size)
{
@@ -114,3 +122,108 @@ done:
return 0;
}
+
+static void uci_parse_error(struct uci_context *ctx, char *pos, char *reason)
+{
+ struct uci_parse_context *pctx = ctx->pctx;
+
+ pctx->reason = reason;
+ pctx->byte = pos - pctx->buf;
+ UCI_THROW(ctx, UCI_ERR_PARSE);
+}
+
+
+/*
+ * Fetch a new line from the input stream and resize buffer if necessary
+ */
+static void uci_getln(struct uci_context *ctx, int offset)
+{
+ struct uci_parse_context *pctx = ctx->pctx;
+ char *p;
+ int ofs;
+
+ if (pctx->buf == NULL) {
+ pctx->buf = uci_malloc(ctx, LINEBUF);
+ pctx->bufsz = LINEBUF;
+ }
+
+ ofs = offset;
+ do {
+ p = &pctx->buf[ofs];
+ p[ofs] = 0;
+
+ p = fgets(p, pctx->bufsz - ofs, pctx->file);
+ if (!p || !*p)
+ return;
+
+ ofs += strlen(p);
+ if (pctx->buf[ofs - 1] == '\n') {
+ pctx->line++;
+ pctx->buf[ofs - 1] = 0;
+ return;
+ }
+
+ if (pctx->bufsz > LINEBUF_MAX/2)
+ uci_parse_error(ctx, p, "line too long");
+
+ pctx->bufsz *= 2;
+ pctx->buf = uci_realloc(ctx, pctx->buf, pctx->bufsz);
+ } while (1);
+}
+
+/*
+ * open a stream and go to the right position
+ *
+ * note: when opening for write and seeking to the beginning of
+ * the stream, truncate the file
+ */
+static FILE *uci_open_stream(struct uci_context *ctx, const char *filename, int pos, bool write, bool create)
+{
+ struct stat statbuf;
+ FILE *file = NULL;
+ int fd, ret;
+ int mode = (write ? O_RDWR : O_RDONLY);
+
+ if (create)
+ mode |= O_CREAT;
+
+ if (!write && ((stat(filename, &statbuf) < 0) ||
+ ((statbuf.st_mode & S_IFMT) != S_IFREG))) {
+ UCI_THROW(ctx, UCI_ERR_NOTFOUND);
+ }
+
+ fd = open(filename, mode, UCI_FILEMODE);
+ if (fd <= 0)
+ goto error;
+
+ if (flock(fd, (write ? LOCK_EX : LOCK_SH)) < 0)
+ goto error;
+
+ ret = lseek(fd, 0, pos);
+
+ if (ret < 0)
+ goto error;
+
+ file = fdopen(fd, (write ? "w+" : "r"));
+ if (file)
+ goto done;
+
+error:
+ UCI_THROW(ctx, UCI_ERR_IO);
+done:
+ return file;
+}
+
+static void uci_close_stream(FILE *stream)
+{
+ int fd;
+
+ if (!stream)
+ return;
+
+ fd = fileno(stream);
+ flock(fd, LOCK_UN);
+ fclose(stream);
+}
+
+