Skip to content

Commit

Permalink
short i/o: fix calls to write to use xwrite or write_in_full
Browse files Browse the repository at this point in the history
We have a number of badly checked write() calls.  Often we are
expecting write() to write exactly the size we requested or fail,
this fails to handle interrupts or short writes.  Switch to using
the new write_in_full().  Otherwise we at a minimum need to check
for EINTR and EAGAIN, where this is appropriate use xwrite().

Note, the changes to config handling are much larger and handled
in the next patch in the sequence.

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
awhitcroft authored and Junio C Hamano committed Jan 8, 2007
1 parent 93d26e4 commit 93822c2
Show file tree
Hide file tree
Showing 20 changed files with 74 additions and 89 deletions.
11 changes: 7 additions & 4 deletions builtin-rerere.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ static int write_rr(struct path_list *rr, int out_fd)
int i;
for (i = 0; i < rr->nr; i++) {
const char *path = rr->items[i].path;
write(out_fd, rr->items[i].util, 40);
write(out_fd, "\t", 1);
write(out_fd, path, strlen(path) + 1);
int length = strlen(path) + 1;
if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
write_in_full(out_fd, "\t", 1) != 1 ||
write_in_full(out_fd, path, length) != length)
die("unable to write rerere record");
}
close(out_fd);
return commit_lock_file(&write_lock);
Expand Down Expand Up @@ -244,7 +246,8 @@ static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
{
int i;
for (i = 0; i < nbuf; i++)
write(1, ptr[i].ptr, ptr[i].size);
if (write_in_full(1, ptr[i].ptr, ptr[i].size) != ptr[i].size)
return -1;
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion builtin-tar-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
if (memcmp(content, "52 comment=", 11))
return 1;

n = xwrite(1, content + 11, 41);
n = write_in_full(1, content + 11, 41);
if (n < 41)
die("git-get-tar-commit-id: write error");

Expand Down
6 changes: 4 additions & 2 deletions commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,10 @@ int write_shallow_commits(int fd, int use_pack_protocol)
if (use_pack_protocol)
packet_write(fd, "shallow %s", hex);
else {
write(fd, hex, 40);
write(fd, "\n", 1);
if (write_in_full(fd, hex, 40) != 40)
break;
if (write_in_full(fd, "\n", 1) != 1)
break;
}
}
return count;
Expand Down
2 changes: 1 addition & 1 deletion daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ static void logreport(int priority, const char *err, va_list params)
buf[buflen++] = '\n';
buf[buflen] = '\0';

write(2, buf, buflen);
write_in_full(2, buf, buflen);
}

