author | Simon Arlott <simon@fire.lp0.eu> | 2009-03-07 00:06:24 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2009-08-18 12:27:41 (UTC) |
commit | 011f2e9bdddcbfe65da397629bca87d167313a28 (patch) (side-by-side diff) | |
tree | 606b84a7b0211a6c4536bb508d57d4f19d20c3ab | |
parent | 6421dc38db02eff8d3ada93e87a2f7e5292af131 (diff) | |
download | cgit-011f2e9bdddcbfe65da397629bca87d167313a28.zip cgit-011f2e9bdddcbfe65da397629bca87d167313a28.tar.gz cgit-011f2e9bdddcbfe65da397629bca87d167313a28.tar.bz2 |
truncate buffer before reading empty files
If readfile() reads an empty file, fgets() won't truncate the buffer
and it'll still contain the contents of the previously read file.
[lh: fixed similar issue in ui-repolist.c]
Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | scan-tree.c | 1 | ||||
-rw-r--r-- | ui-repolist.c | 1 |
2 files changed, 2 insertions, 0 deletions
diff --git a/scan-tree.c b/scan-tree.c index cdafb02..47f3988 100644 --- a/scan-tree.c +++ b/scan-tree.c @@ -1,136 +1,137 @@ #include "cgit.h" #include "html.h" #define MAX_PATH 4096 /* return 1 if path contains a objects/ directory and a HEAD file */ static int is_git_dir(const char *path) { struct stat st; static char buf[MAX_PATH]; if (snprintf(buf, MAX_PATH, "%s/objects", path) >= MAX_PATH) { fprintf(stderr, "Insanely long path: %s\n", path); return 0; } if (stat(buf, &st)) { if (errno != ENOENT) fprintf(stderr, "Error checking path %s: %s (%d)\n", path, strerror(errno), errno); return 0; } if (!S_ISDIR(st.st_mode)) return 0; sprintf(buf, "%s/HEAD", path); if (stat(buf, &st)) { if (errno != ENOENT) fprintf(stderr, "Error checking path %s: %s (%d)\n", path, strerror(errno), errno); return 0; } if (!S_ISREG(st.st_mode)) return 0; return 1; } char *readfile(const char *path) { FILE *f; static char buf[MAX_PATH]; if (!(f = fopen(path, "r"))) return NULL; + buf[0] = 0; fgets(buf, MAX_PATH, f); fclose(f); return buf; } static void add_repo(const char *base, const char *path) { struct cgit_repo *repo; struct stat st; struct passwd *pwd; char *p; if (stat(path, &st)) { fprintf(stderr, "Error accessing %s: %s (%d)\n", path, strerror(errno), errno); return; } if ((pwd = getpwuid(st.st_uid)) == NULL) { fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", path, strerror(errno), errno); return; } if (base == path) p = fmt("%s", path); else p = fmt("%s", path + strlen(base) + 1); if (!strcmp(p + strlen(p) - 5, "/.git")) p[strlen(p) - 5] = '\0'; repo = cgit_add_repo(xstrdup(p)); repo->name = repo->url; repo->path = xstrdup(path); repo->owner = (pwd ? xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name) : ""); p = fmt("%s/description", path); if (!stat(p, &st)) repo->desc = xstrdup(readfile(p)); p = fmt("%s/README.html", path); if (!stat(p, &st)) repo->readme = "README.html"; } static void scan_path(const char *base, const char *path) { DIR *dir; struct dirent *ent; char *buf; struct stat st; if (is_git_dir(path)) { add_repo(base, path); return; } dir = opendir(path); if (!dir) { fprintf(stderr, "Error opening directory %s: %s (%d)\n", path, strerror(errno), errno); return; } while((ent = readdir(dir)) != NULL) { if (ent->d_name[0] == '.') { if (ent->d_name[1] == '\0') continue; if (ent->d_name[1] == '.' && ent->d_name[2] == '\0') continue; } buf = malloc(strlen(path) + strlen(ent->d_name) + 2); if (!buf) { fprintf(stderr, "Alloc error on %s: %s (%d)\n", path, strerror(errno), errno); exit(1); } sprintf(buf, "%s/%s", path, ent->d_name); if (stat(buf, &st)) { fprintf(stderr, "Error checking path %s: %s (%d)\n", buf, strerror(errno), errno); free(buf); continue; } if (S_ISDIR(st.st_mode)) scan_path(base, buf); free(buf); } closedir(dir); } void scan_tree(const char *path) { scan_path(path, path); } diff --git a/ui-repolist.c b/ui-repolist.c index 2c13d50..3aedde5 100644 --- a/ui-repolist.c +++ b/ui-repolist.c @@ -1,217 +1,218 @@ /* ui-repolist.c: functions for generating the repolist page * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ /* This is needed for strcasestr to be defined by <string.h> */ #define _GNU_SOURCE 1 #include <string.h> #include <time.h> #include "cgit.h" #include "html.h" #include "ui-shared.h" time_t read_agefile(char *path) { FILE *f; static char buf[64], buf2[64]; if (!(f = fopen(path, "r"))) return -1; + buf[0] = 0; if (fgets(buf, sizeof(buf), f) == NULL) return -1; fclose(f); if (parse_date(buf, buf2, sizeof(buf2))) return strtoul(buf2, NULL, 10); else return 0; } static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime) { char *path; struct stat s; struct cgit_repo *r = (struct cgit_repo *)repo; if (repo->mtime != -1) { *mtime = repo->mtime; return 1; } path = fmt("%s/%s", repo->path, ctx.cfg.agefile); if (stat(path, &s) == 0) { *mtime = read_agefile(path); r->mtime = *mtime; return 1; } path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); if (stat(path, &s) == 0) *mtime = s.st_mtime; else *mtime = 0; r->mtime = *mtime; return (r->mtime != 0); } static void print_modtime(struct cgit_repo *repo) { time_t t; if (get_repo_modtime(repo, &t)) cgit_print_age(t, -1, NULL); } int is_match(struct cgit_repo *repo) { if (!ctx.qry.search) return 1; if (repo->url && strcasestr(repo->url, ctx.qry.search)) return 1; if (repo->name && strcasestr(repo->name, ctx.qry.search)) return 1; if (repo->desc && strcasestr(repo->desc, ctx.qry.search)) return 1; if (repo->owner && strcasestr(repo->owner, ctx.qry.search)) return 1; return 0; } int is_in_url(struct cgit_repo *repo) { if (!ctx.qry.url) return 1; if (repo->url && !prefixcmp(repo->url, ctx.qry.url)) return 1; return 0; } void print_sort_header(const char *title, const char *sort) { htmlf("<th class='left'><a href='./?s=%s", sort); if (ctx.qry.search) { html("&q="); html_url_arg(ctx.qry.search); } htmlf("'>%s</a></th>", title); } void print_header(int columns) { html("<tr class='nohover'>"); print_sort_header("Name", "name"); print_sort_header("Description", "desc"); print_sort_header("Owner", "owner"); print_sort_header("Idle", "idle"); if (ctx.cfg.enable_index_links) html("<th class='left'>Links</th>"); html("</tr>\n"); } void print_pager(int items, int pagelen, char *search) { int i; html("<div class='pager'>"); for(i = 0; i * pagelen < items; i++) cgit_index_link(fmt("[%d]", i+1), fmt("Page %d", i+1), NULL, search, i * pagelen); html("</div>"); } static int cmp(const char *s1, const char *s2) { if (s1 && s2) return strcmp(s1, s2); if (s1 && !s2) return -1; if (s2 && !s1) return 1; return 0; } static int sort_name(const void *a, const void *b) { const struct cgit_repo *r1 = a; const struct cgit_repo *r2 = b; return cmp(r1->name, r2->name); } static int sort_desc(const void *a, const void *b) { const struct cgit_repo *r1 = a; const struct cgit_repo *r2 = b; return cmp(r1->desc, r2->desc); } static int sort_owner(const void *a, const void *b) { const struct cgit_repo *r1 = a; const struct cgit_repo *r2 = b; return cmp(r1->owner, r2->owner); } static int sort_idle(const void *a, const void *b) { const struct cgit_repo *r1 = a; const struct cgit_repo *r2 = b; time_t t1, t2; t1 = t2 = 0; get_repo_modtime(r1, &t1); get_repo_modtime(r2, &t2); return t2 - t1; } struct sortcolumn { const char *name; int (*fn)(const void *a, const void *b); }; struct sortcolumn sortcolumn[] = { {"name", sort_name}, {"desc", sort_desc}, {"owner", sort_owner}, {"idle", sort_idle}, {NULL, NULL} }; int sort_repolist(char *field) { struct sortcolumn *column; for (column = &sortcolumn[0]; column->name; column++) { if (strcmp(field, column->name)) continue; qsort(cgit_repolist.repos, cgit_repolist.count, sizeof(struct cgit_repo), column->fn); return 1; } return 0; } void cgit_print_repolist() { int i, columns = 4, hits = 0, header = 0; char *last_group = NULL; int sorted = 0; if (ctx.cfg.enable_index_links) columns++; ctx.page.title = ctx.cfg.root_title; cgit_print_http_headers(&ctx); cgit_print_docstart(&ctx); cgit_print_pageheader(&ctx); if (ctx.cfg.index_header) html_include(ctx.cfg.index_header); |