Merge branch 'jk/write-in-full-fix'

Many codepaths did not diagnose write failures correctly when disks
go full, due to their misuse of write_in_full() helper function,
which have been corrected.

* jk/write-in-full-fix:
  read_pack_header: handle signed/unsigned comparison in read result
  config: flip return value of store_write_*()
  notes-merge: use ssize_t for write_in_full() return value
  pkt-line: check write_in_full() errors against "< 0"
  convert less-trivial versions of "write_in_full() != len"
  avoid "write_in_full(fd, buf, len) != len" pattern
  get-tar-commit-id: check write_in_full() return against 0
  config: avoid "write_in_full(fd, buf, len) < len" pattern
This commit is contained in:
Junio C Hamano 2017-09-25 15:24:06 +09:00
Родитель 94982b6999 f48ecd38cb
Коммит c50424a6f0
22 изменённых файлов: 65 добавлений и 67 удалений

Просмотреть файл

@ -33,8 +33,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
if (!skip_prefix(content, "52 comment=", &comment))
return 1;
n = write_in_full(1, comment, 41);
if (n < 41)
if (write_in_full(1, comment, 41) < 0)
die_errno("git get-tar-commit-id: write error");
return 0;

Просмотреть файл

@ -743,7 +743,7 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed,
size_t n;
if (feed(feed_state, &buf, &n))
break;
if (write_in_full(proc.in, buf, n) != n)
if (write_in_full(proc.in, buf, n) < 0)
break;
}
close(proc.in);

Просмотреть файл

@ -18,7 +18,7 @@ static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
{
int i;
for (i = 0; i < nbuf; i++)
if (write_in_full(1, ptr[i].ptr, ptr[i].size) != ptr[i].size)
if (write_in_full(1, ptr[i].ptr, ptr[i].size) < 0)
return -1;
return 0;
}

Просмотреть файл

@ -15,7 +15,7 @@ static char *create_temp_file(struct object_id *oid)
xsnprintf(path, sizeof(path), ".merge_file_XXXXXX");
fd = xmkstemp(path);
if (write_in_full(fd, buf, size) != size)
if (write_in_full(fd, buf, size) < 0)
die_errno("unable to write temp-file");
close(fd);
return path;

Просмотреть файл