static void logerror(const char *err, ...)
Expand Down
2 changes: 1 addition & 1 deletion diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1389,7 +1389,7 @@ static void prep_temp_blob(struct diff_tempfile *temp,
fd = git_mkstemp(temp->tmp_path, TEMPFILE_PATH_LEN, ".diff_XXXXXX");
if (fd < 0)
die("unable to create temp-file");
if (write(fd, blob, size) != size)
if (write_in_full(fd, blob, size) != size)
die("unable to write temp-file");
close(fd);
temp->name = temp->tmp_path;
Expand Down
4 changes: 2 additions & 2 deletions entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat
return error("git-checkout-index: unable to create file %s (%s)",
path, strerror(errno));
}
wrote = write(fd, new, size);
wrote = write_in_full(fd, new, size);
close(fd);
free(new);
if (wrote != size)
Expand All @@ -104,7 +104,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat
return error("git-checkout-index: unable to create "
"file %s (%s)", path, strerror(errno));
}
wrote = write(fd, new, size);
wrote = write_in_full(fd, new, size);
close(fd);
free(new);
if (wrote != size)
Expand Down
2 changes: 1 addition & 1 deletion http-fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
int posn = 0;
struct object_request *obj_req = (struct object_request *)data;
do {
ssize_t retval = write(obj_req->local,
ssize_t retval = xwrite(obj_req->local,
(char *) ptr + posn, size - posn);
if (retval < 0)
return posn;
Expand Down
2 changes: 1 addition & 1 deletion http-push.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
int posn = 0;
struct transfer_request *request = (struct transfer_request *)data;
do {
ssize_t retval = write(request->local_fileno,
ssize_t retval = xwrite(request->local_fileno,
(char *) ptr + posn, size - posn);
if (retval < 0)
return posn;
Expand Down
2 changes: 1 addition & 1 deletion imap-send.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ socket_read( Socket_t *sock, char *buf, int len )
static int
socket_write( Socket_t *sock, const char *buf, int len )
{
int n = write( sock->fd, buf, len );
int n = write_in_full( sock->fd, buf, len );
if (n != len) {
socket_perror( "write", sock, n );
close( sock->fd );
Expand Down
2 changes: 1 addition & 1 deletion index-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
char buf[48];
int len = snprintf(buf, sizeof(buf), "%s\t%s\n",
report, sha1_to_hex(sha1));
xwrite(1, buf, len);
write_in_full(1, buf, len);

/*
* Let's just mimic git-unpack-objects here and write
Expand Down
2 changes: 1 addition & 1 deletion merge-recursive.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ static int mkdir_p(const char *path, unsigned long mode)
static void flush_buffer(int fd, const char *buf, unsigned long size)
{
while (size > 0) {
long ret = xwrite(fd, buf, size);
long ret = write_in_full(fd, buf, size);
if (ret < 0) {
/* Ignore epipe */
if (errno == EPIPE)
Expand Down
6 changes: 3 additions & 3 deletions read-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ static int ce_write_flush(SHA_CTX *context, int fd)
unsigned int buffered = write_buffer_len;
if (buffered) {
SHA1_Update(context, write_buffer, buffered);
if (write(fd, write_buffer, buffered) != buffered)
if (write_in_full(fd, write_buffer, buffered) != buffered)
return -1;
write_buffer_len = 0;
}
Expand Down Expand Up @@ -919,15 +919,15 @@ static int ce_flush(SHA_CTX *context, int fd)

/* Flush first if not enough space for SHA1 signature */
if (left + 20 > WRITE_BUFFER_SIZE) {
if (write(fd, write_buffer, left) != left)
if (write_in_full(fd, write_buffer, left) != left)
return -1;
left = 0;
}

/* Append the SHA1 signature at the end */
SHA1_Final(write_buffer + left, context);
left += 20;
return (write(fd, write_buffer, left) != left) ? -1 : 0;
return (write_in_full(fd, write_buffer, left) != left) ? -1 : 0;
}

static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
Expand Down
8 changes: 4 additions & 4 deletions refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master)
}
lockpath = mkpath("%s.lock", git_HEAD);
fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
written = write(fd, ref, len);
written = write_in_full(fd, ref, len);
close(fd);
if (written != len) {
unlink(lockpath);
Expand Down Expand Up @@ -968,7 +968,7 @@ static int log_ref_write(struct ref_lock *lock,
sha1_to_hex(sha1),
committer);
}
written = len <= maxlen ? write(logfd, logrec, len) : -1;
written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1;
free(logrec);
close(logfd);
if (written != len)
Expand All @@ -987,8 +987,8 @@ int write_ref_sha1(struct ref_lock *lock,
unlock_ref(lock);
return 0;
}
if (write(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
write(lock->lock_fd, &term, 1) != 1
if (write_in_full(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
write_in_full(lock->lock_fd, &term, 1) != 1
|| close(lock->lock_fd) < 0) {
error("Couldn't write %s", lock->lk->filename);
unlock_ref(lock);
Expand Down
19 changes: 6 additions & 13 deletions sha1_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1611,20 +1611,13 @@ int move_temp_to_file(const char *tmpfile, const char *filename)

static int write_buffer(int fd, const void *buf, size_t len)
{
while (len) {
ssize_t size;
ssize_t size;

size = write(fd, buf, len);
if (!size)
return error("file write: disk full");
if (size < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
return error("file write error (%s)", strerror(errno));
}
len -= size;
buf = (char *) buf + size;
}
size = write_in_full(fd, buf, len);
if (!size)
return error("file write: disk full");
if (size < 0)
return error("file write error (%s)", strerror(errno));
return 0;
}

Expand Down
33 changes: 11 additions & 22 deletions ssh-fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,6 @@ static int fd_out;
static unsigned char remote_version;
static unsigned char local_version = 1;

static ssize_t force_write(int fd, void *buffer, size_t length)
{
ssize_t ret = 0;
while (ret < length) {
ssize_t size = write(fd, (char *) buffer + ret, length - ret);
if (size < 0) {
return size;
}
if (size == 0) {
return ret;
}
ret += size;
}
return ret;
}

static int prefetches;

static struct object_list *in_transit;
Expand All @@ -53,8 +37,9 @@ void prefetch(unsigned char *sha1)
node->item = lookup_unknown_object(sha1);
*end_of_transit = node;
end_of_transit = &node->next;
force_write(fd_out, &type, 1);
force_write(fd_out, sha1, 20);
/* XXX: what if these writes fail? */
write_in_full(fd_out, &type, 1);
write_in_full(fd_out, sha1, 20);
prefetches++;
}

Expand Down Expand Up @@ -97,8 +82,10 @@ int fetch(unsigned char *sha1)
static int get_version(void)
{
char type = 'v';
write(fd_out, &type, 1);
write(fd_out, &local_version, 1);
if (write_in_full(fd_out, &type, 1) != 1 ||
write_in_full(fd_out, &local_version, 1)) {
return error("Couldn't request version from remote end");
}
if (xread(fd_in, &remote_version, 1) < 1) {
return error("Couldn't read version from remote end");
}
Expand All @@ -109,8 +96,10 @@ int fetch_ref(char *ref, unsigned char *sha1)
{
signed char remote;
char type = 'r';
write(fd_out, &type, 1);
write(fd_out, ref, strlen(ref) + 1);
int length = strlen(ref) + 1;
if (write_in_full(fd_out, &type, 1) != 1 ||
write_in_full(fd_out, ref, length) != length)
return -1;

if (read_in_full(fd_in, &remote, 1) != 1)
return -1;
Expand Down
10 changes: 6 additions & 4 deletions ssh-upload.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ static int serve_object(int fd_in, int fd_out) {
remote = -1;
}

write(fd_out, &remote, 1);
if (write_in_full(fd_out, &remote, 1) != 1)
return 0;

if (remote < 0)
return 0;
Expand All @@ -53,7 +54,7 @@ static int serve_version(int fd_in, int fd_out)
{
if (xread(fd_in, &remote_version, 1) < 1)
return -1;
write(fd_out, &local_version, 1);
write_in_full(fd_out, &local_version, 1);
return 0;
}

Expand All @@ -74,10 +75,11 @@ static int serve_ref(int fd_in, int fd_out)

if (get_ref_sha1(ref, sha1))
remote = -1;
write(fd_out, &remote, 1);
if (write_in_full(fd_out, &remote, 1) != 1)
return 0;
if (remote)
return 0;
write(fd_out, sha1, 20);
write_in_full(fd_out, sha1, 20);
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion test-delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ int main(int argc, char *argv[])
}

fd = open (argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (fd < 0 || write(fd, out_buf, out_size) != out_size) {
if (fd < 0 || write_in_full(fd, out_buf, out_size) != out_size) {
perror(argv[4]);
return 1;
}
Expand Down
2 changes: 1 addition & 1 deletion unpack-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ static char *create_temp_file(unsigned char *sha1)
fd = mkstemp(path);
if (fd < 0)
die("unable to create temp-file");
if (write(fd, buf, size) != size)
if (write_in_full(fd, buf, size) != size)
die("unable to write temp-file");
close(fd);
return path;
Expand Down
1 change: 1 addition & 0 deletions upload-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
/* emergency quit */
fd = 2;
if (fd == 2) {
/* XXX: are we happy to lose stuff here? */
xwrite(fd, data, sz);
return sz;
}
Expand Down
45 changes: 20 additions & 25 deletions write_or_die.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,45 +33,40 @@ void read_or_die(int fd, void *buf, size_t count)
die("read error (%s)", strerror(errno));
}

void write_or_die(int fd, const void *buf, size_t count)
int write_in_full(int fd, const void *buf, size_t count)
{
const char *p = buf;
ssize_t written;
ssize_t total = 0;
ssize_t written = 0;

while (count > 0) {
written = xwrite(fd, p, count);
if (written == 0)
die("disk full?");
else if (written < 0) {
if (errno == EPIPE)
exit(0);
die("write error (%s)", strerror(errno));
if (written <= 0) {
if (total)
return total;
else
return written;
}
count -= written;
p += written;
total += written;
}

return total;
}

int write_in_full(int fd, const void *buf, size_t count)
void write_or_die(int fd, const void *buf, size_t count)
{
const char *p = buf;
ssize_t total = 0;
ssize_t wcount = 0;
ssize_t written;

while (count > 0) {
wcount = xwrite(fd, p, count);
if (wcount <= 0) {
if (total)
return total;
else
return wcount;
}
count -= wcount;
p += wcount;
total += wcount;
written = write_in_full(fd, buf, count);
if (written == 0)
die("disk full?");
else if (written < 0) {
if (errno == EPIPE)
exit(0);
die("write error (%s)", strerror(errno));
}

return wcount;
}

int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg)
Expand Down

0 comments on commit 93822c2

Please sign in to comment.