summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2012-08-29 10:27:12 +0200
committerYorhel <git@yorhel.nl>2012-08-29 10:27:12 +0200
commitc4616ff186495d1591430bc2dc1a911e1884e28a (patch)
tree39ab92674cbc528b07d77b07b231c0147c92f90b /src
parent7ccb98006a8da1fdaeab59efa3bc0520707d623f (diff)
Added simple error checking & handling when exporting
Diffstat (limited to 'src')
-rw-r--r--src/dir.h5
-rw-r--r--src/dir_export.c13
-rw-r--r--src/dir_mem.c6
-rw-r--r--src/dir_scan.c47
4 files changed, 51 insertions, 20 deletions
diff --git a/src/dir.h b/src/dir.h
index eded6ef..a5070a3 100644
--- a/src/dir.h
+++ b/src/dir.h
@@ -64,8 +64,11 @@ struct dir_output {
* All other fields/flags should be initialzed to NULL or 0.
* *item may be overwritten or freed in subsequent calls, so this function
* should make a copy if necessary.
+ *
+ * The function should return non-zero on error, at which point errno is
+ * assumed to be set to something sensible.
*/
- void (*item)(struct dir *);
+ int (*item)(struct dir *);
/* Finalizes the output to go to the next program state or exit ncdu. Called
* after item(NULL) has been called for the root item or before any item()
diff --git a/src/dir_export.c b/src/dir_export.c
index a9d2751..3d32c1a 100644
--- a/src/dir_export.c
+++ b/src/dir_export.c
@@ -100,15 +100,19 @@ static void output_info(struct dir *d) {
}
-/* TODO: Error handling / reporting! */
-static void item(struct dir *item) {
+/* Note on error handling: For convenience, we just keep writing to *stream
+ * without checking the return values of the functions. Only at the and of each
+ * item() call do we check for ferror(). This greatly simplifies the code, but
+ * assumes that calls to fwrite()/fput./etc don't do any weird stuff when
+ * called with a stream that's in an error state. */
+static int item(struct dir *item) {
if(!item) {
if(!--level) { /* closing of the root item */
fputs("]]", stream);
- fclose(stream);
+ return fclose(stream);
} else /* closing of a regular directory item */
fputs("]", stream);
- return;
+ return ferror(stream);
}
dir_output.items++;
@@ -123,6 +127,7 @@ static void item(struct dir *item) {
fputc('[', stream);
output_info(item);
+ return ferror(stream);
}
diff --git a/src/dir_mem.c b/src/dir_mem.c
index ce67525..3001c01 100644
--- a/src/dir_mem.c
+++ b/src/dir_mem.c
@@ -128,13 +128,13 @@ static void item_add(struct dir *item) {
}
-static void item(struct dir *item) {
+static int item(struct dir *item) {
struct dir *t;
/* Go back to parent dir */
if(!item) {
curdir = curdir->parent;
- return;
+ return 0;
}
item = item_copy(item);
@@ -165,6 +165,8 @@ static void item(struct dir *item) {
dir_output.size = root->size;
dir_output.items = root->items;
+
+ return 0;
}
diff --git a/src/dir_scan.c b/src/dir_scan.c
index a0efcb3..ee9b41d 100644
--- a/src/dir_scan.c
+++ b/src/dir_scan.c
@@ -125,16 +125,20 @@ static int dir_scan_recurse(struct dir *d) {
if(chdir(d->name)) {
dir_setlasterr(dir_curpath);
d->flags |= FF_ERR;
- dir_output.item(d);
- dir_output.item(NULL);
+ if(dir_output.item(d) || dir_output.item(NULL)) {
+ dir_seterr("Output error: %s", strerror(errno));
+ return 1;
+ }
return 0;
}
if((dir = dir_read(&fail)) == NULL) {
dir_setlasterr(dir_curpath);
d->flags |= FF_ERR;
- dir_output.item(d);
- dir_output.item(NULL);
+ if(dir_output.item(d) || dir_output.item(NULL)) {
+ dir_seterr("Output error: %s", strerror(errno));
+ return 1;
+ }
if(chdir("..")) {
dir_seterr("Error going back to parent directory: %s", strerror(errno));
return 1;
@@ -146,9 +150,15 @@ static int dir_scan_recurse(struct dir *d) {
if(fail)
d->flags |= FF_ERR;
- dir_output.item(d);
+ if(dir_output.item(d)) {
+ dir_seterr("Output error: %s", strerror(errno));
+ return 1;
+ }
fail = dir_walk(dir);
- dir_output.item(NULL);
+ if(dir_output.item(NULL)) {
+ dir_seterr("Output error: %s", strerror(errno));
+ return 1;
+ }
/* Not being able to chdir back is fatal */
if(!fail && chdir("..")) {
@@ -190,10 +200,14 @@ static int dir_scan_item(struct dir *d) {
if(d->flags & FF_DIR && !(d->flags & (FF_ERR|FF_EXL|FF_OTHFS)))
fail = dir_scan_recurse(d);
else if(d->flags & FF_DIR) {
- dir_output.item(d);
- dir_output.item(NULL);
- } else
- dir_output.item(d);
+ if(dir_output.item(d) || dir_output.item(NULL)) {
+ dir_seterr("Output error: %s", strerror(errno));
+ fail = 1;
+ }
+ } else if(dir_output.item(d)) {
+ dir_seterr("Output error: %s", strerror(errno));
+ fail = 1;
+ }
return fail || input_handle(1);
}
@@ -260,9 +274,16 @@ int dir_scan_process() {
d->flags |= FF_ERR;
stat_to_dir(d, &fs);
- dir_output.item(d);
- fail = dir_walk(dir);
- dir_output.item(NULL);
+ if(dir_output.item(d)) {
+ dir_seterr("Output error: %s", strerror(errno));
+ fail = 1;
+ }
+ if(!fail)
+ fail = dir_walk(dir);
+ if(!fail && dir_output.item(NULL)) {
+ dir_seterr("Output error: %s", strerror(errno));
+ fail = 1;
+ }
}
while(dir_fatalerr && !input_handle(0))