Merge branch 'jc/daemon' into next

* jc/daemon:
  multi-service daemon: documentation
  daemon: add upload-tar service.
  daemon: prepare for multiple services.
  Add git-zip-tree to .gitignore
  free(NULL) is perfectly valid.
  Use xcalloc instead of calloc
  Use fstat instead of fseek
  git-reset: remove unused variable
  git-cherry: remove unused variable
This commit is contained in:
Junio C Hamano
2006-08-27 23:38:27 -07:00
20 changed files with 182 additions and 89 deletions

1
.gitignore vendored
View File

@@ -125,6 +125,7 @@ git-verify-pack
git-verify-tag
git-whatchanged
git-write-tree
git-zip-tree
git-core-*/?*
gitweb/gitweb.cgi
test-date

View File

@@ -11,17 +11,16 @@ SYNOPSIS
'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
[--timeout=n] [--init-timeout=n] [--strict-paths]
[--base-path=path] [--user-path | --user-path=path]
[--reuseaddr] [--detach] [--pid-file=file]
[--user=user [--group=group]] [directory...]
[--enable=service] [--disable=service]
[--allow-override=service] [--forbid-override=service]
[--reuseaddr] [--detach] [--pid-file=file]
[--user=user [--group=group]] [directory...]
DESCRIPTION
-----------
A really simple TCP git daemon that normally listens on port "DEFAULT_GIT_PORT"
aka 9418. It waits for a connection, and will just execute "git-upload-pack"
when it gets one.
It's careful in that there's a magic request-line that gives the command and
what directory to upload, and it verifies that the directory is OK.
aka 9418. It waits for a connection asking for a service, and will serve
that service if it is enabled.
It verifies that the directory has the magic file "git-daemon-export-ok", and
it will refuse to export any git directory that hasn't explicitly been marked
@@ -29,7 +28,12 @@ for export this way (unless the '--export-all' parameter is specified). If you
pass some directory paths as 'git-daemon' arguments, you can further restrict
the offers to a whitelist comprising of those.
This is ideally suited for read-only updates, i.e., pulling from git repositories.
By default, only `upload-pack` service is enabled, which serves
`git-fetch-pack` and `git-peek-remote` clients that are invoked
from `git-fetch`, `git-ls-remote`, and `git-clone`.
This is ideally suited for read-only updates, i.e., pulling from
git repositories.
OPTIONS
-------
@@ -105,11 +109,38 @@ Giving these options is an error when used with `--inetd`; use
the facility of inet daemon to achieve the same before spawning
`git-daemon` if needed.
--enable-service, --disable-service::
Enable/disable the service site-wide per default. Note
that a service disabled site-wide can still be enabled
per repository if it is marked overridable and the
repository enables the service with an configuration
item.
--allow-override, --forbid-override::
Allow/forbid overriding the site-wide default with per
repository configuration. By default, all the services
are overridable.
<directory>::
A directory to add to the whitelist of allowed directories. Unless
--strict-paths is specified this will also include subdirectories
of each named directory.
SERVICES
--------
upload-pack::
This serves `git-fetch-pack` and `git-peek-remote`
clients. It is enabled by default, but a repository can
disable it by setting `daemon.uploadpack` configuration
item to `false`.
upload-tar::
This serves `git-tar-tree --remote=repository` client.
It is not enabled by default, but a repository can
enable it by setting `daemon.uploadtar` configuration
item to `true`.
Author
------
Written by Linus Torvalds <torvalds@osdl.org>, YOSHIFUJI Hideaki

View File

@@ -261,7 +261,7 @@ LIB_OBJS = \
tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \
write_or_die.o \
alloc.o merge-file.o path-list.o unpack-trees.o help.o $(DIFF_OBJS)
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS)
BUILTIN_OBJS = \
builtin-add.o \

14
TEST
View File

