direct-io.hg

view tools/libfsimage/common/fsimage_grub.c @ 12351:ac10e3047f36

[LIBFSIMAGE] Don't leak FDs or RAM when closing filesystems
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Fri Nov 10 12:27:56 2006 +0000 (2006-11-10)
parents f54e29a3be1f
children fead92ec6b2d
line source
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 */
24 #ifndef __sun__
25 #define _XOPEN_SOURCE 500
26 #endif
27 #include <stdlib.h>
28 #include <strings.h>
29 #include <errno.h>
31 #include "fsimage_grub.h"
32 #include "fsimage_priv.h"
34 static char *disk_read_junk;
36 typedef struct fsig_data {
37 char fd_buf[FSYS_BUFLEN];
38 } fsig_data_t;
40 typedef struct fsig_file_data {
41 char ffd_buf[FSYS_BUFLEN];
42 uint64_t ffd_curpos;
43 uint64_t ffd_filepos;
44 uint64_t ffd_filemax;
45 int ffd_int1;
46 int ffd_int2;
47 int ffd_errnum;
48 } fsig_file_data_t;
50 fsi_file_t *
51 fsig_file_alloc(fsi_t *fsi)
52 {
53 fsi_file_t *ffi;
54 fsig_file_data_t *data = malloc(sizeof (fsig_file_data_t));
56 if (data == NULL)
57 return (NULL);
59 bzero(data, sizeof (fsig_file_data_t));
60 bcopy(fsig_fs_buf(fsi), data->ffd_buf, FSYS_BUFLEN);
62 if ((ffi = fsip_file_alloc(fsi, data)) == NULL) {
63 free(data);
64 return (NULL);
65 }
67 return (ffi);
68 }
70 void *
71 fsig_fs_buf(fsi_t *fsi)
72 {
73 fsig_data_t *data = fsip_fs_data(fsi);
74 return ((void *)data->fd_buf);
75 }
77 void *
78 fsig_file_buf(fsi_file_t *ffi)
79 {
80 fsig_file_data_t *data = fsip_file_data(ffi);
81 return ((void *)data->ffd_buf);
82 }
84 uint64_t *
85 fsig_filepos(fsi_file_t *ffi)
86 {
87 fsig_file_data_t *data = fsip_file_data(ffi);
88 return (&data->ffd_filepos);
89 }
91 uint64_t *
92 fsig_filemax(fsi_file_t *ffi)
93 {
94 fsig_file_data_t *data = fsip_file_data(ffi);
95 return (&data->ffd_filemax);
96 }
98 int *
99 fsig_int1(fsi_file_t *ffi)
100 {
101 fsig_file_data_t *data = fsip_file_data(ffi);
102 return (&data->ffd_int1);
103 }
105 int *
106 fsig_int2(fsi_file_t *ffi)
107 {
108 fsig_file_data_t *data = fsip_file_data(ffi);
109 return (&data->ffd_int2);
110 }
112 int *
113 fsig_errnum(fsi_file_t *ffi)
114 {
115 fsig_file_data_t *data = fsip_file_data(ffi);
116 return (&data->ffd_errnum);
117 }
119 char **
120 fsig_disk_read_junk(void)
121 {
122 return (&disk_read_junk);
123 }
125 int
126 fsig_devread(fsi_file_t *ffi, unsigned int sector, unsigned int offset,
127 unsigned int bufsize, char *buf)
128 {
129 uint64_t off = ffi->ff_fsi->f_off + ((uint64_t)(sector * 512)) + offset;
130 ssize_t bytes_read = 0;
132 while (bufsize) {
133 ssize_t ret = pread(ffi->ff_fsi->f_fd, buf + bytes_read,
134 bufsize, (off_t)off);
135 if (ret == -1)
136 return (0);
137 if (ret == 0)
138 return (0);
140 bytes_read += ret;
141 bufsize -= ret;
142 }
144 return (1);
145 }
147 int
148 fsig_substring(const char *s1, const char *s2)
149 {
150 while (*s1 == *s2) {
151 if (*s1 == '\0')
152 return (0);
153 s1++;
154 s2++;
155 }
157 if (*s1 == '\0')
158 return (-1);
160 return (1);
161 }
163 static int
164 fsig_mount(fsi_t *fsi, const char *path)
165 {
166 fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data;
167 fsi_file_t *ffi;
168 fsi->f_data = malloc(sizeof (fsig_data_t));
170 if (fsi->f_data == NULL)
171 return (-1);
173 if ((ffi = fsig_file_alloc(fsi)) == NULL) {
174 free(fsi->f_data);
175 fsi->f_data = NULL;
176 return (-1);
177 }
179 bzero(fsi->f_data, sizeof (fsig_data_t));
181 if (!ops->fpo_mount(ffi)) {
182 fsip_file_free(ffi);
183 free(fsi->f_data);
184 fsi->f_data = NULL;
185 return (-1);
186 }
188 bcopy(fsig_file_buf(ffi), fsig_fs_buf(fsi), FSYS_BUFLEN);
189 fsip_file_free(ffi);
190 return (0);
191 }
193 static int
194 fsig_umount(fsi_t *fsi)
195 {
196 return (0);
197 }
199 static fsi_file_t *
200 fsig_open(fsi_t *fsi, const char *name)
201 {
202 fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data;
203 char *path = strdup(name);
204 fsi_file_t *ffi = NULL;
206 if (path == NULL || (ffi = fsig_file_alloc(fsi)) == NULL)
207 goto out;
209 if (ops->fpo_dir(ffi, path) == 0) {
210 fsip_file_free(ffi);
211 ffi = NULL;
212 errno = ENOENT;
213 }
215 out:
216 free(path);
217 return (ffi);
218 }
220 static ssize_t
221 fsig_pread(fsi_file_t *ffi, void *buf, size_t nbytes, uint64_t off)
222 {
223 fsig_plugin_ops_t *ops = ffi->ff_fsi->f_plugin->fp_data;
224 fsig_file_data_t *data = fsip_file_data(ffi);
226 data->ffd_filepos = off;
228 if (data->ffd_filepos >= data->ffd_filemax)
229 return (0);
231 /* FIXME: check */
232 if (data->ffd_filepos + nbytes > data->ffd_filemax)
233 nbytes = data->ffd_filemax - data->ffd_filepos;
235 errnum = 0;
236 return (ops->fpo_read(ffi, buf, nbytes));
237 }
239 static ssize_t
240 fsig_read(fsi_file_t *ffi, void *buf, size_t nbytes)
241 {
242 fsig_file_data_t *data = fsip_file_data(ffi);
243 ssize_t ret;
245 ret = fsig_pread(ffi, buf, nbytes, data->ffd_curpos);
246 data->ffd_curpos = data->ffd_filepos;
247 return (ret);
248 }
250 static int
251 fsig_close(fsi_file_t *ffi)
252 {
253 fsip_file_free(ffi);
254 return (0);
255 }
257 static fsi_plugin_ops_t fsig_grub_ops = {
258 .fpo_version = FSIMAGE_PLUGIN_VERSION,
259 .fpo_mount = fsig_mount,
260 .fpo_umount = fsig_umount,
261 .fpo_open = fsig_open,
262 .fpo_read = fsig_read,
263 .fpo_pread = fsig_pread,
264 .fpo_close = fsig_close
265 };
267 fsi_plugin_ops_t *
268 fsig_init(fsi_plugin_t *plugin, fsig_plugin_ops_t *ops)
269 {
270 if (ops->fpo_version > FSIMAGE_PLUGIN_VERSION)
271 return (NULL);
273 plugin->fp_data = ops;
275 return (&fsig_grub_ops);
276 }