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>
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);
{
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;
}
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");
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;
buf[buflen++] = '\n';
buf[buflen] = '\0';
- write(2, buf, buflen);
+ write_in_full(2, buf, buflen);
}
static void logerror(const char *err, ...)
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;
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)
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)
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;
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;
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 );
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
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)
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;
}
/* 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)
}
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);
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)
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);
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;
}
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;
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++;
}
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");
}
{
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;
remote = -1;
}
- write(fd_out, &remote, 1);
+ if (write_in_full(fd_out, &remote, 1) != 1)
+ return 0;
if (remote < 0)
return 0;
{
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;
}
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;
}
}
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;
}
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;
/* emergency quit */
fd = 2;
if (fd == 2) {
+ /* XXX: are we happy to lose stuff here? */
xwrite(fd, data, sz);
return sz;
}
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)