@@ -1,14 +0,0 @@
#!/bin/sh -x
cd t || exit
GIT_USE_RECUR_FOR_RECURSIVE=LetsTryIt
export GIT_USE_RECUR_FOR_RECURSIVE
./t3400-rebase.sh "$@" &&
./t6020-merge-df.sh "$@" &&
./t3401-rebase-partial.sh "$@" &&
./t6021-merge-criss-cross.sh "$@" &&
./t3402-rebase-merge.sh "$@" &&
./t6022-merge-rename.sh "$@" &&
./t6010-merge-base.sh "$@" &&
:

View File

@@ -1131,8 +1131,7 @@ static struct fragment *parse_binary_hunk(char **buf_p,
return frag;
corrupt:
if (data)
free(data);
free(data);
*status_p = -1;
error("corrupt binary patch at line %d: %.*s",
linenr-1, llen-1, buffer);
@@ -1329,8 +1328,7 @@ static void show_stats(struct patch *patch)
printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
len, name, patch->lines_added + patch->lines_deleted,
add, pluses, del, minuses);
if (qname)
free(qname);
free(qname);
}
static int read_old_data(struct stat *st, const char *path, void *buf, unsigned long size)

View File

@@ -55,8 +55,7 @@ static void free_list(struct list *list)
for (i = 0; i < list->nr; i++) {
free(list->list[i]);
if (list->payload[i])
free(list->payload[i]);
free(list->payload[i]);
}
free(list->list);
free(list->payload);

View File

@@ -122,10 +122,8 @@ static int get_value(const char* key_, const char* regex_)
ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1;
free_strings:
if (repo_config)
free(repo_config);
if (global)
free(global);
free(repo_config);
free(global);
return ret;
}

View File

