short i/o: fix calls to read to use xread or read_in_full

We have a number of badly checked read() calls.  Often we are
expecting read() to read exactly the size we requested or fail, this
fails to handle interrupts or short reads.  Add a read_in_full()
providing those semantics.  Otherwise we at a minimum need to check
for EINTR and EAGAIN, where this is appropriate use xread().

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Andy Whitcroft 2007-01-08 15:58:08 +00:00 committed by Junio C Hamano
parent e08140568a
commit 93d26e4cb9
17 changed files with 57 additions and 39 deletions

View File

@ -136,7 +136,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
if (i < 0) if (i < 0)
goto err_ret; goto err_ret;
data = xmalloc(st.st_size + 1); data = xmalloc(st.st_size + 1);
if (st.st_size != xread(i, data, st.st_size)) { if (st.st_size != read_in_full(i, data, st.st_size)) {
error("'%s': short read %s", filename, strerror(errno)); error("'%s': short read %s", filename, strerror(errno));
close(i); close(i);
free(data); free(data);

View File

@ -74,7 +74,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
char *content = buffer + RECORDSIZE; char *content = buffer + RECORDSIZE;
ssize_t n; ssize_t n;
n = xread(0, buffer, HEADERSIZE); n = read_in_full(0, buffer, HEADERSIZE);
if (n < HEADERSIZE) if (n < HEADERSIZE)
die("git-get-tar-commit-id: read error"); die("git-get-tar-commit-id: read error");
if (header->typeflag[0] != 'g') if (header->typeflag[0] != 'g')

View File

@ -91,7 +91,7 @@ static void process_input(int child_fd, int band)
char buf[16384]; char buf[16384];
ssize_t sz = read(child_fd, buf, sizeof(buf)); ssize_t sz = read(child_fd, buf, sizeof(buf));
if (sz < 0) { if (sz < 0) {
if (errno != EINTR) if (errno != EAGAIN && errno != EINTR)
error_clnt("read error: %s\n", strerror(errno)); error_clnt("read error: %s\n", strerror(errno));
return; return;
} }

View File

@ -432,6 +432,7 @@ extern char *git_commit_encoding;
extern char *git_log_output_encoding; extern char *git_log_output_encoding;
extern int copy_fd(int ifd, int ofd); extern int copy_fd(int ifd, int ofd);
extern int read_in_full(int fd, void *buf, size_t count);
extern void read_or_die(int fd, void *buf, size_t count); extern void read_or_die(int fd, void *buf, size_t count);
extern int write_in_full(int fd, const void *buf, size_t count); extern int write_in_full(int fd, const void *buf, size_t count);
extern void write_or_die(int fd, const void *buf, size_t count); extern void write_or_die(int fd, const void *buf, size_t count);

2
dir.c
View File

@ -142,7 +142,7 @@ static int add_excludes_from_file_1(const char *fname,
return 0; return 0;
} }
buf = xmalloc(size+1); buf = xmalloc(size+1);
if (read(fd, buf, size) != size) if (read_in_full(fd, buf, size) != size)
goto err; goto err;
close(fd); close(fd);

View File

@ -175,7 +175,7 @@ static void start_object_request(struct object_request *obj_req)
prevlocal = open(prevfile, O_RDONLY); prevlocal = open(prevfile, O_RDONLY);
if (prevlocal != -1) { if (prevlocal != -1) {
do { do {
prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE); prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE);
if (prev_read>0) { if (prev_read>0) {
if (fwrite_sha1_file(prev_buf, if (fwrite_sha1_file(prev_buf,
1, 1,

View File

@ -288,7 +288,7 @@ static void start_fetch_loose(struct transfer_request *request)
prevlocal = open(prevfile, O_RDONLY); prevlocal = open(prevfile, O_RDONLY);
if (prevlocal != -1) { if (prevlocal != -1) {
do { do {
prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE); prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE);
if (prev_read>0) { if (prev_read>0) {
if (fwrite_sha1_file(prev_buf, if (fwrite_sha1_file(prev_buf,
1, 1,

View File

@ -224,7 +224,7 @@ socket_perror( const char *func, Socket_t *sock, int ret )
static int static int
socket_read( Socket_t *sock, char *buf, int len ) socket_read( Socket_t *sock, char *buf, int len )
{ {
int n = read( sock->fd, buf, len ); int n = xread( sock->fd, buf, len );
if (n <= 0) { if (n <= 0) {
socket_perror( "read", sock, n ); socket_perror( "read", sock, n );
close( sock->fd ); close( sock->fd );
@ -390,7 +390,7 @@ arc4_init( void )
fprintf( stderr, "Fatal: no random number source available.\n" ); fprintf( stderr, "Fatal: no random number source available.\n" );
exit( 3 ); exit( 3 );
} }
if (read( fd, dat, 128 ) != 128) { if (read_in_full( fd, dat, 128 ) != 128) {
fprintf( stderr, "Fatal: cannot read random number source.\n" ); fprintf( stderr, "Fatal: cannot read random number source.\n" );
exit( 3 ); exit( 3 );
} }

View File

@ -638,7 +638,7 @@ static void readjust_pack_header_and_sha1(unsigned char *sha1)
/* Rewrite pack header with updated object number */ /* Rewrite pack header with updated object number */
if (lseek(output_fd, 0, SEEK_SET) != 0) if (lseek(output_fd, 0, SEEK_SET) != 0)
die("cannot seek back: %s", strerror(errno)); die("cannot seek back: %s", strerror(errno));
if (xread(output_fd, &hdr, sizeof(hdr)) != sizeof(hdr)) if (read_in_full(output_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
die("cannot read pack header back: %s", strerror(errno)); die("cannot read pack header back: %s", strerror(errno));
hdr.hdr_entries = htonl(nr_objects); hdr.hdr_entries = htonl(nr_objects);
if (lseek(output_fd, 0, SEEK_SET) != 0) if (lseek(output_fd, 0, SEEK_SET) != 0)

View File

@ -184,7 +184,7 @@ int fetch_ref(char *ref, unsigned char *sha1)
fprintf(stderr, "cannot open %s\n", filename); fprintf(stderr, "cannot open %s\n", filename);
return -1; return -1;
} }
if (read(ifd, hex, 40) != 40 || get_sha1_hex(hex, sha1)) { if (read_in_full(ifd, hex, 40) != 40 || get_sha1_hex(hex, sha1)) {
close(ifd); close(ifd);
fprintf(stderr, "cannot read from %s\n", filename); fprintf(stderr, "cannot read from %s\n", filename);
return -1; return -1;

2
path.c
View File

@ -113,7 +113,7 @@ int validate_symref(const char *path)
fd = open(path, O_RDONLY); fd = open(path, O_RDONLY);
if (fd < 0) if (fd < 0)
return -1; return -1;
len = read(fd, buffer, sizeof(buffer)-1); len = read_in_full(fd, buffer, sizeof(buffer)-1);
close(fd); close(fd);
/* /*

2
refs.c
View File

@ -284,7 +284,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
fd = open(path, O_RDONLY); fd = open(path, O_RDONLY);
if (fd < 0) if (fd < 0)
return NULL; return NULL;
len = read(fd, buffer, sizeof(buffer)-1); len = read_in_full(fd, buffer, sizeof(buffer)-1);
close(fd); close(fd);
/* /*

View File

@ -1869,7 +1869,7 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer,
if (ret != Z_OK) if (ret != Z_OK)
break; break;
} }
size = read(fd, buffer + *bufposn, bufsize - *bufposn); size = xread(fd, buffer + *bufposn, bufsize - *bufposn);
if (size <= 0) { if (size <= 0) {
close(local); close(local);
unlink(tmpfile); unlink(tmpfile);

View File

@ -82,7 +82,7 @@ int fetch(unsigned char *sha1)
remote = conn_buf[0]; remote = conn_buf[0];
memmove(conn_buf, conn_buf + 1, --conn_buf_posn); memmove(conn_buf, conn_buf + 1, --conn_buf_posn);
} else { } else {
if (read(fd_in, &remote, 1) < 1) if (xread(fd_in, &remote, 1) < 1)
return -1; return -1;
} }
/* fprintf(stderr, "Got %d\n", remote); */ /* fprintf(stderr, "Got %d\n", remote); */
@ -99,7 +99,7 @@ static int get_version(void)
char type = 'v'; char type = 'v';
write(fd_out, &type, 1); write(fd_out, &type, 1);
write(fd_out, &local_version, 1); write(fd_out, &local_version, 1);
if (read(fd_in, &remote_version, 1) < 1) { if (xread(fd_in, &remote_version, 1) < 1) {
return error("Couldn't read version from remote end"); return error("Couldn't read version from remote end");
} }
return 0; return 0;
@ -111,10 +111,13 @@ int fetch_ref(char *ref, unsigned char *sha1)
char type = 'r'; char type = 'r';
write(fd_out, &type, 1); write(fd_out, &type, 1);
write(fd_out, ref, strlen(ref) + 1); write(fd_out, ref, strlen(ref) + 1);
read(fd_in, &remote, 1);
if (read_in_full(fd_in, &remote, 1) != 1)
return -1;
if (remote < 0) if (remote < 0)
return remote; return remote;
read(fd_in, sha1, 20); if (read_in_full(fd_in, sha1, 20) != 20)
return -1;
return 0; return 0;
} }

View File

@ -21,17 +21,14 @@ static int serve_object(int fd_in, int fd_out) {
ssize_t size; ssize_t size;
unsigned char sha1[20]; unsigned char sha1[20];
signed char remote; signed char remote;
int posn = 0;
do { size = read_in_full(fd_in, sha1, 20);
size = read(fd_in, sha1 + posn, 20 - posn); if (size < 0) {
if (size < 0) { perror("git-ssh-upload: read ");
perror("git-ssh-upload: read "); return -1;
return -1; }
} if (!size)
if (!size) return -1;
return -1;
posn += size;
} while (posn < 20);
if (verbose) if (verbose)
fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1)); fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1));
@ -54,7 +51,7 @@ static int serve_object(int fd_in, int fd_out) {
static int serve_version(int fd_in, int fd_out) static int serve_version(int fd_in, int fd_out)
{ {
if (read(fd_in, &remote_version, 1) < 1) if (xread(fd_in, &remote_version, 1) < 1)
return -1; return -1;
write(fd_out, &local_version, 1); write(fd_out, &local_version, 1);
return 0; return 0;
@ -67,7 +64,7 @@ static int serve_ref(int fd_in, int fd_out)
int posn = 0; int posn = 0;
signed char remote = 0; signed char remote = 0;
do { do {
if (posn >= PATH_MAX || read(fd_in, ref + posn, 1) < 1) if (posn >= PATH_MAX || xread(fd_in, ref + posn, 1) < 1)
return -1; return -1;
posn++; posn++;
} while (ref[posn - 1]); } while (ref[posn - 1]);
@ -89,7 +86,7 @@ static void service(int fd_in, int fd_out) {
char type; char type;
int retval; int retval;
do { do {
retval = read(fd_in, &type, 1); retval = xread(fd_in, &type, 1);
if (retval < 1) { if (retval < 1) {
if (retval < 0) if (retval < 0)
perror("git-ssh-upload: read "); perror("git-ssh-upload: read ");

View File

@ -242,7 +242,7 @@ static void create_pack_file(void)
*cp++ = buffered; *cp++ = buffered;
outsz++; outsz++;
} }
sz = read(pu_pipe[0], cp, sz = xread(pu_pipe[0], cp,
sizeof(data) - outsz); sizeof(data) - outsz);
if (0 < sz) if (0 < sz)
; ;
@ -267,7 +267,7 @@ static void create_pack_file(void)
/* Status ready; we ship that in the side-band /* Status ready; we ship that in the side-band
* or dump to the standard error. * or dump to the standard error.
*/ */
sz = read(pe_pipe[0], progress, sz = xread(pe_pipe[0], progress,
sizeof(progress)); sizeof(progress));
if (0 < sz) if (0 < sz)
send_client_data(2, progress, sz); send_client_data(2, progress, sz);

View File

@ -1,19 +1,36 @@
#include "cache.h" #include "cache.h"
void read_or_die(int fd, void *buf, size_t count) int read_in_full(int fd, void *buf, size_t count)
{ {
char *p = buf; char *p = buf;
ssize_t loaded; ssize_t total = 0;
ssize_t loaded = 0;
while (count > 0) { while (count > 0) {
loaded = xread(fd, p, count); loaded = xread(fd, p, count);
if (loaded == 0) if (loaded <= 0) {
die("unexpected end of file"); if (total)
else if (loaded < 0) return total;
die("read error (%s)", strerror(errno)); else
return loaded;
}
count -= loaded; count -= loaded;
p += loaded; p += loaded;
total += loaded;
} }
return total;
}
void read_or_die(int fd, void *buf, size_t count)
{
ssize_t loaded;
loaded = read_in_full(fd, buf, count);
if (loaded == 0)
die("unexpected end of file");
else if (loaded < 0)
die("read error (%s)", strerror(errno));
} }
void write_or_die(int fd, const void *buf, size_t count) void write_or_die(int fd, const void *buf, size_t count)