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 2006 Sun Microsystems, Inc. All rights reserved.
21 * Use is subject to license terms.
22 */
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <strings.h>
27 #include <string.h>
28 #include <dirent.h>
29 #include <dlfcn.h>
30 #include <errno.h>
31
32 #include "xenfsimage_plugin.h"
33 #include "fsimage_priv.h"
34
35 static fsi_plugin_t *plugins;
36
37 void
fsip_fs_set_data(fsi_t * fsi,void * data)38 fsip_fs_set_data(fsi_t *fsi, void *data)
39 {
40 fsi->f_data = data;
41 }
42
43 fsi_file_t *
fsip_file_alloc(fsi_t * fsi,void * data)44 fsip_file_alloc(fsi_t *fsi, void *data)
45 {
46 fsi_file_t *ffi = malloc(sizeof (fsi_file_t));
47 if (ffi == NULL)
48 return (NULL);
49
50 bzero(ffi, sizeof (fsi_file_t));
51
52 ffi->ff_fsi = fsi;
53 ffi->ff_data = data;
54 return (ffi);
55 }
56
57 void
fsip_file_free(fsi_file_t * ffi)58 fsip_file_free(fsi_file_t *ffi)
59 {
60 free(ffi);
61 }
62
63 fsi_t *
fsip_fs(fsi_file_t * ffi)64 fsip_fs(fsi_file_t *ffi)
65 {
66 return (ffi->ff_fsi);
67 }
68
69 uint64_t
fsip_fs_offset(fsi_t * fsi)70 fsip_fs_offset(fsi_t *fsi)
71 {
72 return (fsi->f_off);
73 }
74
75 void *
fsip_fs_data(fsi_t * fsi)76 fsip_fs_data(fsi_t *fsi)
77 {
78 return (fsi->f_data);
79 }
80
81 void *
fsip_file_data(fsi_file_t * ffi)82 fsip_file_data(fsi_file_t *ffi)
83 {
84 return (ffi->ff_data);
85 }
86
init_plugin(const char * lib)87 static int init_plugin(const char *lib)
88 {
89 fsi_plugin_init_t init;
90 fsi_plugin_t *fp = malloc(sizeof (fsi_plugin_t));
91
92 if (fp == NULL)
93 return (-1);
94
95 bzero(fp, sizeof (fsi_plugin_t));
96
97 if ((fp->fp_dlh = dlopen(lib, RTLD_LAZY | RTLD_LOCAL)) == NULL) {
98 free(fp);
99 return (0);
100 }
101
102 init = dlsym(fp->fp_dlh, "fsi_init_plugin");
103
104 if (init == NULL)
105 goto fail;
106
107 fp->fp_ops = init(FSIMAGE_PLUGIN_VERSION, fp, &fp->fp_name);
108 if (fp->fp_ops == NULL ||
109 fp->fp_ops->fpo_version > FSIMAGE_PLUGIN_VERSION)
110 goto fail;
111
112 fp->fp_next = plugins;
113 plugins = fp;
114
115 return (0);
116 fail:
117 (void) dlclose(fp->fp_dlh);
118 free(fp);
119 return (-1);
120 }
121
load_plugins(void)122 static int load_plugins(void)
123 {
124 const char *fsdir = getenv("XEN_FSIMAGE_FSDIR");
125 struct dirent *dp = NULL;
126 DIR *dir = NULL;
127 char *tmp = NULL;
128 size_t name_max;
129 int err;
130 int ret = -1;
131
132 if (fsdir == NULL)
133 fsdir = FSIMAGE_FSDIR;
134
135 if ((name_max = pathconf(fsdir, _PC_NAME_MAX)) == -1)
136 goto fail;
137
138 if ((tmp = malloc(name_max + 1)) == NULL)
139 goto fail;
140
141 if ((dir = opendir(fsdir)) == NULL)
142 goto fail;
143
144 for (;;) {
145 errno = 0;
146 dp = readdir(dir);
147
148 if (dp == NULL && errno != 0)
149 goto fail;
150
151 if (dp == NULL)
152 break;
153
154 if (strcmp(dp->d_name, ".") == 0)
155 continue;
156 if (strcmp(dp->d_name, "..") == 0)
157 continue;
158
159 (void) snprintf(tmp, name_max, "%s/%s/fsimage.so", fsdir,
160 dp->d_name);
161
162 if (init_plugin(tmp) != 0)
163 goto fail;
164 }
165
166 ret = 0;
167
168 fail:
169 err = errno;
170 if (dir != NULL)
171 (void) closedir(dir);
172 free(tmp);
173 free(dp);
174 errno = err;
175 return (ret);
176 }
177
find_plugin(fsi_t * fsi,const char * path,const char * options)178 int find_plugin(fsi_t *fsi, const char *path, const char *options)
179 {
180 fsi_plugin_t *fp;
181 int ret = 0;
182
183 if (plugins == NULL && (ret = load_plugins()) != 0)
184 goto out;
185
186 for (fp = plugins; fp != NULL; fp = fp->fp_next) {
187 fsi->f_plugin = fp;
188 if (fp->fp_ops->fpo_mount(fsi, path, options) == 0)
189 goto out;
190 }
191
192 ret = -1;
193 errno = ENOTSUP;
194 out:
195 return (ret);
196 }
197