Skip to content

Commit

Permalink
refs.c: log_ref_write should try to return meaningful errno
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ronnie Sahlberg authored and Junio C Hamano committed Jul 14, 2014
1 parent 76d70dc commit dc615de
Showing 1 changed file with 23 additions and 5 deletions.
28 changes: 23 additions & 5 deletions refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
Expand All @@ -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);
Expand Down

0 comments on commit dc615de

Please sign in to comment.