xref: /kvmtool/disk/core.c (revision 5a24a9f2794e70acd0396188a90f8deb7d868d9a)
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