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