summaryrefslogtreecommitdiffabout
authorStefan Gehn <stefan@srcbox.net>2011-03-26 08:51:39 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2011-03-26 10:44:16 (UTC)
commitf15c5833d2190bc62e0e1e3e9753ef33230ecd53 (patch) (unidiff)
treea81dd18bd692d7a5fb00c38910b871c5ffc29464
parentcc59ee502646dc4e3d0f8bbe29b24c7fa3f0d2dd (diff)
downloadcgit-f15c5833d2190bc62e0e1e3e9753ef33230ecd53.zip
cgit-f15c5833d2190bc62e0e1e3e9753ef33230ecd53.tar.gz
cgit-f15c5833d2190bc62e0e1e3e9753ef33230ecd53.tar.bz2
Fix crash when projectsfile cannot be opened
This patch makes cgit properly abort in case the projectsfile cannot be opened. Without the added return cgit continues using the projects pointer which is NULL and thus causes a segfault.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--scan-tree.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/scan-tree.c b/scan-tree.c
index 627af1b..e5a4baf 100644
--- a/scan-tree.c
+++ b/scan-tree.c
@@ -30,212 +30,213 @@ static int is_git_dir(const char *path)
30 return 0; 30 return 0;
31 } 31 }
32 if (!S_ISDIR(st.st_mode)) 32 if (!S_ISDIR(st.st_mode))
33 return 0; 33 return 0;
34 34
35 sprintf(buf, "%s/HEAD", path); 35 sprintf(buf, "%s/HEAD", path);
36 if (stat(buf, &st)) { 36 if (stat(buf, &st)) {
37 if (errno != ENOENT) 37 if (errno != ENOENT)
38 fprintf(stderr, "Error checking path %s: %s (%d)\n", 38 fprintf(stderr, "Error checking path %s: %s (%d)\n",
39 path, strerror(errno), errno); 39 path, strerror(errno), errno);
40 return 0; 40 return 0;
41 } 41 }
42 if (!S_ISREG(st.st_mode)) 42 if (!S_ISREG(st.st_mode))
43 return 0; 43 return 0;
44 44
45 return 1; 45 return 1;
46} 46}
47 47
48struct cgit_repo *repo; 48struct cgit_repo *repo;
49repo_config_fn config_fn; 49repo_config_fn config_fn;
50char *owner; 50char *owner;
51 51
52static void repo_config(const char *name, const char *value) 52static void repo_config(const char *name, const char *value)
53{ 53{
54 config_fn(repo, name, value); 54 config_fn(repo, name, value);
55} 55}
56 56
57static int git_owner_config(const char *key, const char *value, void *cb) 57static int git_owner_config(const char *key, const char *value, void *cb)
58{ 58{
59 if (!strcmp(key, "gitweb.owner")) 59 if (!strcmp(key, "gitweb.owner"))
60 owner = xstrdup(value); 60 owner = xstrdup(value);
61 return 0; 61 return 0;
62} 62}
63 63
64static char *xstrrchr(char *s, char *from, int c) 64static char *xstrrchr(char *s, char *from, int c)
65{ 65{
66 while (from >= s && *from != c) 66 while (from >= s && *from != c)
67 from--; 67 from--;
68 return from < s ? NULL : from; 68 return from < s ? NULL : from;
69} 69}
70 70
71static void add_repo(const char *base, const char *path, repo_config_fn fn) 71static void add_repo(const char *base, const char *path, repo_config_fn fn)
72{ 72{
73 struct stat st; 73 struct stat st;
74 struct passwd *pwd; 74 struct passwd *pwd;
75 char *rel, *p, *slash; 75 char *rel, *p, *slash;
76 int n; 76 int n;
77 size_t size; 77 size_t size;
78 78
79 if (stat(path, &st)) { 79 if (stat(path, &st)) {
80 fprintf(stderr, "Error accessing %s: %s (%d)\n", 80 fprintf(stderr, "Error accessing %s: %s (%d)\n",
81 path, strerror(errno), errno); 81 path, strerror(errno), errno);
82 return; 82 return;
83 } 83 }
84 84
85 if (ctx.cfg.strict_export && stat(fmt("%s/%s", path, ctx.cfg.strict_export), &st)) 85 if (ctx.cfg.strict_export && stat(fmt("%s/%s", path, ctx.cfg.strict_export), &st))
86 return; 86 return;
87 87
88 if (!stat(fmt("%s/noweb", path), &st)) 88 if (!stat(fmt("%s/noweb", path), &st))
89 return; 89 return;
90 90
91 owner = NULL; 91 owner = NULL;
92 if (ctx.cfg.enable_gitweb_owner) 92 if (ctx.cfg.enable_gitweb_owner)
93 git_config_from_file(git_owner_config, fmt("%s/config", path), NULL); 93 git_config_from_file(git_owner_config, fmt("%s/config", path), NULL);
94 if (base == path) 94 if (base == path)
95 rel = xstrdup(fmt("%s", path)); 95 rel = xstrdup(fmt("%s", path));
96 else 96 else
97 rel = xstrdup(fmt("%s", path + strlen(base) + 1)); 97 rel = xstrdup(fmt("%s", path + strlen(base) + 1));
98 98
99 if (!strcmp(rel + strlen(rel) - 5, "/.git")) 99 if (!strcmp(rel + strlen(rel) - 5, "/.git"))
100 rel[strlen(rel) - 5] = '\0'; 100 rel[strlen(rel) - 5] = '\0';
101 101
102 repo = cgit_add_repo(rel); 102 repo = cgit_add_repo(rel);
103 if (ctx.cfg.remove_suffix) 103 if (ctx.cfg.remove_suffix)
104 if ((p = strrchr(repo->url, '.')) && !strcmp(p, ".git")) 104 if ((p = strrchr(repo->url, '.')) && !strcmp(p, ".git"))
105 *p = '\0'; 105 *p = '\0';
106 repo->name = repo->url; 106 repo->name = repo->url;
107 repo->path = xstrdup(path); 107 repo->path = xstrdup(path);
108 while (!owner) { 108 while (!owner) {
109 if ((pwd = getpwuid(st.st_uid)) == NULL) { 109 if ((pwd = getpwuid(st.st_uid)) == NULL) {
110 fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", 110 fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n",
111 path, strerror(errno), errno); 111 path, strerror(errno), errno);
112 break; 112 break;
113 } 113 }
114 if (pwd->pw_gecos) 114 if (pwd->pw_gecos)
115 if ((p = strchr(pwd->pw_gecos, ','))) 115 if ((p = strchr(pwd->pw_gecos, ',')))
116 *p = '\0'; 116 *p = '\0';
117 owner = xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name); 117 owner = xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name);
118 } 118 }
119 repo->owner = owner; 119 repo->owner = owner;
120 120
121 p = fmt("%s/description", path); 121 p = fmt("%s/description", path);
122 if (!stat(p, &st)) 122 if (!stat(p, &st))
123 readfile(p, &repo->desc, &size); 123 readfile(p, &repo->desc, &size);
124 124
125 if (!repo->readme) { 125 if (!repo->readme) {
126 p = fmt("%s/README.html", path); 126 p = fmt("%s/README.html", path);
127 if (!stat(p, &st)) 127 if (!stat(p, &st))
128 repo->readme = "README.html"; 128 repo->readme = "README.html";
129 } 129 }
130 if (ctx.cfg.section_from_path) { 130 if (ctx.cfg.section_from_path) {
131 n = ctx.cfg.section_from_path; 131 n = ctx.cfg.section_from_path;
132 if (n > 0) { 132 if (n > 0) {
133 slash = rel; 133 slash = rel;
134 while (slash && n && (slash = strchr(slash, '/'))) 134 while (slash && n && (slash = strchr(slash, '/')))
135 n--; 135 n--;
136 } else { 136 } else {
137 slash = rel + strlen(rel); 137 slash = rel + strlen(rel);
138 while (slash && n && (slash = xstrrchr(rel, slash, '/'))) 138 while (slash && n && (slash = xstrrchr(rel, slash, '/')))
139 n++; 139 n++;
140 } 140 }
141 if (slash && !n) { 141 if (slash && !n) {
142 *slash = '\0'; 142 *slash = '\0';
143 repo->section = xstrdup(rel); 143 repo->section = xstrdup(rel);
144 *slash = '/'; 144 *slash = '/';
145 if (!prefixcmp(repo->name, repo->section)) { 145 if (!prefixcmp(repo->name, repo->section)) {
146 repo->name += strlen(repo->section); 146 repo->name += strlen(repo->section);
147 if (*repo->name == '/') 147 if (*repo->name == '/')
148 repo->name++; 148 repo->name++;
149 } 149 }
150 } 150 }
151 } 151 }
152 152
153 p = fmt("%s/cgitrc", path); 153 p = fmt("%s/cgitrc", path);
154 if (!stat(p, &st)) { 154 if (!stat(p, &st)) {
155 config_fn = fn; 155 config_fn = fn;
156 parse_configfile(xstrdup(p), &repo_config); 156 parse_configfile(xstrdup(p), &repo_config);
157 } 157 }
158} 158}
159 159
160static void scan_path(const char *base, const char *path, repo_config_fn fn) 160static void scan_path(const char *base, const char *path, repo_config_fn fn)
161{ 161{
162 DIR *dir = opendir(path); 162 DIR *dir = opendir(path);
163 struct dirent *ent; 163 struct dirent *ent;
164 char *buf; 164 char *buf;
165 struct stat st; 165 struct stat st;
166 166
167 if (!dir) { 167 if (!dir) {
168 fprintf(stderr, "Error opening directory %s: %s (%d)\n", 168 fprintf(stderr, "Error opening directory %s: %s (%d)\n",
169 path, strerror(errno), errno); 169 path, strerror(errno), errno);
170 return; 170 return;
171 } 171 }
172 if (is_git_dir(path)) { 172 if (is_git_dir(path)) {
173 add_repo(base, path, fn); 173 add_repo(base, path, fn);
174 goto end; 174 goto end;
175 } 175 }
176 if (is_git_dir(fmt("%s/.git", path))) { 176 if (is_git_dir(fmt("%s/.git", path))) {
177 add_repo(base, fmt("%s/.git", path), fn); 177 add_repo(base, fmt("%s/.git", path), fn);
178 goto end; 178 goto end;
179 } 179 }
180 while((ent = readdir(dir)) != NULL) { 180 while((ent = readdir(dir)) != NULL) {
181 if (ent->d_name[0] == '.') { 181 if (ent->d_name[0] == '.') {
182 if (ent->d_name[1] == '\0') 182 if (ent->d_name[1] == '\0')
183 continue; 183 continue;
184 if (ent->d_name[1] == '.' && ent->d_name[2] == '\0') 184 if (ent->d_name[1] == '.' && ent->d_name[2] == '\0')
185 continue; 185 continue;
186 if (!ctx.cfg.scan_hidden_path) 186 if (!ctx.cfg.scan_hidden_path)
187 continue; 187 continue;
188 } 188 }
189 buf = malloc(strlen(path) + strlen(ent->d_name) + 2); 189 buf = malloc(strlen(path) + strlen(ent->d_name) + 2);
190 if (!buf) { 190 if (!buf) {
191 fprintf(stderr, "Alloc error on %s: %s (%d)\n", 191 fprintf(stderr, "Alloc error on %s: %s (%d)\n",
192 path, strerror(errno), errno); 192 path, strerror(errno), errno);
193 exit(1); 193 exit(1);
194 } 194 }
195 sprintf(buf, "%s/%s", path, ent->d_name); 195 sprintf(buf, "%s/%s", path, ent->d_name);
196 if (stat(buf, &st)) { 196 if (stat(buf, &st)) {
197 fprintf(stderr, "Error checking path %s: %s (%d)\n", 197 fprintf(stderr, "Error checking path %s: %s (%d)\n",
198 buf, strerror(errno), errno); 198 buf, strerror(errno), errno);
199 free(buf); 199 free(buf);
200 continue; 200 continue;
201 } 201 }
202 if (S_ISDIR(st.st_mode)) 202 if (S_ISDIR(st.st_mode))
203 scan_path(base, buf, fn); 203 scan_path(base, buf, fn);
204 free(buf); 204 free(buf);
205 } 205 }
206end: 206end:
207 closedir(dir); 207 closedir(dir);
208} 208}
209 209
210#define lastc(s) s[strlen(s) - 1] 210#define lastc(s) s[strlen(s) - 1]
211 211
212void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn) 212void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn)
213{ 213{
214 char line[MAX_PATH * 2], *z; 214 char line[MAX_PATH * 2], *z;
215 FILE *projects; 215 FILE *projects;
216 int err; 216 int err;
217 217
218 projects = fopen(projectsfile, "r"); 218 projects = fopen(projectsfile, "r");
219 if (!projects) { 219 if (!projects) {
220 fprintf(stderr, "Error opening projectsfile %s: %s (%d)\n", 220 fprintf(stderr, "Error opening projectsfile %s: %s (%d)\n",
221 projectsfile, strerror(errno), errno); 221 projectsfile, strerror(errno), errno);
222 return;
222 } 223 }
223 while (fgets(line, sizeof(line), projects) != NULL) { 224 while (fgets(line, sizeof(line), projects) != NULL) {
224 for (z = &lastc(line); 225 for (z = &lastc(line);
225 strlen(line) && strchr("\n\r", *z); 226 strlen(line) && strchr("\n\r", *z);
226 z = &lastc(line)) 227 z = &lastc(line))
227 *z = '\0'; 228 *z = '\0';
228 if (strlen(line)) 229 if (strlen(line))
229 scan_path(path, fmt("%s/%s", path, line), fn); 230 scan_path(path, fmt("%s/%s", path, line), fn);
230 } 231 }
231 if ((err = ferror(projects))) { 232 if ((err = ferror(projects))) {
232 fprintf(stderr, "Error reading from projectsfile %s: %s (%d)\n", 233 fprintf(stderr, "Error reading from projectsfile %s: %s (%d)\n",
233 projectsfile, strerror(err), err); 234 projectsfile, strerror(err), err);
234 } 235 }
235 fclose(projects); 236 fclose(projects);
236} 237}
237 238
238void scan_tree(const char *path, repo_config_fn fn) 239void scan_tree(const char *path, repo_config_fn fn)
239{ 240{
240 scan_path(path, path, fn); 241 scan_path(path, path, fn);
241} 242}