/* scan-tree.c * * Copyright (C) 2006-2014 cgit Development Team * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" #include "scan-tree.h" #include "configfile.h" #include "html.h" #include /* return 1 if path contains a objects/ directory and a HEAD file */ static int is_git_dir(const char *path) { struct stat st; struct strbuf pathbuf = STRBUF_INIT; int result = 0; strbuf_addf(&pathbuf, "%s/objects", path); if (stat(pathbuf.buf, &st)) { if (errno != ENOENT) fprintf(stderr, "Error checking path %s: %s (%d)\n", path, strerror(errno), errno); goto out; } if (!S_ISDIR(st.st_mode)) goto out; strbuf_reset(&pathbuf); strbuf_addf(&pathbuf, "%s/HEAD", path); if (stat(pathbuf.buf, &st)) { if (errno != ENOENT) fprintf(stderr, "Error checking path %s: %s (%d)\n", path, strerror(errno), errno); goto out; } if (!S_ISREG(st.st_mode)) goto out; result = 1; out: strbuf_release(&pathbuf); return result; } static struct cgit_repo *repo; static repo_config_fn config_fn; static void scan_tree_repo_config(const char *name, const char *value) { config_fn(repo, name, value); } static int gitconfig_config(const char *key, const char *value, void *cb) { const char *name; if (!strcmp(key, "gitweb.owner")) config_fn(repo, "owner", value); else if (!strcmp(key, "gitweb.description")) config_fn(repo, "desc", value); else if (!strcmp(key, "gitweb.category")) config_fn(repo, "section", value); else if (!strcmp(key, "gitweb.homepage")) config_fn(repo, "homepage", value); else if (skip_prefix(key, "cgit.", &name)) config_fn(repo, name, value); return 0; } static char *xstrrchr(char *s, char *from, int c) { while (from >= s && *from != c) from--; return from < s ? NULL : from; } static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn) { struct stat st; struct passwd *pwd; size_t pathlen; struct strbuf rel = STRBUF_INIT; char *p, *slash; int n; size_t size; if (stat(path->buf, &st)) { fprintf(stderr, "Error accessing %s: %s (%d)\n", path->buf, strerror(errno), errno); return; } strbuf_addch(path, '/'); pathlen = path->len; if (ctx.cfg.strict_export) { strbuf_addstr(path, ctx.cfg.strict_export); if(stat(path->buf, &st)) return; strbuf_setlen(path, pathlen); } strbuf_addstr(path, "noweb"); if (!stat(path->buf, &st)) return; strbuf_setlen(path, pathlen); if (!starts_with(path->buf, base)) strbuf_addbuf(&rel, path); else strbuf_addstr(&rel, path->buf + strlen(base) + 1); if (!strcmp(rel.buf + rel.len - 5, "/.git")) strbuf_setlen(&rel, rel.len - 5); else if (rel.len && rel.buf[rel.len - 1] == '/') strbuf_setlen(&rel, rel.len - 1); repo = cgit_add_repo(rel.buf); config_fn = fn; if (ctx.cfg.enable_git_config) { strbuf_addstr(path, "config"); git_config_from_file(gitconfig_config, path->buf, NULL); strbuf_setlen(path, pathlen); } if (ctx.cfg.remove_su