19f532d00SPekka Enberg #include "kvm/disk-image.h" 29f532d00SPekka Enberg 39f532d00SPekka Enberg #include "kvm/util.h" 49f532d00SPekka Enberg 59f532d00SPekka Enberg #include <sys/types.h> 69f532d00SPekka Enberg #include <sys/mman.h> 79f532d00SPekka Enberg #include <sys/stat.h> 89f532d00SPekka Enberg #include <stddef.h> 99f532d00SPekka Enberg #include <stdlib.h> 109f532d00SPekka Enberg #include <unistd.h> 119f532d00SPekka Enberg #include <fcntl.h> 129f532d00SPekka Enberg 139f532d00SPekka Enberg #define SECTOR_SHIFT 9 149f532d00SPekka Enberg #define SECTOR_SIZE (1UL << SECTOR_SHIFT) 159f532d00SPekka Enberg 169f532d00SPekka Enberg struct disk_image *disk_image__open(const char *filename) 179f532d00SPekka Enberg { 189f532d00SPekka Enberg struct disk_image *self; 199f532d00SPekka Enberg struct stat st; 209f532d00SPekka Enberg 219f532d00SPekka Enberg self = malloc(sizeof *self); 229f532d00SPekka Enberg if (!self) 239f532d00SPekka Enberg return NULL; 249f532d00SPekka Enberg 259f532d00SPekka Enberg self->fd = open(filename, O_RDONLY); 269f532d00SPekka Enberg if (self->fd < 0) 279f532d00SPekka Enberg goto failed_free; 289f532d00SPekka Enberg 299f532d00SPekka Enberg if (fstat(self->fd, &st) < 0) 309f532d00SPekka Enberg goto failed_close_fd; 319f532d00SPekka Enberg 329f532d00SPekka Enberg self->size = st.st_size; 339f532d00SPekka Enberg 349f532d00SPekka Enberg self->mmap = mmap(NULL, self->size, PROT_READ, MAP_PRIVATE, self->fd, 0); 359f532d00SPekka Enberg if (self->mmap == MAP_FAILED) 369f532d00SPekka Enberg goto failed_close_fd; 379f532d00SPekka Enberg 389f532d00SPekka Enberg return self; 399f532d00SPekka Enberg 409f532d00SPekka Enberg failed_close_fd: 419f532d00SPekka Enberg close(self->fd); 429f532d00SPekka Enberg failed_free: 439f532d00SPekka Enberg free(self); 449f532d00SPekka Enberg 459f532d00SPekka Enberg return NULL; 469f532d00SPekka Enberg } 479f532d00SPekka Enberg 489f532d00SPekka Enberg void disk_image__close(struct disk_image *self) 499f532d00SPekka Enberg { 509f532d00SPekka Enberg if (munmap(self->mmap, self->size) < 0) 519f532d00SPekka Enberg warning("munmap() failed"); 529f532d00SPekka Enberg 539f532d00SPekka Enberg if (close(self->fd) < 0) 549f532d00SPekka Enberg warning("close() failed"); 559f532d00SPekka Enberg 569f532d00SPekka Enberg free(self); 579f532d00SPekka Enberg } 589f532d00SPekka Enberg 59*5a24a9f2SPekka Enberg int disk_image__read_sector(struct disk_image *self, uint64_t sector, void *dst, uint32_t dst_len) 609f532d00SPekka Enberg { 619f532d00SPekka Enberg uint64_t offset = sector << SECTOR_SHIFT; 629f532d00SPekka Enberg 63*5a24a9f2SPekka Enberg if (offset + dst_len > self->size) 649f532d00SPekka Enberg return -1; 659f532d00SPekka Enberg 66*5a24a9f2SPekka Enberg memcpy(dst, self->mmap + offset, dst_len); 679f532d00SPekka Enberg 689f532d00SPekka Enberg return 0; 699f532d00SPekka Enberg } 70