Warmcat homepage andy@warmcat.com
libwebsockets
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"", "gen_ut":1714045483, "reponame":"cgit", "desc":"CGI gitweb", "owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://warmcat.com/repo/cgit", "f":3, "items": [ {"schema":"libjg2-1", "cid":"d0ca7a9ffff0a6d09ddf627e34c6eae2", "oid":{ "oid": "d1bb699526842f656f7afa799431003ab285dac2", "alias": [ "refs/heads/decruft","refs/heads/master"]},"blobname": "shared.c", "blob": "/* shared.c: global vars + some callback functions\n *\n * Copyright (C) 2006-2014 cgit Development Team \u003ccgit@lists.zx2c4.com\u003e\n *\n * Licensed under GNU General Public License v2\n * (see COPYING for full license text)\n */\n\n#include \u0022cgit.h\u0022\n\nstruct cgit_repolist cgit_repolist;\nstruct cgit_context ctx;\n\nint chk_zero(int result, char *msg)\n{\n\tif (result !\u003d 0)\n\t\tdie_errno(\u0022%s\u0022, msg);\n\treturn result;\n}\n\nint chk_positive(int result, char *msg)\n{\n\tif (result \u003c\u003d 0)\n\t\tdie_errno(\u0022%s\u0022, msg);\n\treturn result;\n}\n\nint chk_non_negative(int result, char *msg)\n{\n\tif (result \u003c 0)\n\t\tdie_errno(\u0022%s\u0022, msg);\n\treturn result;\n}\n\nchar *cgit_default_repo_desc \u003d \u0022[no description]\u0022;\nstruct cgit_repo *cgit_add_repo(const char *url)\n{\n\tstruct cgit_repo *ret;\n\n\tif (++cgit_repolist.count \u003e cgit_repolist.length) {\n\t\tif (cgit_repolist.length \u003d\u003d 0)\n\t\t\tcgit_repolist.length \u003d 8;\n\t\telse\n\t\t\tcgit_repolist.length *\u003d 2;\n\t\tcgit_repolist.repos \u003d xrealloc(cgit_repolist.repos,\n\t\t\t\t\t cgit_repolist.length *\n\t\t\t\t\t sizeof(struct cgit_repo));\n\t}\n\n\tret \u003d \u0026cgit_repolist.repos[cgit_repolist.count-1];\n\tmemset(ret, 0, sizeof(struct cgit_repo));\n\tret-\u003eurl \u003d trim_end(url, '/');\n\tret-\u003ename \u003d ret-\u003eurl;\n\tret-\u003epath \u003d NULL;\n\tret-\u003edesc \u003d cgit_default_repo_desc;\n\tret-\u003eowner \u003d NULL;\n\tret-\u003ehomepage \u003d NULL;\n\tret-\u003esection \u003d ctx.cfg.section;\n\tret-\u003esnapshots \u003d ctx.cfg.snapshots;\n\tret-\u003eenable_commit_graph \u003d ctx.cfg.enable_commit_graph;\n\tret-\u003eenable_log_filecount \u003d ctx.cfg.enable_log_filecount;\n\tret-\u003eenable_log_linecount \u003d ctx.cfg.enable_log_linecount;\n\tret-\u003eenable_remote_branches \u003d ctx.cfg.enable_remote_branches;\n\tret-\u003eenable_subject_links \u003d ctx.cfg.enable_subject_links;\n\tret-\u003eenable_html_serving \u003d ctx.cfg.enable_html_serving;\n\tret-\u003emax_stats \u003d ctx.cfg.max_stats;\n\tret-\u003ebranch_sort \u003d ctx.cfg.branch_sort;\n\tret-\u003ecommit_sort \u003d ctx.cfg.commit_sort;\n\tret-\u003emodule_link \u003d ctx.cfg.module_link;\n\tret-\u003ereadme \u003d ctx.cfg.readme;\n\tret-\u003emtime \u003d -1;\n\tret-\u003ecommit_filter \u003d ctx.cfg.commit_filter;\n\tret-\u003esource_filter \u003d ctx.cfg.source_filter;\n\tret-\u003eemail_filter \u003d ctx.cfg.email_filter;\n\tret-\u003eclone_url \u003d ctx.cfg.clone_url;\n\tret-\u003esubmodules.strdup_strings \u003d 1;\n\tret-\u003ehide \u003d ret-\u003eignore \u003d 0;\n\tret-\u003einline_readme \u003d ctx.cfg.inline_readme;\n\n\treturn ret;\n}\n\nstruct cgit_repo *cgit_get_repoinfo(const char *url)\n{\n\tint i;\n\tstruct cgit_repo *repo;\n\n\tfor (i \u003d 0; i \u003c cgit_repolist.count; i++) {\n\t\trepo \u003d \u0026cgit_repolist.repos[i];\n\t\tif (repo-\u003eignore)\n\t\t\tcontinue;\n\t\tif (!strcmp(repo-\u003eurl, url))\n\t\t\treturn repo;\n\t}\n\treturn NULL;\n}\n\nvoid cgit_free_commitinfo(struct commitinfo *info)\n{\n\tfree(info-\u003eauthor);\n\tfree(info-\u003eauthor_email);\n\tfree(info-\u003ecommitter);\n\tfree(info-\u003ecommitter_email);\n\tfree(info-\u003esubject);\n\tfree(info-\u003emsg);\n\tfree(info-\u003emsg_encoding);\n\tfree(info);\n}\n\nchar *trim_end(const char *str, char c)\n{\n\tint len;\n\n\tif (str \u003d\u003d NULL)\n\t\treturn NULL;\n\tlen \u003d strlen(str);\n\twhile (len \u003e 0 \u0026\u0026 str[len - 1] \u003d\u003d c)\n\t\tlen--;\n\tif (len \u003d\u003d 0)\n\t\treturn NULL;\n\treturn xstrndup(str, len);\n}\n\nchar *ensure_end(const char *str, char c)\n{\n\tsize_t len \u003d strlen(str);\n\tchar *result;\n\n\tif (len \u0026\u0026 str[len - 1] \u003d\u003d c)\n\t\treturn xstrndup(str, len);\n\n\tresult \u003d xmalloc(len + 2);\n\tmemcpy(result, str, len);\n\tresult[len] \u003d '/';\n\tresult[len + 1] \u003d '\u005c0';\n\treturn result;\n}\n\nvoid strbuf_ensure_end(struct strbuf *sb, char c)\n{\n\tif (!sb-\u003elen || sb-\u003ebuf[sb-\u003elen - 1] !\u003d c)\n\t\tstrbuf_addch(sb, c);\n}\n\nvoid cgit_add_ref(struct reflist *list, struct refinfo *ref)\n{\n\tsize_t size;\n\n\tif (list-\u003ecount \u003e\u003d list-\u003ealloc) {\n\t\tlist-\u003ealloc +\u003d (list-\u003ealloc ? list-\u003ealloc : 4);\n\t\tsize \u003d list-\u003ealloc * sizeof(struct refinfo *);\n\t\tlist-\u003erefs \u003d xrealloc(list-\u003erefs, size);\n\t}\n\tlist-\u003erefs[list-\u003ecount++] \u003d ref;\n}\n\nstatic struct refinfo *cgit_mk_refinfo(const char *refname, const struct object_id *oid)\n{\n\tstruct refinfo *ref;\n\n\tref \u003d xmalloc(sizeof (struct refinfo));\n\tref-\u003erefname \u003d xstrdup(refname);\n\tref-\u003eobject \u003d parse_object(oid);\n\tswitch (ref-\u003eobject-\u003etype) {\n\tcase OBJ_TAG:\n\t\tref-\u003etag \u003d cgit_parse_tag((struct tag *)ref-\u003eobject);\n\t\tbreak;\n\tcase OBJ_COMMIT:\n\t\tref-\u003ecommit \u003d cgit_parse_commit((struct commit *)ref-\u003eobject);\n\t\tbreak;\n\t}\n\treturn ref;\n}\n\nvoid cgit_free_taginfo(struct taginfo *tag)\n{\n\tif (tag-\u003etagger)\n\t\tfree(tag-\u003etagger);\n\tif (tag-\u003etagger_email)\n\t\tfree(tag-\u003etagger_email);\n\tif (tag-\u003emsg)\n\t\tfree(tag-\u003emsg);\n\tfree(tag);\n}\n\nstatic void cgit_free_refinfo(struct refinfo *ref)\n{\n\tif (ref-\u003erefname)\n\t\tfree((char *)ref-\u003erefname);\n\tswitch (ref-\u003eobject-\u003etype) {\n\tcase OBJ_TAG:\n\t\tcgit_free_taginfo(ref-\u003etag);\n\t\tbreak;\n\tcase OBJ_COMMIT:\n\t\tcgit_free_commitinfo(ref-\u003ecommit);\n\t\tbreak;\n\t}\n\tfree(ref);\n}\n\nvoid cgit_free_reflist_inner(struct reflist *list)\n{\n\tint i;\n\n\tfor (i \u003d 0; i \u003c list-\u003ecount; i++) {\n\t\tcgit_free_refinfo(list-\u003erefs[i]);\n\t}\n\tfree(list-\u003erefs);\n}\n\nint cgit_refs_cb(const char *refname, const struct object_id *oid, int flags,\n\t\t void *cb_data)\n{\n\tstruct reflist *list \u003d (struct reflist *)cb_data;\n\tstruct refinfo *info \u003d cgit_mk_refinfo(refname, oid);\n\n\tif (info)\n\t\tcgit_add_ref(list, info);\n\treturn 0;\n}\n\nvoid cgit_diff_tree_cb(struct diff_queue_struct *q,\n\t\t struct diff_options *options, void *data)\n{\n\tint i;\n\n\tfor (i \u003d 0; i \u003c q-\u003enr; i++) {\n\t\tif (q-\u003equeue[i]-\u003estatus \u003d\u003d 'U')\n\t\t\tcontinue;\n\t\t((filepair_fn)data)(q-\u003equeue[i]);\n\t}\n}\n\nstatic int load_mmfile(mmfile_t *file, const struct object_id *oid)\n{\n\tenum object_type type;\n\n\tif (is_null_oid(oid)) {\n\t\tfile-\u003eptr \u003d (char *)\u0022\u0022;\n\t\tfile-\u003esize \u003d 0;\n\t} else {\n\t\tfile-\u003eptr \u003d read_object_file(oid, \u0026type,\n\t\t (unsigned long *)\u0026file-\u003esize);\n\t}\n\treturn 1;\n}\n\n/*\n * Receive diff-buffers from xdiff and concatenate them as\n * needed across multiple callbacks.\n *\n * This is basically a copy of xdiff-interface.c/xdiff_outf(),\n * ripped from git and modified to use globals instead of\n * a special callback-struct.\n */\nstatic char *diffbuf \u003d NULL;\nstatic int buflen \u003d 0;\n\nstatic int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf)\n{\n\tint i;\n\n\tfor (i \u003d 0; i \u003c nbuf; i++) {\n\t\tif (mb[i].ptr[mb[i].size-1] !\u003d '\u005cn') {\n\t\t\t/* Incomplete line */\n\t\t\tdiffbuf \u003d xrealloc(diffbuf, buflen + mb[i].size);\n\t\t\tmemcpy(diffbuf + buflen, mb[i].ptr, mb[i].size);\n\t\t\tbuflen +\u003d mb[i].size;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* we have a complete line */\n\t\tif (!diffbuf) {\n\t\t\t((linediff_fn)priv)(mb[i].ptr, mb[i].size);\n\t\t\tcontinue;\n\t\t}\n\t\tdiffbuf \u003d xrealloc(diffbuf, buflen + mb[i].size);\n\t\tmemcpy(diffbuf + buflen, mb[i].ptr, mb[i].size);\n\t\t((linediff_fn)priv)(diffbuf, buflen + mb[i].size);\n\t\tfree(diffbuf);\n\t\tdiffbuf \u003d NULL;\n\t\tbuflen \u003d 0;\n\t}\n\tif (diffbuf) {\n\t\t((linediff_fn)priv)(diffbuf, buflen);\n\t\tfree(diffbuf);\n\t\tdiffbuf \u003d NULL;\n\t\tbuflen \u003d 0;\n\t}\n\treturn 0;\n}\n\nint cgit_diff_files(const struct object_id *old_oid,\n\t\t const struct object_id *new_oid, unsigned long *old_size,\n\t\t unsigned long *new_size, int *binary, int context,\n\t\t int ignorews, linediff_fn fn)\n{\n\tmmfile_t file1, file2;\n\txpparam_t diff_params;\n\txdemitconf_t emit_params;\n\txdemitcb_t emit_cb;\n\n\tif (!load_mmfile(\u0026file1, old_oid) || !load_mmfile(\u0026file2, new_oid))\n\t\treturn 1;\n\n\t*old_size \u003d file1.size;\n\t*new_size \u003d file2.size;\n\n\tif ((file1.ptr \u0026\u0026 buffer_is_binary(file1.ptr, file1.size)) ||\n\t (file2.ptr \u0026\u0026 buffer_is_binary(file2.ptr, file2.size))) {\n\t\t*binary \u003d 1;\n\t\tif (file1.size)\n\t\t\tfree(file1.ptr);\n\t\tif (file2.size)\n\t\t\tfree(file2.ptr);\n\t\treturn 0;\n\t}\n\n\tmemset(\u0026diff_params, 0, sizeof(diff_params));\n\tmemset(\u0026emit_params, 0, sizeof(emit_params));\n\tmemset(\u0026emit_cb, 0, sizeof(emit_cb));\n\tdiff_params.flags \u003d XDF_NEED_MINIMAL;\n\tif (ignorews)\n\t\tdiff_params.flags |\u003d XDF_IGNORE_WHITESPACE;\n\temit_params.ctxlen \u003d context \u003e 0 ? context : 3;\n\temit_params.flags \u003d XDL_EMIT_FUNCNAMES;\n\temit_cb.outf \u003d filediff_cb;\n\temit_cb.priv \u003d fn;\n\txdl_diff(\u0026file1, \u0026file2, \u0026diff_params, \u0026emit_params, \u0026emit_cb);\n\tif (file1.size)\n\t\tfree(file1.ptr);\n\tif (file2.size)\n\t\tfree(file2.ptr);\n\treturn 0;\n}\n\nvoid cgit_diff_tree(const struct object_id *old_oid,\n\t\t const struct object_id *new_oid,\n\t\t filepair_fn fn, const char *prefix, int ignorews)\n{\n\tstruct diff_options opt;\n\tstruct pathspec_item item;\n\n\tmemset(\u0026item, 0, sizeof(item));\n\tdiff_setup(\u0026opt);\n\topt.output_format \u003d DIFF_FORMAT_CALLBACK;\n\topt.detect_rename \u003d 1;\n\topt.rename_limit \u003d ctx.cfg.renamelimit;\n\topt.flags.recursive \u003d 1;\n\tif (ignorews)\n\t\tDIFF_XDL_SET(\u0026opt, IGNORE_WHITESPACE);\n\topt.format_callback \u003d cgit_diff_tree_cb;\n\topt.format_callback_data \u003d fn;\n\tif (prefix) {\n\t\titem.match \u003d xstrdup(prefix);\n\t\titem.len \u003d strlen(prefix);\n\t\topt.pathspec.nr \u003d 1;\n\t\topt.pathspec.items \u003d \u0026item;\n\t}\n\tdiff_setup_done(\u0026opt);\n\n\tif (old_oid \u0026\u0026 !is_null_oid(old_oid))\n\t\tdiff_tree_oid(old_oid, new_oid, \u0022\u0022, \u0026opt);\n\telse\n\t\tdiff_root_tree_oid(new_oid, \u0022\u0022, \u0026opt);\n\tdiffcore_std(\u0026opt);\n\tdiff_flush(\u0026opt);\n\n\tfree(item.match);\n}\n\nvoid cgit_diff_commit(struct commit *commit, filepair_fn fn, const char *prefix)\n{\n\tconst struct object_id *old_oid \u003d NULL;\n\n\tif (commit-\u003eparents)\n\t\told_oid \u003d \u0026commit-\u003eparents-\u003eitem-\u003eobject.oid;\n\tcgit_diff_tree(old_oid, \u0026commit-\u003eobject.oid, fn, prefix,\n\t\t ctx.qry.ignorews);\n}\n\nint cgit_parse_snapshots_mask(const char *str)\n{\n\tstruct string_list tokens \u003d STRING_LIST_INIT_DUP;\n\tstruct string_list_item *item;\n\tconst struct cgit_snapshot_format *f;\n\tint rv \u003d 0;\n\n\t/* favor legacy setting */\n\tif (atoi(str))\n\t\treturn 1;\n\n\tif (strcmp(str, \u0022all\u0022) \u003d\u003d 0)\n\t\treturn INT_MAX;\n\n\tstring_list_split(\u0026tokens, str, ' ', -1);\n\tstring_list_remove_empty_items(\u0026tokens, 0);\n\n\tfor_each_string_list_item(item, \u0026tokens) {\n\t\tfor (f \u003d cgit_snapshot_formats; f-\u003esuffix; f++) {\n\t\t\tif (!strcmp(item-\u003estring, f-\u003esuffix) ||\n\t\t\t !strcmp(item-\u003estring, f-\u003esuffix + 1)) {\n\t\t\t\trv |\u003d cgit_snapshot_format_bit(f);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tstring_list_clear(\u0026tokens, 0);\n\treturn rv;\n}\n\ntypedef struct {\n\tchar * name;\n\tchar * value;\n} cgit_env_var;\n\nvoid cgit_prepare_repo_env(struct cgit_repo * repo)\n{\n\tcgit_env_var env_vars[] \u003d {\n\t\t{ .name \u003d \u0022CGIT_REPO_URL\u0022, .value \u003d repo-\u003eurl },\n\t\t{ .name \u003d \u0022CGIT_REPO_NAME\u0022, .value \u003d repo-\u003ename },\n\t\t{ .name \u003d \u0022CGIT_REPO_PATH\u0022, .value \u003d repo-\u003epath },\n\t\t{ .name \u003d \u0022CGIT_REPO_OWNER\u0022, .value \u003d repo-\u003eowner },\n\t\t{ .name \u003d \u0022CGIT_REPO_DEFBRANCH\u0022, .value \u003d repo-\u003edefbranch },\n\t\t{ .name \u003d \u0022CGIT_REPO_SECTION\u0022, .value \u003d repo-\u003esection },\n\t\t{ .name \u003d \u0022CGIT_REPO_CLONE_URL\u0022, .value \u003d repo-\u003eclone_url }\n\t};\n\tint env_var_count \u003d ARRAY_SIZE(env_vars);\n\tcgit_env_var *p, *q;\n\tstatic char *warn \u003d \u0022cgit warning: failed to set env: %s\u003d%s\u005cn\u0022;\n\n\tp \u003d env_vars;\n\tq \u003d p + env_var_count;\n\tfor (; p \u003c q; p++)\n\t\tif (p-\u003evalue \u0026\u0026 setenv(p-\u003ename, p-\u003evalue, 1))\n\t\t\tfprintf(stderr, warn, p-\u003ename, p-\u003evalue);\n}\n\n/* Read the content of the specified file into a newly allocated buffer,\n * zeroterminate the buffer and return 0 on success, errno otherwise.\n */\nint readfile(const char *path, char **buf, size_t *size)\n{\n\tint fd, e;\n\tstruct stat st;\n\n\tfd \u003d open(path, O_RDONLY);\n\tif (fd \u003d\u003d -1)\n\t\treturn errno;\n\tif (fstat(fd, \u0026st)) {\n\t\te \u003d errno;\n\t\tclose(fd);\n\t\treturn e;\n\t}\n\tif (!S_ISREG(st.st_mode)) {\n\t\tclose(fd);\n\t\treturn EISDIR;\n\t}\n\t*buf \u003d xmalloc(st.st_size + 1);\n\t*size \u003d read_in_full(fd, *buf, st.st_size);\n\te \u003d errno;\n\t(*buf)[*size] \u003d '\u005c0';\n\tclose(fd);\n\treturn (*size \u003d\u003d st.st_size ? 0 : e);\n}\n\nstatic int is_token_char(char c)\n{\n\treturn isalnum(c) || c \u003d\u003d '_';\n}\n\n/* Replace name with getenv(name), return pointer to zero-terminating char\n */\nstatic char *expand_macro(char *name, int maxlength)\n{\n\tchar *value;\n\tint len;\n\n\tlen \u003d 0;\n\tvalue \u003d getenv(name);\n\tif (value) {\n\t\tlen \u003d strlen(value);\n\t\tif (len \u003e maxlength)\n\t\t\tlen \u003d maxlength;\n\t\tmemcpy(name, value, len);\n\t}\n\treturn name + len;\n}\n\n#define EXPBUFSIZE (1024 * 8)\n\n/* Replace all tokens prefixed by '$' in the specified text with the\n * value of the named environment variable.\n * NB: the return value is a static buffer, i.e. it must be strdup'd\n * by the caller.\n */\nchar *expand_macros(const char *txt)\n{\n\tstatic char result[EXPBUFSIZE];\n\tchar *p, *start;\n\tint len;\n\n\tp \u003d result;\n\tstart \u003d NULL;\n\twhile (p \u003c result + EXPBUFSIZE - 1 \u0026\u0026 txt \u0026\u0026 *txt) {\n\t\t*p \u003d *txt;\n\t\tif (start) {\n\t\t\tif (!is_token_char(*txt)) {\n\t\t\t\tif (p - start \u003e 0) {\n\t\t\t\t\t*p \u003d '\u005c0';\n\t\t\t\t\tlen \u003d result + EXPBUFSIZE - start - 1;\n\t\t\t\t\tp \u003d expand_macro(start, len) - 1;\n\t\t\t\t}\n\t\t\t\tstart \u003d NULL;\n\t\t\t\ttxt--;\n\t\t\t}\n\t\t\tp++;\n\t\t\ttxt++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (*txt \u003d\u003d '$') {\n\t\t\tstart \u003d p;\n\t\t\ttxt++;\n\t\t\tcontinue;\n\t\t}\n\t\tp++;\n\t\ttxt++;\n\t}\n\t*p \u003d '\u005c0';\n\tif (start \u0026\u0026 p - start \u003e 0) {\n\t\tlen \u003d result + EXPBUFSIZE - start - 1;\n\t\tp \u003d expand_macro(start, len);\n\t\t*p \u003d '\u005c0';\n\t}\n\treturn result;\n}\n\nchar *get_mimetype_for_filename(const char *filename)\n{\n\tchar *ext, *mimetype, *token, line[1024], *saveptr;\n\tFILE *file;\n\tstruct string_list_item *mime;\n\n\tif (!filename)\n\t\treturn NULL;\n\n\text \u003d strrchr(filename, '.');\n\tif (!ext)\n\t\treturn NULL;\n\t++ext;\n\tif (!ext[0])\n\t\treturn NULL;\n\tmime \u003d string_list_lookup(\u0026ctx.cfg.mimetypes, ext);\n\tif (mime)\n\t\treturn xstrdup(mime-\u003eutil);\n\n\tif (!ctx.cfg.mimetype_file)\n\t\treturn NULL;\n\tfile \u003d fopen(ctx.cfg.mimetype_file, \u0022r\u0022);\n\tif (!file)\n\t\treturn NULL;\n\twhile (fgets(line, sizeof(line), file)) {\n\t\tif (!line[0] || line[0] \u003d\u003d '#')\n\t\t\tcontinue;\n\t\tmimetype \u003d strtok_r(line, \u0022 \u005ct\u005cr\u005cn\u0022, \u0026saveptr);\n\t\twhile ((token \u003d strtok_r(NULL, \u0022 \u005ct\u005cr\u005cn\u0022, \u0026saveptr))) {\n\t\t\tif (!strcasecmp(ext, token)) {\n\t\t\t\tfclose(file);\n\t\t\t\treturn xstrdup(mimetype);\n\t\t\t}\n\t\t}\n\t}\n\tfclose(file);\n\treturn NULL;\n}\n","s":{"c":1714045483,"u": 8161}} ],"g": 11459,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 1, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}