1 /*
2  * Permission is hereby granted, free of charge, to any person obtaining a copy
3  * of this software and associated documentation files (the "Software"), to
4  * deal in the Software without restriction, including without limitation the
5  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6  * sell copies of the Software, and to permit persons to whom the Software is
7  * furnished to do so, subject to the following conditions:
8  *
9  * The above copyright notice and this permission notice shall be included in
10  * all copies or substantial portions of the Software.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18  * DEALINGS IN THE SOFTWARE.
19  *
20  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
21  * Use is subject to license terms.
22  */
23 
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <strings.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <pthread.h>
33 
34 #include "xenfsimage_plugin.h"
35 #include "fsimage_priv.h"
36 
37 static pthread_mutex_t fsi_lock = PTHREAD_MUTEX_INITIALIZER;
38 
fsi_open_fsimage(const char * path,uint64_t off,const char * options)39 fsi_t *fsi_open_fsimage(const char *path, uint64_t off, const char *options)
40 {
41 	fsi_t *fsi = NULL;
42 	int fd;
43 	int err;
44 
45 	if ((fd = open(path, O_RDONLY)) == -1)
46 		goto fail;
47 
48 	if ((fsi = malloc(sizeof(*fsi))) == NULL)
49 		goto fail;
50 
51 	fsi->f_fd = fd;
52 	fsi->f_off = off;
53 	fsi->f_data = NULL;
54 	fsi->f_bootstring = NULL;
55 
56 	pthread_mutex_lock(&fsi_lock);
57 	err = find_plugin(fsi, path, options);
58 	pthread_mutex_unlock(&fsi_lock);
59 	if (err != 0)
60 		goto fail;
61 
62 	return (fsi);
63 
64 fail:
65 	err = errno;
66 	if (fd != -1)
67 		(void) close(fd);
68 	free(fsi);
69 	errno = err;
70 	return (NULL);
71 }
72 
fsi_close_fsimage(fsi_t * fsi)73 void fsi_close_fsimage(fsi_t *fsi)
74 {
75 	pthread_mutex_lock(&fsi_lock);
76         fsi->f_plugin->fp_ops->fpo_umount(fsi);
77         (void) close(fsi->f_fd);
78 	free(fsi);
79 	pthread_mutex_unlock(&fsi_lock);
80 }
81 
fsi_file_exists(fsi_t * fsi,const char * path)82 int fsi_file_exists(fsi_t *fsi, const char *path)
83 {
84 	fsi_file_t *ffi;
85 
86 	if ((ffi = fsi_open_file(fsi, path)) == NULL)
87 		return (0);
88 
89 	fsi_close_file(ffi);
90 	return (1);
91 }
92 
fsi_open_file(fsi_t * fsi,const char * path)93 fsi_file_t *fsi_open_file(fsi_t *fsi, const char *path)
94 {
95 	fsi_plugin_ops_t *ops;
96 	fsi_file_t *ffi;
97 
98 	pthread_mutex_lock(&fsi_lock);
99 	ops = fsi->f_plugin->fp_ops;
100 	ffi = ops->fpo_open(fsi, path);
101 	pthread_mutex_unlock(&fsi_lock);
102 
103 	return (ffi);
104 }
105 
fsi_close_file(fsi_file_t * ffi)106 int fsi_close_file(fsi_file_t *ffi)
107 {
108 	fsi_plugin_ops_t *ops;
109 	int err;
110 
111 	pthread_mutex_lock(&fsi_lock);
112 	ops = ffi->ff_fsi->f_plugin->fp_ops;
113 	err = ops->fpo_close(ffi);
114 	pthread_mutex_unlock(&fsi_lock);
115 
116 	return (err);
117 }
118 
fsi_read_file(fsi_file_t * ffi,void * buf,size_t nbytes)119 ssize_t fsi_read_file(fsi_file_t *ffi, void *buf, size_t nbytes)
120 {
121 	fsi_plugin_ops_t *ops;
122 	ssize_t ret;
123 
124 	pthread_mutex_lock(&fsi_lock);
125 	ops = ffi->ff_fsi->f_plugin->fp_ops;
126 	ret = ops->fpo_read(ffi, buf, nbytes);
127 	pthread_mutex_unlock(&fsi_lock);
128 
129 	return (ret);
130 }
131 
fsi_pread_file(fsi_file_t * ffi,void * buf,size_t nbytes,uint64_t off)132 ssize_t fsi_pread_file(fsi_file_t *ffi, void *buf, size_t nbytes, uint64_t off)
133 {
134 	fsi_plugin_ops_t *ops;
135 	ssize_t ret;
136 
137 	pthread_mutex_lock(&fsi_lock);
138 	ops = ffi->ff_fsi->f_plugin->fp_ops;
139 	ret = ops->fpo_pread(ffi, buf, nbytes, off);
140 	pthread_mutex_unlock(&fsi_lock);
141 
142 	return (ret);
143 }
144 
145 char *
fsi_bootstring_alloc(fsi_t * fsi,size_t len)146 fsi_bootstring_alloc(fsi_t *fsi, size_t len)
147 {
148 	fsi->f_bootstring = malloc(len);
149 	if (fsi->f_bootstring == NULL)
150 		return (NULL);
151 
152 	bzero(fsi->f_bootstring, len);
153 	return (fsi->f_bootstring);
154 }
155 
156 void
fsi_bootstring_free(fsi_t * fsi)157 fsi_bootstring_free(fsi_t *fsi)
158 {
159 	if (fsi->f_bootstring != NULL) {
160 		free(fsi->f_bootstring);
161 		fsi->f_bootstring = NULL;
162 	}
163 }
164 
165 char *
fsi_fs_bootstring(fsi_t * fsi)166 fsi_fs_bootstring(fsi_t *fsi)
167 {
168 	return (fsi->f_bootstring);
169 }
170