diff options
author | Ronnie Sahlberg <sahlberg@google.com> | 2014-06-20 07:42:55 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-07-14 11:54:42 -0700 |
commit | dc615de8610c807633c63313937056bf45df0b8f (patch) | |
tree | a11c6e51b933a942f4f01335ebd3513d85168eb1 | |
parent | 76d70dc0c63fe89958308f249136864aec5cdf03 (diff) | |
download | git-dc615de8610c807633c63313937056bf45df0b8f.tar.gz |
refs.c: log_ref_write should try to return meaningful errno
Making errno from write_ref_sha1() meaningful, which should fix
* a bug in "git checkout -b" where it prints strerror(errno)
despite errno possibly being zero or clobbered
* a bug in "git fetch"'s s_update_ref, which trusts the result of an
errno == ENOTDIR check to detect D/F conflicts
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Acked-by: Michael Haggerty <mhagger@alum.mit.edu>
-rw-r--r-- | refs.c | 28 |
1 files changed, 23 insertions, 5 deletions
@@ -2859,8 +2859,19 @@ static int log_ref_write(const char *refname, const unsigned char *old_sha1, len += copy_msg(logrec + len - 1, msg) - 1; written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1; free(logrec); - if (close(logfd) != 0 || written != len) - return error("Unable to append to %s", log_file); + if (written != len) { + int save_errno = errno; + close(logfd); + error("Unable to append to %s", log_file); + errno = save_errno; + return -1; + } + if (close(logfd)) { + int save_errno = errno; + error("Unable to append to %s", log_file); + errno = save_errno; + return -1; + } return 0; } @@ -2869,14 +2880,17 @@ static int is_branch(const char *refname) return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/"); } +/* This function must return a meaningful errno */ int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, const char *logmsg) { static char term = '\n'; struct object *o; - if (!lock) + if (!lock) { + errno = EINVAL; return -1; + } if (!lock->force_write && !hashcmp(lock->old_sha1, sha1)) { unlock_ref(lock); return 0; @@ -2886,19 +2900,23 @@ int write_ref_sha1(struct ref_lock *lock, error("Trying to write ref %s with nonexistent object %s", lock->ref_name, sha1_to_hex(sha1)); unlock_ref(lock); + errno = EINVAL; return -1; } if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) { error("Trying to write non-commit object %s to branch %s", sha1_to_hex(sha1), lock->ref_name); unlock_ref(lock); + errno = EINVAL; return -1; } if (write_in_full(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 || - write_in_full(lock->lock_fd, &term, 1) != 1 - || close_ref(lock) < 0) { + write_in_full(lock->lock_fd, &term, 1) != 1 || + close_ref(lock) < 0) { + int save_errno = errno; error("Couldn't write %s", lock->lk->filename); unlock_ref(lock); + errno = save_errno; return -1; } clear_loose_ref_cache(&ref_cache); |