xref: /illumos-gate/usr/src/cmd/fs.d/udfs/fstyp/fstyp.c (revision 0e42dee6)
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
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
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
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
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
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
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
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
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