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