@@ -93,10 +93,8 @@ static void show_commit(struct commit *commit)
free_commit_list(commit->parents);
commit->parents = NULL;
}
if (commit->buffer) {
free(commit->buffer);
commit->buffer = NULL;
}
free(commit->buffer);
commit->buffer = NULL;
}
static void process_blob(struct blob *blob,

View File

@@ -361,8 +361,7 @@ int git_config(config_fn_t fn)
}
ret += git_config_from_file(fn, filename);
if (repo_config)
free(repo_config);
free(repo_config);
return ret;
}
@@ -734,8 +733,7 @@ int git_config_set_multivar(const char* key, const char* value,
out_free:
if (0 <= fd)
close(fd);
if (config_filename)
free(config_filename);
free(config_filename);
if (lock_file) {
unlink(lock_file);
free(lock_file);

124
daemon.c
View File

@@ -232,13 +232,42 @@ static char *path_ok(char *dir)
return NULL; /* Fallthrough. Deny by default */
}
static int upload(char *dir)
{
/* Timeout as string */
char timeout_buf[64];
const char *path;
typedef int (*daemon_service_fn)(void);
struct daemon_service {
const char *name;
const char *config_name;
daemon_service_fn fn;
int enabled;
int overridable;
};
loginfo("Request for '%s'", dir);
static struct daemon_service *service_looking_at;
static int service_enabled;
static int git_daemon_config(const char *var, const char *value)
{
if (!strncmp(var, "daemon.", 7) &&
!strcmp(var + 7, service_looking_at->config_name)) {
service_enabled = git_config_bool(var, value);
return 0;
}
/* we are not interested in parsing any other configuration here */
return 0;
}
static int run_service(char *dir, struct daemon_service *service)
{
const char *path;
int enabled = service->enabled;
loginfo("Request %s for '%s'", service->name, dir);
if (!enabled && !service->overridable) {
logerror("'%s': service not enabled.", service->name);
errno = EACCES;
return -1;
}
if (!(path = path_ok(dir)))
return -1;
@@ -260,12 +289,34 @@ static int upload(char *dir)
return -1;
}
if (service->overridable) {
service_looking_at = service;
service_enabled = -1;
git_config(git_daemon_config);
if (0 <= service_enabled)
enabled = service_enabled;
}
if (!enabled) {
logerror("'%s': service not enabled for '%s'",
service->name, path);
errno = EACCES;
return -1;
}
/*
* We'll ignore SIGTERM from now on, we have a
* good client.
*/
signal(SIGTERM, SIG_IGN);
return service->fn();
}
static int upload_pack(void)
{
/* Timeout as string */
char timeout_buf[64];
snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
/* git-upload-pack only ever reads stuff, so this is safe */
@@ -273,10 +324,43 @@ static int upload(char *dir)
return -1;
}
static int upload_tar(void)
{
execl_git_cmd("upload-tar", ".", NULL);
return -1;
}
static struct daemon_service daemon_service[] = {
{ "upload-pack", "uploadpack", upload_pack, 1, 1 },
{ "upload-tar", "uploadtar", upload_tar, 0, 1 },
};
static void enable_service(const char *name, int ena) {
int i;
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
if (!strcmp(daemon_service[i].name, name)) {
daemon_service[i].enabled = ena;
return;
}
}
die("No such service %s", name);
}
static void make_service_overridable(const char *name, int ena) {
int i;
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
if (!strcmp(daemon_service[i].name, name)) {
daemon_service[i].overridable = ena;
return;
}
}
die("No such service %s", name);
}
static int execute(struct sockaddr *addr)
{
static char line[1000];
int pktlen, len;
int pktlen, len, i;
if (addr) {
char addrbuf[256] = "";
@@ -313,8 +397,14 @@ static int execute(struct sockaddr *addr)
if (len && line[len-1] == '\n')
line[--len] = 0;
if (!strncmp("git-upload-pack ", line, 16))
return upload(line+16);
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
struct daemon_service *s = &(daemon_service[i]);
int namelen = strlen(s->name);
if (!strncmp("git-", line, 4) &&
!strncmp(s->name, line + 4, namelen) &&
line[namelen + 4] == ' ')
return run_service(line + namelen + 5, s);
}
logerror("Protocol error: '%s'", line);
return -1;
@@ -805,6 +895,22 @@ int main(int argc, char **argv)
group_name = arg + 8;
continue;
}
if (!strncmp(arg, "--enable=", 9)) {
enable_service(arg + 9, 1);
continue;
}
if (!strncmp(arg, "--disable=", 10)) {
enable_service(arg + 10, 0);
continue;
}
if (!strncmp(arg, "--allow-override=", 17)) {
make_service_overridable(arg + 17, 1);
continue;
}
if (!strncmp(arg, "--forbid-override=", 18)) {
make_service_overridable(arg + 18, 0);
continue;
}
if (!strcmp(arg, "--")) {
ok_paths = &argv[i+1];
break;

8
dir.c
View File

@@ -112,17 +112,15 @@ static int add_excludes_from_file_1(const char *fname,
int baselen,
struct exclude_list *which)
{
struct stat st;
int fd, i;
long size;
char *buf, *entry;
fd = open(fname, O_RDONLY);
if (fd < 0)
if (fd < 0 || fstat(fd, &st) < 0)
goto err;
size = lseek(fd, 0, SEEK_END);
if (size < 0)
goto err;
lseek(fd, 0, SEEK_SET);
size = st.st_size;
if (size == 0) {
close(fd);
return 0;

View File

@@ -302,8 +302,7 @@ int pull(int targets, char **target, const char **write_ref,
if (ret)
goto unlock_and_fail;
}
if (msg)
free(msg);
free(msg);
return 0;

View File

@@ -51,9 +51,6 @@ patch=$tmp-patch
mkdir $patch
trap "rm -rf $tmp-*" 0 1 2 3 15
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
for c in $inup
do
git-diff-tree -p $c

View File

@@ -3,9 +3,6 @@
USAGE='[--mixed | --soft | --hard] [<commit-ish>]'
. git-sh-setup
tmp=${GIT_DIR}/reset.$$
trap 'rm -f $tmp-*' 0 1 2 3 15
update=
reset_type=--mixed
case "$1" in

View File

@@ -696,10 +696,8 @@ xml_start_tag(void *userData, const char *name, const char **atts)
strcat(ctx->name, ".");
strcat(ctx->name, c);
if (ctx->cdata) {
free(ctx->cdata);
ctx->cdata = NULL;
}
free(ctx->cdata);
ctx->cdata = NULL;
ctx->userFunc(ctx, 0);
}
@@ -726,8 +724,7 @@ static void
xml_cdata(void *userData, const XML_Char *s, int len)
{
struct xml_ctx *ctx = (struct xml_ctx *)userData;
if (ctx->cdata)
free(ctx->cdata);
free(ctx->cdata);
ctx->cdata = xmalloc(len + 1);
strlcpy(ctx->cdata, s, len + 1);
}
@@ -765,9 +762,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
ls->dentry_flags |= IS_DIR;
}
} else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
if (ls->dentry_name) {
free(ls->dentry_name);
}
free(ls->dentry_name);
ls->dentry_name = NULL;
ls->dentry_flags = 0;
}

