--- squashfs-tools/mksquashfs.c
+++ squashfs-tools/mksquashfs.c
@@ -910,16 +910,41 @@
 }
 
 
-void read_bytes(int fd, long long byte, int bytes, char *buff)
+int read_bytes(int fd, void *buff, int bytes)
+{
+	int res, count;
+
+	for(count = 0; count < bytes; count += res) {
+		res = read(fd, buff + count, bytes - count);
+		if(res < 1) {
+			if(res == 0)
+				goto bytes_read;
+			else if(errno != EINTR) {
+				ERROR("Read failed because %s\n",
+						strerror(errno));
+				return -1;
+			} else
+				res = 0;
+		}
+	}
+
+bytes_read:
+	return count;
+}
+
+
+void read_destination(int fd, long long byte, int bytes, char *buff)
 {
 	off_t off = byte;
 
+	TRACE("read_destination: reading from position 0x%llx, bytes %d\n", byte, bytes);
+
 	pthread_mutex_lock(&pos_mutex);
 	if(lseek(fd, off, SEEK_SET) == -1)
 		BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno));
 
-	if(read(fd, buff, bytes) == -1)
-		BAD_ERROR("Read on destination failed because %s\n", strerror(errno));
+	if(read_bytes(fd, buff, bytes) < bytes)
+		BAD_ERROR("Read on destination failed\n");
 	pthread_mutex_unlock(&pos_mutex);
 }
 
@@ -1455,7 +1480,7 @@
 			data = compressed_buffer->data;
 		else {
 			data = cbuffer;
-			read_bytes(fd, start_block, size, data);
+			read_destination(fd, start_block, size, data);
 		}
 
 		if((res = uncompress((unsigned char *) buffer->data, &bytes, (const unsigned char *) data, size)) != Z_OK) {
@@ -1469,7 +1494,7 @@
 	} else if(compressed_buffer)
 		memcpy(buffer->data, compressed_buffer->data, size);
 	else
-		read_bytes(fd, start_block, size, buffer->data);
+		read_destination(fd, start_block, size, buffer->data);
 
 	return buffer;
 }
@@ -1657,7 +1682,7 @@
 char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE];
 char *read_from_disk(long long start, unsigned int avail_bytes)
 {
-	read_bytes(fd, start, avail_bytes, read_from_file_buffer);
+	read_destination(fd, start, avail_bytes, read_from_file_buffer);
 	return read_from_file_buffer;
 }
 
@@ -1861,7 +1886,7 @@
 				if(dup_buffer)
 					dup_data = dup_buffer->data;
 				else {
-					read_bytes(fd, dup_start, b->size, buffer2);
+					read_destination(fd, dup_start, b->size, buffer2);
 					dup_data = buffer2;
 				}
 				res = memcmp(target_data, dup_data, b->size);
@@ -1926,7 +1951,7 @@
 		file_buffer = cache_get(reader_buffer, 0, 0);
 		file_buffer->sequence = index ++;
 
-		byte = file_buffer->size = read(file, file_buffer->data, block_size);
+		byte = file_buffer->size = read_bytes(file, file_buffer->data, block_size);
 
 		file_buffer->file_size = read_size;
 
@@ -1946,7 +1971,7 @@
 	if(expected == block_size) {
 		char buffer;
 
-		if(read(file, &buffer, 1) == 1)
+		if(read_bytes(file, &buffer, 1) == 1)
 			goto restat;
 	}
 
@@ -3483,7 +3508,7 @@
 	if((metadata = malloc(bytes)) == NULL)
 		BAD_ERROR("Failed to alloc metadata buffer in write_recovery_data\n");
 
-	read_bytes(fd, sBlk->inode_table_start, bytes, metadata);
+	read_destination(fd, sBlk->inode_table_start, bytes, metadata);
 
 	sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid);
 	if((recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1)
@@ -3513,7 +3538,7 @@
 	int fd, recoverfd, bytes;
 	squashfs_super_block orig_sBlk, sBlk;
 	char *metadata;
-	int readbytes;
+	int res;
 	struct stat buf;
 	char header[] = RECOVER_ID;
 	char header2[RECOVER_ID_SIZE];
@@ -3527,15 +3552,21 @@
 	if((fd = open(destination_file, O_RDWR)) == -1)
 		BAD_ERROR("Failed to open destination file because %s\n", strerror(errno));
 
-	if(read(recoverfd, header2, RECOVER_ID_SIZE) == -1)
+	res = read_bytes(recoverfd, header2, RECOVER_ID_SIZE);
+	if(res == -1)
 		BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno));
+	if(res < RECOVER_ID_SIZE)
+		BAD_ERROR("Recovery file appears to be truncated\n");
 	if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 )
 		BAD_ERROR("Not a recovery file\n");
 
-	if(read(recoverfd, &sBlk, sizeof(squashfs_super_block)) == -1)
+	res = read_bytes(recoverfd, &sBlk, sizeof(squashfs_super_block));
+	if(res == -1)
 		BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno));
+	if(res < sizeof(squashfs_super_block))
+		BAD_ERROR("Recovery file appears to be truncated\n");
 
-	read_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &orig_sBlk);
+	read_destination(fd, 0, sizeof(squashfs_super_block), (char *) &orig_sBlk);
 
 	if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(squashfs_super_block) - 4) != 0)
 		BAD_ERROR("Recovery file and destination file do not seem to match\n");
@@ -3545,10 +3576,11 @@
 	if((metadata = malloc(bytes)) == NULL)
 		BAD_ERROR("Failed to alloc metadata buffer in read_recovery_data\n");
 
-	if((readbytes = read(recoverfd, metadata, bytes)) == -1)
+	res = read_bytes(recoverfd, metadata, bytes);
+	if(res == -1)
 		BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno));
 
-	if(readbytes != bytes)
+	if(res < bytes)
 		BAD_ERROR("Recovery file appears to be truncated\n");
 
 	write_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &sBlk);
