-/*
- * 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);
-}
-
-static void uci_parse_history_line(struct uci_context *ctx, struct uci_package *p, char *buf)
-{
- bool delete = false;
- bool rename = false;
- char *package = NULL;
- char *section = NULL;
- char *option = NULL;
- char *value = NULL;
-
- if (buf[0] == '-') {
- delete = true;
- buf++;
- } else if (buf[0] == '@') {
- rename = true;
- buf++;
- }
-
- UCI_INTERNAL(uci_parse_tuple, ctx, buf, &package, §ion, &option, &value);
- if (!package || !section || (!delete && !value))
- goto error;
- if (strcmp(package, p->e.name) != 0)
- goto error;
- if (!uci_validate_name(section))
- goto error;
- if (option && !uci_validate_name(option))
- goto error;
-
- if (rename)
- UCI_INTERNAL(uci_rename, ctx, p, section, option, value);
- else if (delete)
- UCI_INTERNAL(uci_delete, ctx, p, section, option);
- else
- UCI_INTERNAL(uci_set, ctx, p, section, option, value);