View File

@@ -1238,10 +1238,8 @@ xml_start_tag(void *userData, const char *name, const char **atts)
strcat(ctx->name, ".");
strcat(ctx->name, c);
if (ctx->cdata) {
free(ctx->cdata);
ctx->cdata = NULL;
}
free(ctx->cdata);
ctx->cdata = NULL;
ctx->userFunc(ctx, 0);
}
@@ -1268,8 +1266,7 @@ static void
xml_cdata(void *userData, const XML_Char *s, int len)
{
struct xml_ctx *ctx = (struct xml_ctx *)userData;
if (ctx->cdata)
free(ctx->cdata);
free(ctx->cdata);
ctx->cdata = xmalloc(len + 1);
strlcpy(ctx->cdata, s, len + 1);
}
@@ -1518,9 +1515,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
ls->dentry_flags |= IS_DIR;
}
} else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
if (ls->dentry_name) {
free(ls->dentry_name);
}
free(ls->dentry_name);
ls->dentry_name = NULL;
ls->dentry_flags = 0;
}

View File

@@ -30,7 +30,7 @@ static void grow_refs_hash(void)
int new_hash_size = (refs_hash_size + 1000) * 3 / 2;
struct object_refs **new_hash;
new_hash = calloc(new_hash_size, sizeof(struct object_refs *));
new_hash = xcalloc(new_hash_size, sizeof(struct object_refs *));
for (i = 0; i < refs_hash_size; i++) {
struct object_refs *ref = refs_hash[i];
if (!ref)

View File

@@ -73,7 +73,7 @@ static void grow_object_hash(void)
int new_hash_size = obj_hash_size < 32 ? 32 : 2 * obj_hash_size;
struct object **new_hash;
new_hash = calloc(new_hash_size, sizeof(struct object *));
new_hash = xcalloc(new_hash_size, sizeof(struct object *));
for (i = 0; i < obj_hash_size; i++) {
struct object *obj = obj_hash[i];
if (!obj)

View File

@@ -85,8 +85,7 @@ void path_list_clear(struct path_list *list, int free_items)
for (i = 0; i < list->nr; i++) {
if (list->strdup_paths)
free(list->items[i].path);
if (list->items[i].util)
free(list->items[i].util);
free(list->items[i].util);
}
free(list->items);
}

6
refs.c
View File

@@ -348,10 +348,8 @@ void unlock_ref(struct ref_lock *lock)
if (lock->lk)
rollback_lock_file(lock->lk);
}
if (lock->ref_file)
free(lock->ref_file);
if (lock->log_file)
free(lock->log_file);
free(lock->ref_file);
free(lock->log_file);
free(lock);
}