@@ -613,33 +613,47 @@ static void uci_export_package(struct uci_package *p, FILE *stream, bool header)
struct uci_element *s, *o, *i;
if (header)
- fprintf(stream, "package %s\n", uci_escape(ctx, p->e.name));
+ if(fprintf(stream, "package %s\n", uci_escape(ctx, p->e.name)) < 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
+
uci_foreach_element(&p->sections, s) {
struct uci_section *sec = uci_to_section(s);
- fprintf(stream, "\nconfig %s", uci_escape(ctx, sec->type));
+ if(fprintf(stream, "\nconfig %s", uci_escape(ctx, sec->type)) < 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
+
if (!sec->anonymous || (ctx->flags & UCI_FLAG_EXPORT_NAME))
- fprintf(stream, " '%s'", uci_escape(ctx, sec->e.name));
- fprintf(stream, "\n");
+ {
+ if(fprintf(stream, " '%s'", uci_escape(ctx, sec->e.name)) < 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
+ }
+ if(fprintf(stream, "\n") < 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
uci_foreach_element(&sec->options, o) {
struct uci_option *opt = uci_to_option(o);
switch(opt->type) {
case UCI_TYPE_STRING:
- fprintf(stream, "\toption %s", uci_escape(ctx, opt->e.name));
- fprintf(stream, " '%s'\n", uci_escape(ctx, opt->v.string));
+ if(fprintf(stream, "\toption %s", uci_escape(ctx, opt->e.name)) < 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
+ if(fprintf(stream, " '%s'\n", uci_escape(ctx, opt->v.string)) < 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
break;
case UCI_TYPE_LIST:
uci_foreach_element(&opt->v.list, i) {
- fprintf(stream, "\tlist %s", uci_escape(ctx, opt->e.name));
- fprintf(stream, " '%s'\n", uci_escape(ctx, i->name));
+ if(fprintf(stream, "\tlist %s", uci_escape(ctx, opt->e.name)) < 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
+ if(fprintf(stream, " '%s'\n", uci_escape(ctx, i->name)) < 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
}
break;
default:
- fprintf(stream, "\t# unknown type for option '%s'\n", uci_escape(ctx, opt->e.name));
+ if(fprintf(stream, "\t# unknown type for option '%s'\n", uci_escape(ctx, opt->e.name)) < 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
break;
}
}
}
- fprintf(stream, "\n");
+ if(fprintf(stream, "\n") < 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
}
int uci_export(struct uci_context *ctx, FILE *stream, struct uci_package *package, bool header)
@@ -649,6 +663,8 @@ int uci_export(struct uci_context *ctx, FILE *stream, struct uci_package *packag
UCI_HANDLE_ERR(ctx);
UCI_ASSERT(ctx, stream != NULL);
+ UCI_TRAP_SAVE(ctx, error);
+
if (package)
uci_export_package(package, stream, header);
else {
@@ -657,7 +673,12 @@ int uci_export(struct uci_context *ctx, FILE *stream, struct uci_package *packag
}
}
+ UCI_TRAP_RESTORE(ctx);
+
return 0;
+
+error:
+ return -1;
}
int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct uci_package **package, bool single)
@@ -800,10 +821,12 @@ static void uci_file_commit(struct uci_context *ctx, struct uci_package **packag
if (!f2)
UCI_THROW(ctx, UCI_ERR_IO);
- uci_export(ctx, f2, p, false);
+ UCI_INTERNAL(uci_export, ctx, f2, p, false);
- fflush(f2);
- fsync(fileno(f2));
+ if(fflush(f2) != 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
+ if(fsync(fileno(f2)) != 0)
+ UCI_THROW(ctx, UCI_ERR_IO);
uci_close_stream(f2);
do_rename = true;
Currently there is no error checking that uci write is successful. When file system is full, the temporary file can be created, but no contents can be written to it. This empty file is then renamed over the previous valid uci file. This patch adds error handling to all file write functions to prevent this. Signed-off-by: Reuben Dowle <reuben.dowle@4rf.com> --- file.c | 49 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 13 deletions(-)