Merge branch 'jk/write-in-full-fix'
authorJunio C Hamano <gitster@pobox.com>
Mon, 25 Sep 2017 06:24:06 +0000 (15:24 +0900)
committerJunio C Hamano <gitster@pobox.com>
Mon, 25 Sep 2017 06:24:06 +0000 (15:24 +0900)
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

22 files changed:
builtin/get-tar-commit-id.c
builtin/receive-pack.c
builtin/rerere.c
builtin/unpack-file.c
config.c
diff.c
entry.c
fast-import.c
http-backend.c
ll-merge.c
notes-merge.c
pkt-line.c
read-cache.c
refs.c
refs/files-backend.c
rerere.c
sha1_file.c
shallow.c
streaming.c
t/helper/test-delta.c
transport-helper.c
wrapper.c
index e21c5416cd478eab3b0dddcba5ca9eeefad83d34..6d9a79f9b39834d953685b2641354915df3cfcbe 100644 (file)
@@ -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;
index 52c63ebfdc737688a7d99f6be34c43cf80b1d011..dd06b3fb4f9ee3e4da46d807b183541ec14c5481 100644 (file)
@@ -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);
index ffb66e29073c07c43197ae34f2c31d3b9b610903..0bc40298c2417a6d1f25aafb4b3577243e985c57 100644 (file)
@@ -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;
 }
index 281ca1db6ce13ddb4cc227ebb7ea454176e8e9e1..32e01555774c838e489fd33c675488e754c3e8e2 100644 (file)
@@ -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;
index cd5a69e6308c0cad6028deb04fb17e8d2dc4086c..a77cae56ed26212c6bfbbd831c85c8cf64deb8b9 100644 (file)
--- a/config.c
+++ b/config.c
@@ -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;
                }
diff --git a/diff.c b/diff.c
index ea7e5978bce1e91b603bb3beb61dfc391e2f80ef..3c6a3e0faa58f810ce2fe8b27f62581c175edf64 100644 (file)
--- a/diff.c
+++ b/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);
diff --git a/entry.c b/entry.c
index cb291aa88bf148608184edeff68943315b44e6ab..1c7e3c11d5075d4b39eeca76ab2272e781f773c8 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -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:
index 49516d60e69a26c41d9c47ecc0b60dbadabdad12..35bf671f12c41ce5a2a9f9224babee792bf71209 100644 (file)
@@ -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");
 }
 
index 8076b1d5e5ae01341fa739f55c6bcf6695e6507a..e51c7805c805ac6c1234665f5f90fcdd51d39231 100644 (file)
@@ -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);
index 9fb855a90030e07e28c1ae9d0994006da22cd4ed..a6ad2ec12dc9c1ece81f120196c81fd259e40eb6 100644 (file)
@@ -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);
 }
index b04d2f213116a6413d564107a6e12e3f7317accb..597d43f65c664c04dc3045c3d913146321f9e97b 100644 (file)
@@ -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)
index f364944b931a756b3b4819fb49ff5e9e01daf676..647bbd3bceda71f15fdf137a37f3fa53e6fa6d86 100644 (file)
@@ -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, ...)
index 7d00265c494244a060e0104e9854d02fe1c6b44a..cdcd11c71efd67130dd8159c9ac4da86e854222a 100644 (file)
@@ -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)
diff --git a/refs.c b/refs.c
index c30f4c36be57d9304464bf96e54e9b38742ffdaf..e8b67ddce80c83f8ec0dbfb3adc6d6c10b2f4b2d 100644 (file)
--- a/refs.c
+++ b/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;
index 32663a999ea030f76f400608ae1ed6dbaebbc20c..dac33628b37d4e19ea15e6706f1ab67c9b3a3e6c 100644 (file)
@@ -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));
index d77235645ea88ff9a51346436fcaac69dabfaaeb..1ce440f4bb84d001ff2b0ac1a67772f4bf5926c0 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -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);
index b4a67bb838d6e1a87093a90398cb254653269a86..dd7cbe52ef73754f30dfc61379549bc2fbd5e86c 100644 (file)
@@ -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;
 
index 1cc1c764151db233ba1cd43e06cbe87ba3f925ad..eabb65d3a7c286832f5a93bb732e8c9c94fa772e 100644 (file)
--- a/shallow.c
+++ b/shallow.c
@@ -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);
index 6f1c60f12bc5eea13c4b27cf6c80d690ffe49ab8..5892b50bd89c3c66bdb541ca0100f0671834a542 100644 (file)
@@ -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 ||
index 59937dc1be1c4f0b3d80e3ef3a86e09bff3703b6..591730adc4f3940940fdb4691da0afb81648e353 100644 (file)
@@ -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;
        }
index 42b960ff86d24c9e2659f01a63a8f7a5efbc853c..c948d5215c22fbbb3e174e219017935741e9b2d5 100644 (file)
@@ -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");
 }
 
index 36630e5d1855a41407e217e610aa1f293288abe1..61aba0b5c1bece4aad04bee649accae990a8ce18 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -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);