1 /* $OpenBSD: vioraw.c,v 1.11 2023/09/14 15:25:43 dv Exp $ */
2 /*
3 * Copyright (c) 2018 Ori Bernstein <ori@eigenstate.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <errno.h>
25
26 #include "virtio.h"
27
28 static ssize_t
raw_pread(void * file,char * buf,size_t len,off_t off)29 raw_pread(void *file, char *buf, size_t len, off_t off)
30 {
31 return pread(*(int *)file, buf, len, off);
32 }
33
34 static ssize_t
raw_preadv(void * file,struct iovec * iov,int cnt,off_t offset)35 raw_preadv(void *file, struct iovec *iov, int cnt, off_t offset)
36 {
37 return preadv(*(int *)file, iov, cnt, offset);
38 }
39
40 static ssize_t
raw_pwrite(void * file,char * buf,size_t len,off_t off)41 raw_pwrite(void *file, char *buf, size_t len, off_t off)
42 {
43 return pwrite(*(int *)file, buf, len, off);
44 }
45
46 static ssize_t
raw_pwritev(void * file,struct iovec * iov,int cnt,off_t offset)47 raw_pwritev(void *file, struct iovec *iov, int cnt, off_t offset)
48 {
49 return pwritev(*(int *)file, iov, cnt, offset);
50 }
51
52 static void
raw_close(void * file,int stayopen)53 raw_close(void *file, int stayopen)
54 {
55 if (!stayopen)
56 close(*(int *)file);
57 free(file);
58 }
59
60 /*
61 * Initializes a raw disk image backing file from an fd. Stores the
62 * number of bytes in *szp, returning -1 for error, 0 for success.
63 */
64 int
virtio_raw_init(struct virtio_backing * file,off_t * szp,int * fd,size_t nfd)65 virtio_raw_init(struct virtio_backing *file, off_t *szp, int *fd, size_t nfd)
66 {
67 off_t sz;
68 int *fdp;
69
70 if (nfd != 1)
71 return (-1);
72
73 sz = lseek(fd[0], 0, SEEK_END);
74 if (sz == -1)
75 return (-1);
76
77 fdp = malloc(sizeof(int));
78 if (!fdp)
79 return (-1);
80 *fdp = fd[0];
81 file->p = fdp;
82 file->pread = raw_pread;
83 file->preadv = raw_preadv;
84 file->pwrite = raw_pwrite;
85 file->pwritev = raw_pwritev;
86 file->close = raw_close;
87 *szp = sz;
88 return (0);
89 }
90
91 /*
92 * virtio_raw_create
93 *
94 * Create an empty imagefile with the specified path and size.
95 *
96 * Parameters:
97 * imgfile_path: path to the image file to create
98 * imgsize : size of the image file to create (in bytes)
99 *
100 * Return:
101 * EEXIST: The requested image file already exists
102 * 0 : Image file successfully created
103 * Exxxx : Various other Exxxx errno codes due to other I/O errors
104 */
105 int
virtio_raw_create(const char * imgfile_path,uint64_t imgsize)106 virtio_raw_create(const char *imgfile_path, uint64_t imgsize)
107 {
108 int fd, ret;
109
110 /* Refuse to overwrite an existing image */
111 fd = open(imgfile_path, O_RDWR | O_CREAT | O_TRUNC | O_EXCL,
112 S_IRUSR | S_IWUSR);
113 if (fd == -1)
114 return (errno);
115
116 /* Extend to desired size */
117 if (ftruncate(fd, (off_t)imgsize) == -1) {
118 ret = errno;
119 close(fd);
120 unlink(imgfile_path);
121 return (ret);
122 }
123
124 ret = close(fd);
125 return (ret);
126 }
127