diff options
author | Junio C Hamano <junkio@cox.net> | 2005-09-25 16:28:51 -0700 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2005-09-25 19:25:09 -0700 |
commit | 152da3dfcf2c16d7c240a0dbdcb8a3ae1d332d81 (patch) | |
tree | e97976f88276b18652c763f224b8b810e3ce68d4 /update-ref.c | |
parent | 66bf85a462893f9df7e516a5f334dbba08122617 (diff) | |
download | git-152da3dfcf2c16d7c240a0dbdcb8a3ae1d332d81.tar.gz git-152da3dfcf2c16d7c240a0dbdcb8a3ae1d332d81.tar.xz |
Plug a small race in update-ref.c.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'update-ref.c')
-rw-r--r-- | update-ref.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/update-ref.c b/update-ref.c index 127ef99ee..01496f6a9 100644 --- a/update-ref.c +++ b/update-ref.c @@ -1,5 +1,6 @@ #include "cache.h" #include "refs.h" +#include <ctype.h> static const char git_update_ref_usage[] = "git-update-ref <refname> <value> [<oldval>]"; @@ -50,6 +51,19 @@ const char *resolve_ref(const char *path, unsigned char *sha1) return path; } +static int re_verify(const char *path, unsigned char *oldsha1, unsigned char *currsha1) +{ + char buf[40]; + int fd = open(path, O_RDONLY), nr; + if (fd < 0) + return -1; + nr = read(fd, buf, 40); + close(fd); + if (nr != 40 || get_sha1_hex(buf, currsha1) < 0) + return -1; + return memcmp(oldsha1, currsha1, 20) ? -1 : 0; +} + int main(int argc, char **argv) { char *hex; @@ -97,12 +111,16 @@ int main(int argc, char **argv) } /* - * FIXME! - * - * We should re-read the old ref here, and re-verify that it - * matches "oldsha1". Otherwise there's a small race. + * Re-read the ref after getting the lock to verify */ + if (oldval && re_verify(path, oldsha1, currsha1) < 0) { + unlink(lockpath); + die("Ref lock failed"); + } + /* + * Finally, replace the old ref with the new one + */ if (rename(lockpath, path) < 0) { unlink(lockpath); die("Unable to create %s", path); |