From e9b9368168399bf165a0172bb00a67216479c82b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 9 Jun 2006 15:26:08 -0700 Subject: [PATCH 1/5] builtin-init-db: spell the in-program configuration variable in lowercase. Just for consistency -- setup.c spells it in lowercase. Signed-off-by: Junio C Hamano --- builtin-init-db.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-init-db.c b/builtin-init-db.c index 2a1384ccb0..88b39a47eb 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -287,7 +287,7 @@ int cmd_init_db(int argc, const char **argv, char **envp) safe_create_dir(path, 1); if (shared_repository) - git_config_set("core.sharedRepository", "true"); + git_config_set("core.sharedrepository", "true"); return 0; } From f6407823d1467a6b6d2002878a64dec42df0a361 Mon Sep 17 00:00:00 2001 From: "Horst H. von Brand" Date: Fri, 9 Jun 2006 22:15:09 -0400 Subject: [PATCH 2/5] Fix formatting of Documentation/git-clone.txt Signed-off-by: Horst H. von Brand Signed-off-by: Junio C Hamano --- Documentation/git-clone.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 7572e4b80d..a90521e513 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -95,8 +95,8 @@ OPTIONS defined default, typically `/usr/share/git-core/templates`. --use-separate-remote:: - Save remotes heads under `$GIT_DIR/remotes/origin/' instead - of `$GIT_DIR/refs/heads/'. Only the master branch is saved + Save remotes heads under `$GIT_DIR/remotes/origin/` instead + of `$GIT_DIR/refs/heads/`. Only the master branch is saved in the latter. :: From 138086a72582620e0b3ec0aa60a78da208e89a2a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 9 Jun 2006 22:07:23 -0700 Subject: [PATCH 3/5] shared repository - add a few missing calls to adjust_shared_perm(). There were a few calls to adjust_shared_perm() that were missing: - init-db creates refs, refs/heads, and refs/tags before reading from templates that could specify sharedrepository in the config file; - updating config file created it under user's umask without adjusting; - updating refs created it under user's umask without adjusting; - switching branches created .git/HEAD under user's umask without adjusting. This moves adjust_shared_perm() from sha1_file.c to path.c, since a few SIMPLE_PROGRAM need to call repository configuration functions which in turn need to call adjust_shared_perm(). sha1_file.c needs to link with SHA1 computation library which is usually not linked to SIMPLE_PROGRAM. Signed-off-by: Junio C Hamano --- builtin-init-db.c | 15 +++++++++++++++ config.c | 2 +- lockfile.c | 15 ++++++++++----- path.c | 23 +++++++++++++++++++++++ refs.c | 5 +++++ sha1_file.c | 23 ----------------------- 6 files changed, 54 insertions(+), 29 deletions(-) diff --git a/builtin-init-db.c b/builtin-init-db.c index 88b39a47eb..6a24e9bcab 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -198,6 +198,21 @@ static void create_default_files(const char *git_dir, const char *template_path) git_config(git_default_config); + /* + * We would have created the above under user's umask -- under + * shared-repository settings, we would need to fix them up. + */ + if (shared_repository) { + path[len] = 0; + adjust_shared_perm(path); + strcpy(path + len, "refs"); + adjust_shared_perm(path); + strcpy(path + len, "refs/heads"); + adjust_shared_perm(path); + strcpy(path + len, "refs/tags"); + adjust_shared_perm(path); + } + /* * Create the default symlink from ".git/HEAD" to the "master" * branch, if it does not exist yet. diff --git a/config.c b/config.c index 2ae6153e5e..c47497001e 100644 --- a/config.c +++ b/config.c @@ -536,7 +536,7 @@ int git_config_set_multivar(const char* key, const char* value, * contents of .git/config will be written into it. */ fd = open(lock_file, O_WRONLY | O_CREAT | O_EXCL, 0666); - if (fd < 0) { + if (fd < 0 || adjust_shared_perm(lock_file)) { fprintf(stderr, "could not lock config file\n"); free(store.key); ret = -1; diff --git a/lockfile.c b/lockfile.c index 9bc60837aa..2346e0e9ef 100644 --- a/lockfile.c +++ b/lockfile.c @@ -27,11 +27,16 @@ int hold_lock_file_for_update(struct lock_file *lk, const char *path) int fd; sprintf(lk->filename, "%s.lock", path); fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666); - if (fd >=0 && !lk->next) { - lk->next = lock_file_list; - lock_file_list = lk; - signal(SIGINT, remove_lock_file_on_signal); - atexit(remove_lock_file); + if (0 <= fd) { + if (!lk->next) { + lk->next = lock_file_list; + lock_file_list = lk; + signal(SIGINT, remove_lock_file_on_signal); + atexit(remove_lock_file); + } + if (adjust_shared_perm(lk->filename)) + return error("cannot fix permission bits on %s", + lk->filename); } return fd; } diff --git a/path.c b/path.c index 334b2bd195..5168b5f17d 100644 --- a/path.c +++ b/path.c @@ -250,3 +250,26 @@ char *enter_repo(char *path, int strict) return NULL; } + +int adjust_shared_perm(const char *path) +{ + struct stat st; + int mode; + + if (!shared_repository) + return 0; + if (lstat(path, &st) < 0) + return -1; + mode = st.st_mode; + if (mode & S_IRUSR) + mode |= S_IRGRP; + if (mode & S_IWUSR) + mode |= S_IWGRP; + if (mode & S_IXUSR) + mode |= S_IXGRP; + if (S_ISDIR(mode)) + mode |= S_ISGID; + if (chmod(path, mode) < 0) + return -2; + return 0; +} diff --git a/refs.c b/refs.c index f91b7716dc..713ca46736 100644 --- a/refs.c +++ b/refs.c @@ -104,6 +104,11 @@ int create_symref(const char *git_HEAD, const char *refs_heads_master) error("Unable to create %s", git_HEAD); return -3; } + if (adjust_shared_perm(git_HEAD)) { + unlink(lockpath); + error("Unable to fix permissions on %s", lockpath); + return -4; + } return 0; } diff --git a/sha1_file.c b/sha1_file.c index aea0f40d57..b4ff233bad 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -50,29 +50,6 @@ int get_sha1_hex(const char *hex, unsigned char *sha1) return 0; } -int adjust_shared_perm(const char *path) -{ - struct stat st; - int mode; - - if (!shared_repository) - return 0; - if (lstat(path, &st) < 0) - return -1; - mode = st.st_mode; - if (mode & S_IRUSR) - mode |= S_IRGRP; - if (mode & S_IWUSR) - mode |= S_IWGRP; - if (mode & S_IXUSR) - mode |= S_IXGRP; - if (S_ISDIR(mode)) - mode |= S_ISGID; - if (chmod(path, mode) < 0) - return -2; - return 0; -} - int safe_create_leading_directories(char *path) { char *pos = path; From 5e3a620cd5f7baaf27198192a614271c6145ec3b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 10 Jun 2006 01:12:50 -0700 Subject: [PATCH 4/5] git-clone: fix --bare over dumb-http It left an extra .git/ directory under the target directory by mistake. Signed-off-by: Junio C Hamano --- git-clone.sh | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/git-clone.sh b/git-clone.sh index 64318b4dd3..6fa0daaacf 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -29,7 +29,7 @@ http_fetch () { clone_dumb_http () { # $1 - remote, $2 - local cd "$2" && - clone_tmp='.git/clone-tmp' && + clone_tmp="$GIT_DIR/clone-tmp" && mkdir -p "$clone_tmp" || exit 1 http_fetch "$1/info/refs" "$clone_tmp/refs" || { echo >&2 "Cannot get remote repository information. @@ -207,15 +207,11 @@ mkdir -p "$dir" && D=$(cd "$dir" && pwd) && trap 'err=$?; cd ..; rm -r "$D"; exit $err' 0 case "$bare" in -yes) GIT_DIR="$D" ;; -*) GIT_DIR="$D/.git" ;; -esac && export GIT_DIR && git-init-db ${template+"$template"} || usage -case "$bare" in yes) GIT_DIR="$D" ;; *) GIT_DIR="$D/.git" ;; -esac +esac && export GIT_DIR && git-init-db ${template+"$template"} || usage if test -n "$reference" then From 94df2506edd76a886a1044376f8c99349b2f226e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 9 Jun 2006 23:09:49 -0700 Subject: [PATCH 5/5] shared repository: optionally allow reading to "others". This enhances core.sharedrepository to have additionally specify that read and exec permissions to be given to others as well. It is useful when serving a repository via gitweb and git-daemon that runs as a user outside the project group. The configuration item can take the following values: [core] sharedrepository ; the same as "group" sharedrepository = true ; ditto sharedrepository = 1 ; ditto sharedrepository = group ; allow rwx to group sharedrepository = all ; allow rwx to group, allow rx to other sharedrepository = umask ; not shared - use umask It also extends "git init-db" to take "--shared=all" and friends from the command line. Signed-off-by: Junio C Hamano --- builtin-init-db.c | 15 ++++++++++++--- cache.h | 6 ++++++ environment.c | 2 +- path.c | 14 ++++++++++++-- setup.c | 17 ++++++++++++++++- 5 files changed, 47 insertions(+), 7 deletions(-) diff --git a/builtin-init-db.c b/builtin-init-db.c index 6a24e9bcab..7fdd2fa9f9 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -263,7 +263,9 @@ int cmd_init_db(int argc, const char **argv, char **envp) if (!strncmp(arg, "--template=", 11)) template_dir = arg+11; else if (!strcmp(arg, "--shared")) - shared_repository = 1; + shared_repository = PERM_GROUP; + else if (!strncmp(arg, "--shared=", 9)) + shared_repository = git_config_perm("arg", arg+9); else die(init_db_usage); } @@ -301,8 +303,15 @@ int cmd_init_db(int argc, const char **argv, char **envp) strcpy(path+len, "/info"); safe_create_dir(path, 1); - if (shared_repository) - git_config_set("core.sharedrepository", "true"); + if (shared_repository) { + char buf[10]; + /* We do not spell "group" and such, so that + * the configuration can be read by older version + * of git. + */ + sprintf(buf, "%d", shared_repository); + git_config_set("core.sharedrepository", buf); + } return 0; } diff --git a/cache.h b/cache.h index d5d7fe4f8c..1b8e053f28 100644 --- a/cache.h +++ b/cache.h @@ -208,6 +208,12 @@ extern const unsigned char null_sha1[20]; int git_mkstemp(char *path, size_t n, const char *template); +enum sharedrepo { + PERM_UMASK = 0, + PERM_GROUP, + PERM_EVERYBODY +}; +int git_config_perm(const char *var, const char *value); int adjust_shared_perm(const char *path); int safe_create_leading_directories(char *path); char *safe_strncpy(char *, const char *, size_t); diff --git a/environment.c b/environment.c index 2e79eab18d..3de8eb3b2a 100644 --- a/environment.c +++ b/environment.c @@ -18,7 +18,7 @@ int log_all_ref_updates = 0; int warn_ambiguous_refs = 1; int repository_format_version = 0; char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8"; -int shared_repository = 0; +int shared_repository = PERM_UMASK; const char *apply_default_whitespace = NULL; static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir, diff --git a/path.c b/path.c index 5168b5f17d..5d82503b6b 100644 --- a/path.c +++ b/path.c @@ -262,11 +262,21 @@ int adjust_shared_perm(const char *path) return -1; mode = st.st_mode; if (mode & S_IRUSR) - mode |= S_IRGRP; + mode |= (shared_repository == PERM_GROUP + ? S_IRGRP + : (shared_repository == PERM_EVERYBODY + ? (S_IRGRP|S_IROTH) + : 0)); + if (mode & S_IWUSR) mode |= S_IWGRP; + if (mode & S_IXUSR) - mode |= S_IXGRP; + mode |= (shared_repository == PERM_GROUP + ? S_IXGRP + : (shared_repository == PERM_EVERYBODY + ? (S_IXGRP|S_IXOTH) + : 0)); if (S_ISDIR(mode)) mode |= S_ISGID; if (chmod(path, mode) < 0) diff --git a/setup.c b/setup.c index fe7f884696..4612f110ee 100644 --- a/setup.c +++ b/setup.c @@ -219,12 +219,27 @@ const char *setup_git_directory_gently(int *nongit_ok) return cwd + offset; } +int git_config_perm(const char *var, const char *value) +{ + if (value) { + if (!strcmp(value, "umask")) + return PERM_UMASK; + if (!strcmp(value, "group")) + return PERM_GROUP; + if (!strcmp(value, "all") || + !strcmp(value, "world") || + !strcmp(value, "everybody")) + return PERM_EVERYBODY; + } + return git_config_bool(var, value); +} + int check_repository_format_version(const char *var, const char *value) { if (strcmp(var, "core.repositoryformatversion") == 0) repository_format_version = git_config_int(var, value); else if (strcmp(var, "core.sharedrepository") == 0) - shared_repository = git_config_bool(var, value); + shared_repository = git_config_perm(var, value); return 0; }