@ -2292,10 +2292,11 @@ static int write_error(const char *filename)
return 4;
}
static int store_write_section(int fd, const char *key)
static ssize_t write_section(int fd, const char *key)
{
const char *dot;
int i, success;
int i;
ssize_t ret;
struct strbuf sb = STRBUF_INIT;
dot = memchr(key, '.', store.baselen);
@ -2311,15 +2312,16 @@ static int store_write_section(int fd, const char *key)
strbuf_addf(&sb, "[%.*s]\n", store.baselen, key);
}
success = write_in_full(fd, sb.buf, sb.len) == sb.len;
ret = write_in_full(fd, sb.buf, sb.len);
strbuf_release(&sb);
return success;
return ret;
}
static int store_write_pair(int fd, const char *key, const char *value)
static ssize_t write_pair(int fd, const char *key, const char *value)
{
int i, success;
int i;
ssize_t ret;
int length = strlen(key + store.baselen + 1);
const char *quote = "";
struct strbuf sb = STRBUF_INIT;
@ -2359,10 +2361,10 @@ static int store_write_pair(int fd, const char *key, const char *value)
}
strbuf_addf(&sb, "%s\n", quote);
success = write_in_full(fd, sb.buf, sb.len) == sb.len;
ret = write_in_full(fd, sb.buf, sb.len);
strbuf_release(&sb);
return success;
return ret;
}
static ssize_t find_beginning_of_line(const char *contents, size_t size,
@ -2491,8 +2493,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
}
store.key = (char *)key;
if (!store_write_section(fd, key) ||
!store_write_pair(fd, key, value))
if (write_section(fd, key) < 0 ||
write_pair(fd, key, value) < 0)
goto write_err_out;
} else {
struct stat st;
@ -2602,11 +2604,10 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
/* write the first part of the config */
if (copy_end > copy_begin) {
if (write_in_full(fd, contents + copy_begin,
copy_end - copy_begin) <
copy_end - copy_begin)
copy_end - copy_begin) < 0)
goto write_err_out;
if (new_line &&
write_str_in_full(fd, "\n") != 1)
write_str_in_full(fd, "\n") < 0)
goto write_err_out;
}
copy_begin = store.offset[i];
@ -2615,18 +2616,17 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
/* write the pair (value == NULL means unset) */
if (value != NULL) {
if (store.state == START) {
if (!store_write_section(fd, key))
if (write_section(fd, key) < 0)
goto write_err_out;
}
if (!store_write_pair(fd, key, value))
if (write_pair(fd, key, value) < 0)
goto write_err_out;
}
/* write the rest of the config */
if (copy_begin < contents_sz)
if (write_in_full(fd, contents + copy_begin,
contents_sz - copy_begin) <
contents_sz - copy_begin)
contents_sz - copy_begin) < 0)
goto write_err_out;
munmap(contents, contents_sz);
@ -2803,7 +2803,7 @@ int git_config_rename_section_in_file(const char *config_filename,
continue;
}
store.baselen = strlen(new_name);
if (!store_write_section(out_fd, new_name)) {
if (write_section(out_fd, new_name) < 0) {
ret = write_error(get_lock_file_path(lock));
goto out;
}
@ -2829,7 +2829,7 @@ int git_config_rename_section_in_file(const char *config_filename,
if (remove)
continue;
length = strlen(output);
if (write_in_full(out_fd, output, length) != length) {
if (write_in_full(out_fd, output, length) < 0) {
ret = write_error(get_lock_file_path(lock));
goto out;
}

2
diff.c
Просмотреть файл

@ -3738,7 +3738,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
blob = buf.buf;
size = buf.len;
}
if (write_in_full(temp->tempfile->fd, blob, size) != size ||
if (write_in_full(temp->tempfile->fd, blob, size) < 0 ||
close_tempfile_gently(temp->tempfile))
die_errno("unable to write temp-file");
temp->name = get_tempfile_path(temp->tempfile);

Просмотреть файл

@ -257,7 +257,8 @@ static int write_entry(struct cache_entry *ce,
char *new;
struct strbuf buf = STRBUF_INIT;
unsigned long size;
size_t wrote, newsize = 0;
ssize_t wrote;
size_t newsize = 0;
struct stat st;
const struct submodule *sub;
@ -332,7 +333,7 @@ static int write_entry(struct cache_entry *ce,
fstat_done = fstat_output(fd, state, &st);
close(fd);
free(new);
if (wrote != size)
if (wrote < 0)
return error("unable to write file %s", path);
break;
case S_IFGITLINK:

Просмотреть файл

@ -2952,7 +2952,7 @@ static void parse_reset_branch(const char *arg)
static void cat_blob_write(const char *buf, unsigned long size)
{
if (write_in_full(cat_blob_fd, buf, size) != size)
if (write_in_full(cat_blob_fd, buf, size) < 0)
die_errno("Write to frontend failed");
}

Просмотреть файл

@ -358,7 +358,7 @@ static void inflate_request(const char *prog_name, int out, int buffer_input)
die("zlib error inflating request, result %d", ret);
n = stream.total_out - cnt;
if (write_in_full(out, out_buf, n) != n)
if (write_in_full(out, out_buf, n) < 0)
die("%s aborted reading request", prog_name);
cnt += n;
@ -379,7 +379,7 @@ static void copy_request(const char *prog_name, int out)
ssize_t n = read_request(0, &buf);
if (n < 0)
die_errno("error reading request body");
if (write_in_full(out, buf, n) != n)
if (write_in_full(out, buf, n) < 0)
die("%s aborted reading request", prog_name);
close(out);
free(buf);

Просмотреть файл

@ -154,7 +154,7 @@ static void create_temp(mmfile_t *src, char *path, size_t len)
xsnprintf(path, len, ".merge_file_XXXXXX");
fd = xmkstemp(path);
if (write_in_full(fd, src->ptr, src->size) != src->size)
if (write_in_full(fd, src->ptr, src->size) < 0)
die_errno("unable to write temp-file");
close(fd);
}

Просмотреть файл

@ -302,7 +302,7 @@ static void write_buf_to_worktree(const struct object_id *obj,
fd = xopen(path, O_WRONLY | O_EXCL | O_CREAT, 0666);
while (size > 0) {
long ret = write_in_full(fd, buf, size);
ssize_t ret = write_in_full(fd, buf, size);
if (ret < 0) {
/* Ignore epipe */
if (errno == EPIPE)

Просмотреть файл

@ -94,9 +94,9 @@ void packet_flush(int fd)
int packet_flush_gently(int fd)
{
packet_trace("0000", 4, 1);
if (write_in_full(fd, "0000", 4) == 4)
return 0;
return error("flush packet write failed");
if (write_in_full(fd, "0000", 4) < 0)
return error("flush packet write failed");
return 0;
}
void packet_buf_flush(struct strbuf *buf)
@ -137,19 +137,18 @@ static int packet_write_fmt_1(int fd, int gently,
const char *fmt, va_list args)
{
static struct strbuf buf = STRBUF_INIT;
ssize_t count;
strbuf_reset(&buf);
format_packet(&buf, fmt, args);
count = write_in_full(fd, buf.buf, buf.len);
if (count == buf.len)
return 0;
if (!gently) {
check_pipe(errno);
die_errno("packet write with format failed");
if (write_in_full(fd, buf.buf, buf.len) < 0) {
if (!gently) {
check_pipe(errno);
die_errno("packet write with format failed");
}
return error("packet write with format failed");
}
return error("packet write with format failed");
return 0;
}
void packet_write_fmt(int fd, const char *fmt, ...)
@ -184,9 +183,9 @@ static int packet_write_gently(const int fd_out, const char *buf, size_t size)
packet_size = size + 4;
set_packet_header(packet_write_buffer, packet_size);
memcpy(packet_write_buffer + 4, buf, size);
if (write_in_full(fd_out, packet_write_buffer, packet_size) == packet_size)
return 0;
return error("packet write failed");
if (write_in_full(fd_out, packet_write_buffer, packet_size) < 0)
return error("packet write failed");
return 0;
}
void packet_buf_write(struct strbuf *buf, const char *fmt, ...)

Просмотреть файл

@ -1922,7 +1922,7 @@ static int ce_write_flush(git_SHA_CTX *context, int fd)
unsigned int buffered = write_buffer_len;
if (buffered) {
git_SHA1_Update(context, write_buffer, buffered);
if (write_in_full(fd, write_buffer, buffered) != buffered)
if (write_in_full(fd, write_buffer, buffered) < 0)
return -1;
write_buffer_len = 0;
}
@ -1971,7 +1971,7 @@ static int ce_flush(git_SHA_CTX *context, int fd, unsigned char *sha1)
/* Flush first if not enough space for SHA1 signature */
if (left + 20 > WRITE_BUFFER_SIZE) {
if (write_in_full(fd, write_buffer, left) != left)
if (write_in_full(fd, write_buffer, left) < 0)
return -1;
left = 0;
}
@ -1980,7 +1980,7 @@ static int ce_flush(git_SHA_CTX *context, int fd, unsigned char *sha1)
git_SHA1_Final(write_buffer + left, context);
hashcpy(sha1, write_buffer + left);
left += 20;
return (write_in_full(fd, write_buffer, left) != left) ? -1 : 0;
return (write_in_full(fd, write_buffer, left) < 0) ? -1 : 0;
}
static void ce_smudge_racily_clean_entry(struct cache_entry *ce)

2
refs.c
Просмотреть файл

@ -609,7 +609,7 @@ static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
}
}
if (write_in_full(fd, buf.buf, buf.len) != buf.len) {
if (write_in_full(fd, buf.buf, buf.len) < 0) {
strbuf_addf(err, "could not write to '%s'", filename);
rollback_lock_file(&lock);
goto done;

Просмотреть файл

@ -1549,7 +1549,7 @@ static int log_ref_write_fd(int fd, const struct object_id *old_oid,
written = len <= maxlen ? write_in_full(fd, logrec, len) : -1;
free(logrec);
if (written != len)
if (written < 0)
return -1;
return 0;
@ -1628,8 +1628,8 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
return -1;
}
fd = get_lock_file_fd(&lock->lk);
if (write_in_full(fd, oid_to_hex(oid), GIT_SHA1_HEXSZ) != GIT_SHA1_HEXSZ ||
write_in_full(fd, &term, 1) != 1 ||
if (write_in_full(fd, oid_to_hex(oid), GIT_SHA1_HEXSZ) < 0 ||
write_in_full(fd, &term, 1) < 0 ||
close_ref_gently(lock) < 0) {
strbuf_addf(err,
"couldn't write '%s'", get_lock_file_path(&lock->lk));
@ -3006,8 +3006,8 @@ static int files_reflog_expire(struct ref_store *ref_store,
rollback_lock_file(&reflog_lock);
} else if (update &&
(write_in_full(get_lock_file_fd(&lock->lk),
oid_to_hex(&cb.last_kept_oid), GIT_SHA1_HEXSZ) != GIT_SHA1_HEXSZ ||
write_str_in_full(get_lock_file_fd(&lock->lk), "\n") != 1 ||
oid_to_hex(&cb.last_kept_oid), GIT_SHA1_HEXSZ) < 0 ||
write_str_in_full(get_lock_file_fd(&lock->lk), "\n") < 1 ||
close_ref_gently(lock) < 0)) {
status |= error("couldn't write %s",
get_lock_file_path(&lock->lk));

Просмотреть файл

@ -258,7 +258,7 @@ static int write_rr(struct string_list *rr, int out_fd)
rerere_id_hex(id),
rr->items[i].string, 0);
if (write_in_full(out_fd, buf.buf, buf.len) != buf.len)
if (write_in_full(out_fd, buf.buf, buf.len) < 0)
die("unable to write rerere record");
strbuf_release(&buf);

Просмотреть файл

@ -1850,7 +1850,7 @@ int index_path(struct object_id *oid, const char *path, struct stat *st, unsigne
int read_pack_header(int fd, struct pack_header *header)
{
if (read_in_full(fd, header, sizeof(*header)) < sizeof(*header))
if (read_in_full(fd, header, sizeof(*header)) != sizeof(*header))
/* "eof before pack header was fully read" */
return PH_ERROR_EOF;

Просмотреть файл

@ -294,7 +294,7 @@ const char *setup_temporary_shallow(const struct oid_array *extra)
if (write_shallow_commits(&sb, 0, extra)) {
temp = xmks_tempfile(git_path("shallow_XXXXXX"));
if (write_in_full(temp->fd, sb.buf, sb.len) != sb.len ||
if (write_in_full(temp->fd, sb.buf, sb.len) < 0 ||
close_tempfile_gently(temp) < 0)
die_errno("failed to write to %s",
get_tempfile_path(temp));
@ -319,7 +319,7 @@ void setup_alternate_shallow(struct lock_file *shallow_lock,
LOCK_DIE_ON_ERROR);
check_shallow_file_for_update();
if (write_shallow_commits(&sb, 0, extra)) {
if (write_in_full(fd, sb.buf, sb.len) != sb.len)
if (write_in_full(fd, sb.buf, sb.len) < 0)
die_errno("failed to write to %s",
get_lock_file_path(shallow_lock));
*alternate_shallow_file = get_lock_file_path(shallow_lock);
@ -366,7 +366,7 @@ void prune_shallow(int show_only)
LOCK_DIE_ON_ERROR);
check_shallow_file_for_update();
if (write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY)) {
if (write_in_full(fd, sb.buf, sb.len) != sb.len)
if (write_in_full(fd, sb.buf, sb.len) < 0)
die_errno("failed to write to %s",
get_lock_file_path(&shallow_lock));
commit_lock_file(&shallow_lock);

Просмотреть файл

@ -540,7 +540,7 @@ int stream_blob_to_fd(int fd, const struct object_id *oid, struct stream_filter
kept = 0;
wrote = write_in_full(fd, buf, readlen);
if (wrote != readlen)
if (wrote < 0)
goto close_and_exit;
}
if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 ||

Просмотреть файл

@ -69,7 +69,7 @@ int cmd_main(int argc, const char **argv)
}
fd = open (argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (fd < 0 || write_in_full(fd, out_buf, out_size) != out_size) {
if (fd < 0 || write_in_full(fd, out_buf, out_size) < 0) {
perror(argv[4]);
return 1;
}

Просмотреть файл

@ -44,8 +44,7 @@ static void sendline(struct helper_data *helper, struct strbuf *buffer)
{
if (debug)
fprintf(stderr, "Debug: Remote helper: -> %s", buffer->buf);
if (write_in_full(helper->helper->in, buffer->buf, buffer->len)
!= buffer->len)
if (write_in_full(helper->helper->in, buffer->buf, buffer->len) < 0)
die_errno("Full write to remote helper failed");
}
@ -74,7 +73,7 @@ static void write_constant(int fd, const char *str)
{
if (debug)
fprintf(stderr, "Debug: Remote helper: -> %s", str);
if (write_in_full(fd, str, strlen(str)) != strlen(str))
if (write_in_full(fd, str, strlen(str)) < 0)
die_errno("Full write to remote helper failed");
}

Просмотреть файл

@ -652,7 +652,7 @@ int xsnprintf(char *dst, size_t max, const char *fmt, ...)
void write_file_buf(const char *path, const char *buf, size_t len)
{
int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (write_in_full(fd, buf, len) != len)
if (write_in_full(fd, buf, len) < 0)
die_errno(_("could not write to %s"), path);
if (close(fd))
die_errno(_("could not close %s"), path);