1*9f532d00SPekka Enberg #include "kvm/disk-image.h" 2*9f532d00SPekka Enberg 3*9f532d00SPekka Enberg #include "kvm/util.h" 4*9f532d00SPekka Enberg 5*9f532d00SPekka Enberg #include <sys/types.h> 6*9f532d00SPekka Enberg #include <sys/mman.h> 7*9f532d00SPekka Enberg #include <sys/stat.h> 8*9f532d00SPekka Enberg #include <stddef.h> 9*9f532d00SPekka Enberg #include <stdlib.h> 10*9f532d00SPekka Enberg #include <unistd.h> 11*9f532d00SPekka Enberg #include <fcntl.h> 12*9f532d00SPekka Enberg 13*9f532d00SPekka Enberg #define SECTOR_SHIFT 9 14*9f532d00SPekka Enberg #define SECTOR_SIZE (1UL << SECTOR_SHIFT) 15*9f532d00SPekka Enberg 16*9f532d00SPekka Enberg struct disk_image *disk_image__open(const char *filename) 17*9f532d00SPekka Enberg { 18*9f532d00SPekka Enberg struct disk_image *self; 19*9f532d00SPekka Enberg struct stat st; 20*9f532d00SPekka Enberg 21*9f532d00SPekka Enberg self = malloc(sizeof *self); 22*9f532d00SPekka Enberg if (!self) 23*9f532d00SPekka Enberg return NULL; 24*9f532d00SPekka Enberg 25*9f532d00SPekka Enberg self->fd = open(filename, O_RDONLY); 26*9f532d00SPekka Enberg if (self->fd < 0) 27*9f532d00SPekka Enberg goto failed_free; 28*9f532d00SPekka Enberg 29*9f532d00SPekka Enberg if (fstat(self->fd, &st) < 0) 30*9f532d00SPekka Enberg goto failed_close_fd; 31*9f532d00SPekka Enberg 32*9f532d00SPekka Enberg self->size = st.st_size; 33*9f532d00SPekka Enberg 34*9f532d00SPekka Enberg self->mmap = mmap(NULL, self->size, PROT_READ, MAP_PRIVATE, self->fd, 0); 35*9f532d00SPekka Enberg if (self->mmap == MAP_FAILED) 36*9f532d00SPekka Enberg goto failed_close_fd; 37*9f532d00SPekka Enberg 38*9f532d00SPekka Enberg return self; 39*9f532d00SPekka Enberg 40*9f532d00SPekka Enberg failed_close_fd: 41*9f532d00SPekka Enberg close(self->fd); 42*9f532d00SPekka Enberg failed_free: 43*9f532d00SPekka Enberg free(self); 44*9f532d00SPekka Enberg 45*9f532d00SPekka Enberg return NULL; 46*9f532d00SPekka Enberg } 47*9f532d00SPekka Enberg 48*9f532d00SPekka Enberg void disk_image__close(struct disk_image *self) 49*9f532d00SPekka Enberg { 50*9f532d00SPekka Enberg if (munmap(self->mmap, self->size) < 0) 51*9f532d00SPekka Enberg warning("munmap() failed"); 52*9f532d00SPekka Enberg 53*9f532d00SPekka Enberg if (close(self->fd) < 0) 54*9f532d00SPekka Enberg warning("close() failed"); 55*9f532d00SPekka Enberg 56*9f532d00SPekka Enberg free(self); 57*9f532d00SPekka Enberg } 58*9f532d00SPekka Enberg 59*9f532d00SPekka Enberg int disk_image__read_sector(struct disk_image *self, uint64_t sector, void *dst) 60*9f532d00SPekka Enberg { 61*9f532d00SPekka Enberg uint64_t offset = sector << SECTOR_SHIFT; 62*9f532d00SPekka Enberg 63*9f532d00SPekka Enberg if (offset + SECTOR_SIZE > self->size) 64*9f532d00SPekka Enberg return -1; 65*9f532d00SPekka Enberg 66*9f532d00SPekka Enberg memcpy(dst, self->mmap + offset, SECTOR_SIZE); 67*9f532d00SPekka Enberg 68*9f532d00SPekka Enberg return 0; 69*9f532d00SPekka Enberg } 70