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 <xenfsimage_plugin.h>
25 #include INCLUDE_EXTFS_H
26 #include <errno.h>
27 #include <inttypes.h>
28 
29 static int
ext2lib_mount(fsi_t * fsi,const char * name,const char * options)30 ext2lib_mount(fsi_t *fsi, const char *name, const char *options)
31 {
32 	int err;
33 	char opts[30] = "";
34 	ext2_filsys *fs;
35 	uint64_t offset = fsip_fs_offset(fsi);
36 
37 	if (offset)
38 		snprintf(opts, 29, "offset=%" PRId64, offset);
39 
40 	fs = malloc(sizeof (*fs));
41 	if (fs == NULL)
42 		return (-1);
43 
44 	err = ext2fs_open2(name, opts, 0, 0, 0, unix_io_manager, fs);
45 
46 	if (err != 0) {
47 		free(fs);
48 		errno = EINVAL;
49 		return (-1);
50 	}
51 
52 	fsip_fs_set_data(fsi, fs);
53 	return (0);
54 }
55 
56 static int
ext2lib_umount(fsi_t * fsi)57 ext2lib_umount(fsi_t *fsi)
58 {
59 	ext2_filsys *fs = fsip_fs_data(fsi);
60 	if (ext2fs_close(*fs) != 0) {
61 		free(fs);
62 		errno = EINVAL;
63 		return (-1);
64 	}
65 	free(fs);
66 	return (0);
67 }
68 
69 fsi_file_t *
ext2lib_open(fsi_t * fsi,const char * path)70 ext2lib_open(fsi_t *fsi, const char *path)
71 {
72 	ext2_ino_t ino;
73 	ext2_filsys *fs = fsip_fs_data(fsi);
74 	ext2_file_t *f;
75 	fsi_file_t *file;
76 	int err;
77 
78 	err = ext2fs_namei_follow(*fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
79 	    path, &ino);
80 
81 	if (err != 0) {
82 		errno = ENOENT;
83 		return (NULL);
84 	}
85 
86 	f = malloc(sizeof (*f));
87 	if (f == NULL)
88 		return (NULL);
89 
90 	err = ext2fs_file_open(*fs, ino, 0, f);
91 
92 	if (err != 0) {
93 		free(f);
94 		errno = EINVAL;
95 		return (NULL);
96 	}
97 
98 	file = fsip_file_alloc(fsi, f);
99 	if (file == NULL)
100 		free(f);
101 	return (file);
102 }
103 
104 ssize_t
ext2lib_read(fsi_file_t * file,void * buf,size_t nbytes)105 ext2lib_read(fsi_file_t *file, void *buf, size_t nbytes)
106 {
107 	ext2_file_t *f = fsip_file_data(file);
108 	unsigned int n;
109 	int err;
110 
111 	err = ext2fs_file_read(*f, buf, nbytes, &n);
112 	if (err != 0) {
113 		errno = EINVAL;
114 		return (-1);
115 	}
116 
117 	return (n);
118 }
119 
120 ssize_t
ext2lib_pread(fsi_file_t * file,void * buf,size_t nbytes,uint64_t off)121 ext2lib_pread(fsi_file_t *file, void *buf, size_t nbytes, uint64_t off)
122 {
123 	ext2_file_t *f = fsip_file_data(file);
124 	__u64 tmpoff;
125 	unsigned int n;
126 	int err;
127 
128 	if ((err = ext2fs_file_llseek(*f, 0, EXT2_SEEK_CUR, &tmpoff)) != 0) {
129 		errno = EINVAL;
130 		return (-1);
131 	}
132 
133 	if ((err = ext2fs_file_llseek(*f, off, EXT2_SEEK_SET, NULL)) != 0) {
134 		errno = EINVAL;
135 		return (-1);
136 	}
137 
138 	err = ext2fs_file_read(*f, buf, nbytes, &n);
139 
140 	ext2fs_file_llseek(*f, tmpoff, EXT2_SEEK_SET, NULL);
141 
142 	if (err != 0) {
143 		errno = EINVAL;
144 		return (-1);
145 	}
146 
147 	return (n);
148 }
149 
150 int
ext2lib_close(fsi_file_t * file)151 ext2lib_close(fsi_file_t *file)
152 {
153 	ext2_file_t *f = fsip_file_data(file);
154 	ext2fs_file_close(*f);
155 	free(f);
156 	return (0);
157 }
158 
159 fsi_plugin_ops_t *
fsi_init_plugin(int version,fsi_plugin_t * fp,const char ** name)160 fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
161 {
162 	static fsi_plugin_ops_t ops = {
163 		FSIMAGE_PLUGIN_VERSION,
164 		.fpo_mount = ext2lib_mount,
165 		.fpo_umount = ext2lib_umount,
166 		.fpo_open = ext2lib_open,
167 		.fpo_read = ext2lib_read,
168 		.fpo_pread = ext2lib_pread,
169 		.fpo_close = ext2lib_close
170 	};
171 
172 	*name = "ext2fs-lib";
173 	return (&ops);
174 }
175