proper error handling for gw_get_repo_description()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
diff --git a/gotweb/gotweb.c b/gotweb/gotweb.c
index a445dd1..5e2390d 100644
--- a/gotweb/gotweb.c
+++ b/gotweb/gotweb.c
@@ -158,7 +158,7 @@ static const struct kvalid gw_keys[KEY__ZMAX] = {
static struct gw_dir *gw_init_gw_dir(char *);
static struct gw_header *gw_init_header(void);
-static char *gw_get_repo_description(struct gw_trans *,
+static const struct got_error *gw_get_repo_description(char **, struct gw_trans *,
char *);
static char *gw_get_repo_owner(struct gw_trans *,
char *);
@@ -306,6 +306,15 @@ gw_apply_unveil(const char *repo_path, const char *repo_file)
}
static const struct got_error *
+gw_empty_string(char **s)
+{
+ *s = strdup("");
+ if (*s == NULL)
+ return got_error_from_errno("strdup");
+ return NULL;
+}
+
+static const struct got_error *
gw_blame(struct gw_trans *gw_trans)
{
const struct got_error *error = NULL;
@@ -1034,8 +1043,10 @@ gw_load_got_path(struct gw_trans *gw_trans, struct gw_dir *gw_dir)
gw_dir->path = strdup(dir_test);
done:
- gw_dir->description = gw_get_repo_description(gw_trans,
+ error = gw_get_repo_description(&gw_dir->description, gw_trans,
gw_dir->path);
+ if (error)
+ goto errored;
gw_dir->owner = gw_get_repo_owner(gw_trans, gw_dir->path);
error = gw_get_repo_age(&gw_dir->age, gw_trans, gw_dir->path,
"refs/heads", TM_DIFF);
@@ -1427,42 +1438,60 @@ gw_gen_tree_header(char *str)
return return_html;
}
-static char *
-gw_get_repo_description(struct gw_trans *gw_trans, char *dir)
+static const struct got_error *
+gw_get_repo_description(char **description, struct gw_trans *gw_trans,
+ char *dir)
{
+ const struct got_error *error = NULL;
FILE *f = NULL;
- char *description = NULL, *d_file = NULL;
+ char *d_file = NULL;
unsigned int len;
+ ssize_t n;
+ *description = NULL;
if (gw_trans->gw_conf->got_show_repo_description == 0)
- goto err;
+ return gw_empty_string(description);
if (asprintf(&d_file, "%s/description", dir) == -1)
- goto err;
+ return got_error_from_errno("asprintf");
- if ((f = fopen(d_file, "r")) == NULL)
- goto err;
+ f = fopen(d_file, "r");
+ if (f == NULL) {
+ if (errno == ENOENT || errno == EACCES)
+ return gw_empty_string(description);
+ error = got_error_from_errno2("fopen", d_file);
+ goto done;
+ }
- if (fseek(f, 0, SEEK_END) == -1)
- goto err;
- len = ftell(f) + 1;
- if (ferror(f))
- goto err;
- if (fseek(f, 0, SEEK_SET) == -1)
- goto err;
- if ((description = calloc(len, sizeof(char *))) == NULL)
- goto err;
+ if (fseek(f, 0, SEEK_END) == -1) {
+ error = got_ferror(f, GOT_ERR_IO);
+ goto done;
+ }
+ len = ftell(f);
+ if (len == -1) {
+ error = got_ferror(f, GOT_ERR_IO);
+ goto done;
+ }
+ if (fseek(f, 0, SEEK_SET) == -1) {
+ error = got_ferror(f, GOT_ERR_IO);
+ goto done;
+ }
+ *description = calloc(len + 1, sizeof(**description));
+ if (*description == NULL) {
+ error = got_error_from_errno("calloc");
+ goto done;
+ }
- fread(description, 1, len, f);
- if (ferror(f))
- goto err;
- fclose(f);
+ n = fread(*description, 1, len, f);
+ if (n == -1) {
+ error = got_ferror(f, GOT_ERR_IO);
+ goto done;
+ }
+done:
+ if (f != NULL && fclose(f) == -1 && error == NULL)
+ error = got_error_from_errno("fclose");
free(d_file);
- return description;
-err:
- if (f != NULL)
- fclose(f);
- return strdup("");
+ return error;
}
static char *