--- 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);