1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*
29 * libfstyp module for udfs
30 */
31 #include <fcntl.h>
32 #include <stdio.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <locale.h>
36 #include <stdlib.h>
37 #include <strings.h>
38 #include <sys/param.h>
39 #include <sys/stat.h>
40 #include <sys/time.h>
41 #include <sys/types.h>
42 #include <sys/file.h>
43 #include <libnvpair.h>
44 #include <libfstyp_module.h>
45 #include <sys/fs/udf_volume.h>
46 #include "ud_lib.h"
47
48
49 typedef struct fstyp_udfs {
50 int fd;
51 ud_handle_t udh;
52 nvlist_t *attr;
53 } fstyp_udfs_t;
54
55 static int is_udfs(fstyp_udfs_t *h);
56 static int print_vds(fstyp_udfs_t *h, struct vds *,
57 FILE *fout, FILE *ferr);
58 static int get_attr(fstyp_udfs_t *h);
59
60 int fstyp_mod_init(int fd, off_t offset, fstyp_mod_handle_t *handle);
61 void fstyp_mod_fini(fstyp_mod_handle_t handle);
62 int fstyp_mod_ident(fstyp_mod_handle_t handle);
63 int fstyp_mod_get_attr(fstyp_mod_handle_t handle, nvlist_t **attrp);
64 int fstyp_mod_dump(fstyp_mod_handle_t handle, FILE *fout, FILE *ferr);
65
66
67 int
fstyp_mod_init(int fd,off_t offset,fstyp_mod_handle_t * handle)68 fstyp_mod_init(int fd, off_t offset, fstyp_mod_handle_t *handle)
69 {
70 fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
71
72 if (offset != 0) {
73 return (FSTYP_ERR_OFFSET);
74 }
75
76 if ((h = calloc(1, sizeof (fstyp_udfs_t))) == NULL) {
77 return (FSTYP_ERR_NOMEM);
78 }
79 h->fd = fd;
80
81 if (ud_init(h->fd, &h->udh) != 0) {
82 free(h);
83 return (FSTYP_ERR_NOMEM);
84 }
85
86 *handle = (fstyp_mod_handle_t)h;
87 return (0);
88 }
89
90 void
fstyp_mod_fini(fstyp_mod_handle_t handle)91 fstyp_mod_fini(fstyp_mod_handle_t handle)
92 {
93 fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
94
95 if (h->attr == NULL) {
96 nvlist_free(h->attr);
97 h->attr = NULL;
98 }
99 ud_fini(h->udh);
100 free(h);
101 }
102
103 int
fstyp_mod_ident(fstyp_mod_handle_t handle)104 fstyp_mod_ident(fstyp_mod_handle_t handle)
105 {
106 fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
107
108 return (is_udfs(h));
109 }
110
111 int
fstyp_mod_get_attr(fstyp_mod_handle_t handle,nvlist_t ** attrp)112 fstyp_mod_get_attr(fstyp_mod_handle_t handle, nvlist_t **attrp)
113 {
114 fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
115 int error;
116
117 if (h->attr == NULL) {
118 if (nvlist_alloc(&h->attr, NV_UNIQUE_NAME_TYPE, 0)) {
119 return (FSTYP_ERR_NOMEM);
120 }
121 if ((error = get_attr(h)) != 0) {
122 nvlist_free(h->attr);
123 h->attr = NULL;
124 return (error);
125 }
126 }
127
128 *attrp = h->attr;
129 return (0);
130 }
131
132 int
fstyp_mod_dump(fstyp_mod_handle_t handle,FILE * fout,FILE * ferr)133 fstyp_mod_dump(fstyp_mod_handle_t handle, FILE *fout, FILE *ferr)
134 {
135 fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
136 struct udf *udfs = &h->udh->udfs;
137 int ret;
138
139 (void) fprintf(fout,
140 "Standard Identifier %5s\n", udfs->ecma_id);
141
142 if (udfs->flags & VALID_MVDS) {
143 ret = print_vds(h, &udfs->mvds, fout, ferr);
144 } else {
145 ret = print_vds(h, &udfs->rvds, fout, ferr);
146 }
147
148 return (ret);
149 }
150
151
152 /*
153 * Assumption is that we will confirm to level-1
154 */
155 int
is_udfs(fstyp_udfs_t * h)156 is_udfs(fstyp_udfs_t *h)
157 {
158 struct udf *udfs = &h->udh->udfs;
159 int32_t ret;
160
161 if ((ret = ud_fill_udfs_info(h->udh)) != 0) {
162 return (ret);
163 }
164
165 if ((udfs->flags & VALID_UDFS) == 0) {
166 return (FSTYP_ERR_NO_MATCH);
167 }
168
169 return (0);
170 }
171
172 /*
173 * For now, only return generic attributes.
174 * Will open an RFE to add native attributes.
175 */
176 static int
get_attr(fstyp_udfs_t * h)177 get_attr(fstyp_udfs_t *h)
178 {
179 struct udf *udfs = &h->udh->udfs;
180 struct vds *v;
181 struct pri_vol_desc *pvd;
182 uint32_t len;
183 uint64_t off;
184 uint8_t *buf;
185 int8_t str[64];
186 int ret = 0;
187
188 v = (udfs->flags & VALID_MVDS) ? &udfs->mvds : &udfs->rvds;
189
190 /* allocate buffer */
191 len = udfs->lbsize;
192 if (v->pvd_len > len) {
193 len = v->pvd_len;
194 }
195 if ((buf = (uint8_t *)malloc(len)) == NULL) {
196 return (FSTYP_ERR_NOMEM);
197 }
198
199 (void) nvlist_add_boolean_value(h->attr, "gen_clean", B_TRUE);
200
201 /* Primary Volume Descriptor */
202 if (v->pvd_len != 0) {
203 off = v->pvd_loc * udfs->lbsize;
204 if (ud_read_dev(h->udh, off, buf, v->pvd_len) != 0) {
205 ret = FSTYP_ERR_IO;
206 goto out;
207 }
208 /* LINTED */
209 pvd = (struct pri_vol_desc *)(uint32_t *)buf;
210
211 ud_convert2local(pvd->pvd_vol_id, str, 32);
212 str[32] = '\0';
213 (void) nvlist_add_string(h->attr, "gen_volume_label", str);
214 }
215
216 ret = 0;
217
218 out:
219 free(buf);
220 return (ret);
221 }
222
223 /* ARGSUSED */
224 int
print_vds(fstyp_udfs_t * h,struct vds * v,FILE * fout,FILE * ferr)225 print_vds(fstyp_udfs_t *h, struct vds *v, FILE *fout, FILE *ferr)
226 {
227 struct udf *udfs = &h->udh->udfs;
228 int32_t i;
229 uint32_t len;
230 uint64_t off;
231 uint8_t *buf;
232 int ret = 0;
233
234 /*
235 * All descriptors are 512 bytes
236 * except lvd, usd and lvid
237 * findout the largest and allocate space
238 */
239 len = udfs->lbsize;
240 if (v->lvd_len > len) {
241 len = v->lvd_len;
242 }
243 if (v->usd_len > len) {
244 len = v->usd_len;
245 }
246 if (udfs->lvid_len > len) {
247 len = udfs->lvid_len;
248 }
249
250 if ((buf = (uint8_t *)malloc(len)) == NULL) {
251 return (FSTYP_ERR_NOMEM);
252 }
253
254 /*
255 * Anchor Volume Descriptor
256 */
257 if (udfs->avdp_len != 0) {
258 off = udfs->avdp_loc * udfs->lbsize;
259 if (ud_read_dev(h->udh, off, buf, udfs->avdp_len) != 0) {
260 ret = FSTYP_ERR_IO;
261 goto out;
262 }
263
264 /* LINTED */
265 print_avd(fout, (struct anch_vol_desc_ptr *)buf);
266 }
267
268 /*
269 * Primary Volume Descriptor
270 */
271 if (v->pvd_len != 0) {
272 off = v->pvd_loc * udfs->lbsize;
273 if (ud_read_dev(h->udh, off, buf, v->pvd_len) != 0) {
274 ret = FSTYP_ERR_IO;
275 goto out;
276 }
277
278 /* LINTED */
279 print_pvd(fout, (struct pri_vol_desc *)buf);
280 }
281
282 /*
283 * Implementation Use descriptor
284 */
285 if (v->iud_len != 0) {
286 off = v->iud_loc * udfs->lbsize;
287 if (ud_read_dev(h->udh, off, buf, v->iud_len) != 0) {
288 ret = FSTYP_ERR_IO;
289 goto out;
290 }
291
292 /* LINTED */
293 print_iuvd(fout, (struct iuvd_desc *)buf);
294 }
295
296 /*
297 * Paritions
298 */
299 for (i = 0; i < h->udh->n_parts; i++) {
300 if (v->part_len[i] != 0) {
301 off = v->part_loc[i] * udfs->lbsize;
302 if (ud_read_dev(h->udh, off, buf,
303 v->part_len[i]) != 0) {
304 ret = FSTYP_ERR_IO;
305 goto out;
306 }
307
308 /* LINTED */
309 print_part(fout, (struct part_desc *)buf);
310 }
311 }
312
313 /*
314 * Logical Volume Descriptor
315 */
316 if (v->lvd_len != 0) {
317 off = v->lvd_loc * udfs->lbsize;
318 if (ud_read_dev(h->udh, off, buf, v->lvd_len) != 0) {
319 ret = FSTYP_ERR_IO;
320 goto out;
321 }
322
323 /* LINTED */
324 print_lvd(fout, (struct log_vol_desc *)buf);
325 }
326
327 /*
328 * Unallocated Space Descriptor
329 */
330 if (v->usd_len != 0) {
331 off = v->usd_loc * udfs->lbsize;
332 if (ud_read_dev(h->udh, off, buf, v->usd_len) != 0) {
333 ret = FSTYP_ERR_IO;
334 goto out;
335 }
336
337 /* LINTED */
338 print_usd(fout, (struct unall_spc_desc *)buf);
339 }
340
341 /*
342 * Logical Volume Integrity Descriptor
343 */
344 if (udfs->lvid_len != 0) {
345 off = udfs->lvid_loc * udfs->lbsize;
346 if (ud_read_dev(h->udh, off, buf, udfs->lvid_len) != 0) {
347 ret = FSTYP_ERR_IO;
348 goto out;
349 }
350
351 /* LINTED */
352 print_lvid(fout, (struct log_vol_int_desc *)buf);
353 }
354
355 /*
356 * File Set Descriptor
357 */
358 if (udfs->fsd_len != 0) {
359 off = udfs->fsd_loc * udfs->lbsize;
360 if (ud_read_dev(h->udh, off, buf, udfs->fsd_len) != 0) {
361 ret = FSTYP_ERR_IO;
362 goto out;
363 }
364
365 /* LINTED */
366 print_fsd(fout, h->udh, (struct file_set_desc *)buf);
367 }
368 ret = 0;
369
370 out:
371 free(buf);
372 return (ret);
373 }
374