improve stream read and write error handling - stagit-gopher - A git gopher fro… | |
git clone git://bitreich.org/stagit-gopher/ git://enlrupgkhuxnvlhsf6lc3fziv5h2h… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
commit cbb963db3795ea24cd0d68f73b415f9fc48922cc | |
parent 1dd611d990843966e50b23dac30617d6aa5b2b2e | |
Author: Hiltjo Posthuma <[email protected]> | |
Date: Sat, 19 Mar 2022 12:51:57 +0100 | |
improve stream read and write error handling | |
Diffstat: | |
M stagit-gopher-index.c | 13 +++++++++++++ | |
M stagit-gopher.c | 35 ++++++++++++++++++++++++-----… | |
2 files changed, 40 insertions(+), 8 deletions(-) | |
--- | |
diff --git a/stagit-gopher-index.c b/stagit-gopher-index.c | |
@@ -20,6 +20,16 @@ static const char *relpath = ""; | |
static char description[255] = "Repositories"; | |
static char *name = ""; | |
+/* Handle read or write errors for a FILE * stream */ | |
+void | |
+checkfileerror(FILE *fp, const char *name, int mode) | |
+{ | |
+ if (mode == 'r' && ferror(fp)) | |
+ errx(1, "read error: %s", name); | |
+ else if (mode == 'w' && (fflush(fp) || ferror(fp))) | |
+ errx(1, "write error: %s", name); | |
+} | |
+ | |
/* Format `len' columns of characters. If string is shorter pad the rest | |
* with characters `pad`. */ | |
int | |
@@ -289,6 +299,7 @@ main(int argc, char *argv[]) | |
description[strcspn(description, "\t\r\n")] = … | |
else | |
description[0] = '\0'; | |
+ checkfileerror(fp, "description", 'r'); | |
fclose(fp); | |
} | |
@@ -303,5 +314,7 @@ main(int argc, char *argv[]) | |
git_repository_free(repo); | |
git_libgit2_shutdown(); | |
+ checkfileerror(stdout, "<stdout>", 'w'); | |
+ | |
return ret; | |
} | |
diff --git a/stagit-gopher.c b/stagit-gopher.c | |
@@ -83,6 +83,16 @@ static char lastoidstr[GIT_OID_HEXSZ + 2]; /* id + newline +… | |
static FILE *rcachefp, *wcachefp; | |
static const char *cachefile; | |
+/* Handle read or write errors for a FILE * stream */ | |
+void | |
+checkfileerror(FILE *fp, const char *name, int mode) | |
+{ | |
+ if (mode == 'r' && ferror(fp)) | |
+ errx(1, "read error: %s", name); | |
+ else if (mode == 'w' && (fflush(fp) || ferror(fp))) | |
+ errx(1, "write error: %s", name); | |
+} | |
+ | |
/* Format `len' columns of characters. If string is shorter pad the rest | |
* with characters `pad`. */ | |
int | |
@@ -878,6 +888,7 @@ writelog(FILE *fp, const git_oid *oid) | |
writeheader(fpfile, ci->summary); | |
printshowfile(fpfile, ci); | |
writefooter(fpfile); | |
+ checkfileerror(fpfile, path, 'w'); | |
fclose(fpfile); | |
} | |
err: | |
@@ -1018,14 +1029,13 @@ writeblob(git_object *obj, const char *fpath, const cha… | |
fprintf(fp, " (%zuB)\n", filesize); | |
fputs("---\n", fp); | |
- if (git_blob_is_binary((git_blob *)obj)) { | |
+ if (git_blob_is_binary((git_blob *)obj)) | |
fputs("Binary file.\n", fp); | |
- } else { | |
+ else | |
lc = writeblobgph(fp, (git_blob *)obj); | |
- if (ferror(fp)) | |
- err(1, "fwrite"); | |
- } | |
+ | |
writefooter(fp); | |
+ checkfileerror(fp, fpath, 'w'); | |
fclose(fp); | |
return lc; | |
@@ -1337,6 +1347,7 @@ main(int argc, char *argv[]) | |
if (fpread) { | |
if (!fgets(description, sizeof(description), fpread)) | |
description[0] = '\0'; | |
+ checkfileerror(fpread, path, 'r'); | |
fclose(fpread); | |
} | |
@@ -1349,8 +1360,9 @@ main(int argc, char *argv[]) | |
if (fpread) { | |
if (!fgets(cloneurl, sizeof(cloneurl), fpread)) | |
cloneurl[0] = '\0'; | |
- cloneurl[strcspn(cloneurl, "\n")] = '\0'; | |
+ checkfileerror(fpread, path, 'r'); | |
fclose(fpread); | |
+ cloneurl[strcspn(cloneurl, "\n")] = '\0'; | |
} | |
/* check LICENSE */ | |
@@ -1408,13 +1420,15 @@ main(int argc, char *argv[]) | |
while (!feof(rcachefp)) { | |
n = fread(buf, 1, sizeof(buf), rcachefp); | |
if (ferror(rcachefp)) | |
- err(1, "fread"); | |
+ break; | |
if (fwrite(buf, 1, n, fp) != n || | |
fwrite(buf, 1, n, wcachefp) != n) | |
- err(1, "fwrite"); | |
+ break; | |
} | |
+ checkfileerror(rcachefp, cachefile, 'r'); | |
fclose(rcachefp); | |
} | |
+ checkfileerror(wcachefp, tmppath, 'w'); | |
fclose(wcachefp); | |
} else { | |
if (head) | |
@@ -1424,6 +1438,7 @@ main(int argc, char *argv[]) | |
fprintf(fp, "[0|Atom feed|%s/atom.xml|server|port]\n", relpath); | |
fprintf(fp, "[0|Atom feed (tags)|%s/tags.xml|server|port]\n", relpath); | |
writefooter(fp); | |
+ checkfileerror(fp, "log.gph", 'w'); | |
fclose(fp); | |
/* files for HEAD */ | |
@@ -1432,6 +1447,7 @@ main(int argc, char *argv[]) | |
if (head) | |
writefiles(fp, head); | |
writefooter(fp); | |
+ checkfileerror(fp, "files.gph", 'w'); | |
fclose(fp); | |
/* summary page with branches and tags */ | |
@@ -1439,16 +1455,19 @@ main(int argc, char *argv[]) | |
writeheader(fp, "Refs"); | |
writerefs(fp); | |
writefooter(fp); | |
+ checkfileerror(fp, "refs.gph", 'w'); | |
fclose(fp); | |
/* Atom feed */ | |
fp = efopen("atom.xml", "w"); | |
writeatom(fp, 1); | |
+ checkfileerror(fp, "atom.xml", 'w'); | |
fclose(fp); | |
/* Atom feed for tags / releases */ | |
fp = efopen("tags.xml", "w"); | |
writeatom(fp, 0); | |
+ checkfileerror(fp, "tags.xml", 'w'); | |
fclose(fp); | |
/* rename new cache file on success */ |