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