17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
50e42deeartem * Common Development and Distribution License (the "License").
60e42deeartem * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
220e42deeartem * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bdstevel@tonic-gate * Use is subject to license terms.
247c478bdstevel@tonic-gate */
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bdstevel@tonic-gate
280e42deeartem/*
290e42deeartem * libfstyp module for udfs
300e42deeartem */
317c478bdstevel@tonic-gate#include <fcntl.h>
327c478bdstevel@tonic-gate#include <stdio.h>
337c478bdstevel@tonic-gate#include <errno.h>
347c478bdstevel@tonic-gate#include <unistd.h>
357c478bdstevel@tonic-gate#include <locale.h>
367c478bdstevel@tonic-gate#include <stdlib.h>
377c478bdstevel@tonic-gate#include <strings.h>
387c478bdstevel@tonic-gate#include <sys/param.h>
397c478bdstevel@tonic-gate#include <sys/stat.h>
407c478bdstevel@tonic-gate#include <sys/time.h>
417c478bdstevel@tonic-gate#include <sys/types.h>
427c478bdstevel@tonic-gate#include <sys/file.h>
430e42deeartem#include <libnvpair.h>
440e42deeartem#include <libfstyp_module.h>
457c478bdstevel@tonic-gate#include <sys/fs/udf_volume.h>
467c478bdstevel@tonic-gate#include "ud_lib.h"
477c478bdstevel@tonic-gate
487c478bdstevel@tonic-gate
490e42deeartemtypedef struct fstyp_udfs {
500e42deeartem	int		fd;
510e42deeartem	ud_handle_t	udh;
520e42deeartem	nvlist_t	*attr;
530e42deeartem} fstyp_udfs_t;
547c478bdstevel@tonic-gate
550e42deeartemstatic int	is_udfs(fstyp_udfs_t *h);
560e42deeartemstatic int	print_vds(fstyp_udfs_t *h, struct vds *,
570e42deeartem		FILE *fout, FILE *ferr);
580e42deeartemstatic int	get_attr(fstyp_udfs_t *h);
590e42deeartem
600e42deeartemint	fstyp_mod_init(int fd, off_t offset, fstyp_mod_handle_t *handle);
610e42deeartemvoid	fstyp_mod_fini(fstyp_mod_handle_t handle);
620e42deeartemint	fstyp_mod_ident(fstyp_mod_handle_t handle);
630e42deeartemint	fstyp_mod_get_attr(fstyp_mod_handle_t handle, nvlist_t **attrp);
640e42deeartemint	fstyp_mod_dump(fstyp_mod_handle_t handle, FILE *fout, FILE *ferr);
657c478bdstevel@tonic-gate
667c478bdstevel@tonic-gate
677c478bdstevel@tonic-gateint
680e42deeartemfstyp_mod_init(int fd, off_t offset, fstyp_mod_handle_t *handle)
697c478bdstevel@tonic-gate{
700e42deeartem	fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
710e42deeartem
720e42deeartem	if (offset != 0) {
730e42deeartem		return (FSTYP_ERR_OFFSET);
747c478bdstevel@tonic-gate	}
757c478bdstevel@tonic-gate
760e42deeartem	if ((h = calloc(1, sizeof (fstyp_udfs_t))) == NULL) {
770e42deeartem		return (FSTYP_ERR_NOMEM);
787c478bdstevel@tonic-gate	}
790e42deeartem	h->fd = fd;
807c478bdstevel@tonic-gate
810e42deeartem	if (ud_init(h->fd, &h->udh) != 0) {
820e42deeartem		free(h);
830e42deeartem		return (FSTYP_ERR_NOMEM);
847c478bdstevel@tonic-gate	}
857c478bdstevel@tonic-gate
860e42deeartem	*handle = (fstyp_mod_handle_t)h;
870e42deeartem	return (0);
880e42deeartem}
890e42deeartem
900e42deeartemvoid
910e42deeartemfstyp_mod_fini(fstyp_mod_handle_t handle)
920e42deeartem{
930e42deeartem	fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
940e42deeartem
950e42deeartem	if (h->attr == NULL) {
960e42deeartem		nvlist_free(h->attr);
970e42deeartem		h->attr = NULL;
980e42deeartem	}
990e42deeartem	ud_fini(h->udh);
1000e42deeartem	free(h);
1010e42deeartem}
1020e42deeartem
1030e42deeartemint
1040e42deeartemfstyp_mod_ident(fstyp_mod_handle_t handle)
1050e42deeartem{
1060e42deeartem	fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
1070e42deeartem
1080e42deeartem	return (is_udfs(h));
1090e42deeartem}
1100e42deeartem
1110e42deeartemint
1120e42deeartemfstyp_mod_get_attr(fstyp_mod_handle_t handle, nvlist_t **attrp)
1130e42deeartem{
1140e42deeartem	fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
1150e42deeartem	int error;
1160e42deeartem
1170e42deeartem	if (h->attr == NULL) {
1180e42deeartem		if (nvlist_alloc(&h->attr, NV_UNIQUE_NAME_TYPE, 0)) {
1190e42deeartem			return (FSTYP_ERR_NOMEM);
1200e42deeartem		}
1210e42deeartem		if ((error = get_attr(h)) != 0) {
1220e42deeartem			nvlist_free(h->attr);
1230e42deeartem			h->attr = NULL;
1240e42deeartem			return (error);
1250e42deeartem		}
1260e42deeartem	}
1270e42deeartem
1280e42deeartem	*attrp = h->attr;
1290e42deeartem	return (0);
1300e42deeartem}
1310e42deeartem
1320e42deeartemint
1330e42deeartemfstyp_mod_dump(fstyp_mod_handle_t handle, FILE *fout, FILE *ferr)
1340e42deeartem{
1350e42deeartem	fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
1360e42deeartem	struct udf *udfs = &h->udh->udfs;
1370e42deeartem	int ret;
1387c478bdstevel@tonic-gate
1390e42deeartem	(void) fprintf(fout,
1400e42deeartem		"Standard Identifier %5s\n", udfs->ecma_id);
1410e42deeartem
1420e42deeartem	if (udfs->flags & VALID_MVDS) {
1430e42deeartem		ret = print_vds(h, &udfs->mvds, fout, ferr);
1440e42deeartem	} else {
1450e42deeartem		ret = print_vds(h, &udfs->rvds, fout, ferr);
1460e42deeartem	}
1477c478bdstevel@tonic-gate
1480e42deeartem	return (ret);
1497c478bdstevel@tonic-gate}
1507c478bdstevel@tonic-gate
1517c478bdstevel@tonic-gate
1527c478bdstevel@tonic-gate/*
1537c478bdstevel@tonic-gate * Assumption is that we will confirm to level-1
1547c478bdstevel@tonic-gate */
1557c478bdstevel@tonic-gateint
1560e42deeartemis_udfs(fstyp_udfs_t *h)
1577c478bdstevel@tonic-gate{
1580e42deeartem	struct udf *udfs = &h->udh->udfs;
1597c478bdstevel@tonic-gate	int32_t ret;
1607c478bdstevel@tonic-gate
1610e42deeartem	if ((ret = ud_fill_udfs_info(h->udh)) != 0) {
1627c478bdstevel@tonic-gate		return (ret);
1637c478bdstevel@tonic-gate	}
1647c478bdstevel@tonic-gate
1650e42deeartem	if ((udfs->flags & VALID_UDFS) == 0) {
1660e42deeartem		return (FSTYP_ERR_NO_MATCH);
1677c478bdstevel@tonic-gate	}
1687c478bdstevel@tonic-gate
1690e42deeartem	return (0);
1700e42deeartem}
1710e42deeartem
1720e42deeartem/*
1730e42deeartem * For now, only return generic attributes.
1740e42deeartem * Will open an RFE to add native attributes.
1750e42deeartem */
1760e42deeartemstatic int
1770e42deeartemget_attr(fstyp_udfs_t *h)
1780e42deeartem{
1790e42deeartem	struct udf *udfs = &h->udh->udfs;
1800e42deeartem	struct vds *v;
1810e42deeartem	struct pri_vol_desc *pvd;
1820e42deeartem	uint32_t len;
1830e42deeartem	uint64_t off;
1840e42deeartem	uint8_t *buf;
1850e42deeartem	int8_t str[64];
1860e42deeartem	int ret = 0;
1870e42deeartem
1880e42deeartem	v = (udfs->flags & VALID_MVDS) ? &udfs->mvds : &udfs->rvds;
1897c478bdstevel@tonic-gate
1900e42deeartem	/* allocate buffer */
1910e42deeartem	len = udfs->lbsize;
1920e42deeartem	if (v->pvd_len > len) {
1930e42deeartem		len = v->pvd_len;
1940e42deeartem	}
1950e42deeartem	if ((buf = (uint8_t *)malloc(len)) == NULL) {
1960e42deeartem		return (FSTYP_ERR_NOMEM);
1977c478bdstevel@tonic-gate	}
1987c478bdstevel@tonic-gate
1990e42deeartem	(void) nvlist_add_boolean_value(h->attr, "gen_clean", B_TRUE);
2007c478bdstevel@tonic-gate
2010e42deeartem	/* Primary Volume Descriptor */
2020e42deeartem	if (v->pvd_len != 0) {
2030e42deeartem		off = v->pvd_loc * udfs->lbsize;
2040e42deeartem		if (ud_read_dev(h->udh, off, buf, v->pvd_len) != 0) {
2050e42deeartem			ret = FSTYP_ERR_IO;
2060e42deeartem			goto out;
2070e42deeartem		}
2080e42deeartem		/* LINTED */
2090e42deeartem		pvd = (struct pri_vol_desc *)(uint32_t *)buf;
2100e42deeartem
2110e42deeartem		ud_convert2local(pvd->pvd_vol_id, str, 32);
2120e42deeartem		str[32] = '\0';
2130e42deeartem		(void) nvlist_add_string(h->attr, "gen_volume_label", str);
2147c478bdstevel@tonic-gate	}
2157c478bdstevel@tonic-gate
2160e42deeartem	ret = 0;
2170e42deeartem
2180e42deeartemout:
2190e42deeartem	free(buf);
2207c478bdstevel@tonic-gate	return (ret);
2217c478bdstevel@tonic-gate}
2227c478bdstevel@tonic-gate
2230e42deeartem/* ARGSUSED */
2247c478bdstevel@tonic-gateint
2250e42deeartemprint_vds(fstyp_udfs_t *h, struct vds *v, FILE *fout, FILE *ferr)
2267c478bdstevel@tonic-gate{
2270e42deeartem	struct udf *udfs = &h->udh->udfs;
2287c478bdstevel@tonic-gate	int32_t i;
2297c478bdstevel@tonic-gate	uint32_t len;
2307c478bdstevel@tonic-gate	uint64_t off;
2317c478bdstevel@tonic-gate	uint8_t *buf;
2320e42deeartem	int	ret = 0;
2337c478bdstevel@tonic-gate
2347c478bdstevel@tonic-gate	/*
2357c478bdstevel@tonic-gate	 * All descriptors are 512 bytes
2367c478bdstevel@tonic-gate	 * except lvd, usd and lvid
2377c478bdstevel@tonic-gate	 * findout the largest and allocate space
2387c478bdstevel@tonic-gate	 */
2390e42deeartem	len = udfs->lbsize;
2407c478bdstevel@tonic-gate	if (v->lvd_len > len) {
2417c478bdstevel@tonic-gate		len = v->lvd_len;
2427c478bdstevel@tonic-gate	}
2437c478bdstevel@tonic-gate	if (v->usd_len > len) {
2447c478bdstevel@tonic-gate		len = v->usd_len;
2457c478bdstevel@tonic-gate	}
2460e42deeartem	if (udfs->lvid_len > len) {
2470e42deeartem		len = udfs->lvid_len;
2487c478bdstevel@tonic-gate	}
2497c478bdstevel@tonic-gate
2507c478bdstevel@tonic-gate	if ((buf = (uint8_t *)malloc(len)) == NULL) {
2510e42deeartem		return (FSTYP_ERR_NOMEM);
2527c478bdstevel@tonic-gate	}
2537c478bdstevel@tonic-gate
2547c478bdstevel@tonic-gate	/*
2557c478bdstevel@tonic-gate	 * Anchor Volume Descriptor
2567c478bdstevel@tonic-gate	 */
2570e42deeartem	if (udfs->avdp_len != 0) {
2580e42deeartem		off = udfs->avdp_loc * udfs->lbsize;
2590e42deeartem		if (ud_read_dev(h->udh, off, buf, udfs->avdp_len) != 0) {
2600e42deeartem			ret = FSTYP_ERR_IO;
2610e42deeartem			goto out;
2627c478bdstevel@tonic-gate		}
2637c478bdstevel@tonic-gate
2647c478bdstevel@tonic-gate		/* LINTED */
2650e42deeartem		print_avd(fout, (struct anch_vol_desc_ptr *)buf);
2667c478bdstevel@tonic-gate	}
2677c478bdstevel@tonic-gate
2687c478bdstevel@tonic-gate	/*
2697c478bdstevel@tonic-gate	 * Primary Volume Descriptor
2707c478bdstevel@tonic-gate	 */
2717c478bdstevel@tonic-gate	if (v->pvd_len != 0) {
2720e42deeartem		off = v->pvd_loc * udfs->lbsize;
2730e42deeartem		if (ud_read_dev(h->udh, off, buf, v->pvd_len) != 0) {
2740e42deeartem			ret = FSTYP_ERR_IO;
2750e42deeartem			goto out;
2767c478bdstevel@tonic-gate		}
2777c478bdstevel@tonic-gate
2787c478bdstevel@tonic-gate		/* LINTED */
2790e42deeartem		print_pvd(fout, (struct pri_vol_desc *)buf);
2807c478bdstevel@tonic-gate	}
2817c478bdstevel@tonic-gate
2827c478bdstevel@tonic-gate	/*
2837c478bdstevel@tonic-gate	 * Implementation Use descriptor
2847c478bdstevel@tonic-gate	 */
2857c478bdstevel@tonic-gate	if (v->iud_len != 0) {
2860e42deeartem		off = v->iud_loc * udfs->lbsize;
2870e42deeartem		if (ud_read_dev(h->udh, off, buf, v->iud_len) != 0) {
2880e42deeartem			ret = FSTYP_ERR_IO;
2890e42deeartem			goto out;
2907c478bdstevel@tonic-gate		}
2917c478bdstevel@tonic-gate
2927c478bdstevel@tonic-gate		/* LINTED */
2930e42deeartem		print_iuvd(fout, (struct iuvd_desc *)buf);
2947c478bdstevel@tonic-gate	}
2957c478bdstevel@tonic-gate
2967c478bdstevel@tonic-gate	/*
2977c478bdstevel@tonic-gate	 * Paritions
2987c478bdstevel@tonic-gate	 */
2990e42deeartem	for (i = 0; i < h->udh->n_parts; i++) {
3007c478bdstevel@tonic-gate		if (v->part_len[i] != 0) {
3010e42deeartem			off = v->part_loc[i] * udfs->lbsize;
3020e42deeartem			if (ud_read_dev(h->udh, off, buf,
3030e42deeartem			    v->part_len[i]) != 0) {
3040e42deeartem				ret = FSTYP_ERR_IO;
3050e42deeartem				goto out;
3067c478bdstevel@tonic-gate			}
3077c478bdstevel@tonic-gate
3087c478bdstevel@tonic-gate			/* LINTED */
3090e42deeartem			print_part(fout, (struct part_desc *)buf);
3107c478bdstevel@tonic-gate		}
3117c478bdstevel@tonic-gate	}
3127c478bdstevel@tonic-gate
3137c478bdstevel@tonic-gate	/*
3147c478bdstevel@tonic-gate	 * Logical Volume Descriptor
3157c478bdstevel@tonic-gate	 */
3167c478bdstevel@tonic-gate	if (v->lvd_len != 0) {
3170e42deeartem		off = v->lvd_loc * udfs->lbsize;
3180e42deeartem		if (ud_read_dev(h->udh, off, buf, v->lvd_len) != 0) {
3190e42deeartem			ret = FSTYP_ERR_IO;
3200e42deeartem			goto out;
3217c478bdstevel@tonic-gate		}
3227c478bdstevel@tonic-gate
3237c478bdstevel@tonic-gate		/* LINTED */
3240e42deeartem		print_lvd(fout, (struct log_vol_desc *)buf);
3257c478bdstevel@tonic-gate	}
3267c478bdstevel@tonic-gate
3277c478bdstevel@tonic-gate	/*
3287c478bdstevel@tonic-gate	 * Unallocated Space Descriptor
3297c478bdstevel@tonic-gate	 */
3307c478bdstevel@tonic-gate	if (v->usd_len != 0) {
3310e42deeartem		off = v->usd_loc * udfs->lbsize;
3320e42deeartem		if (ud_read_dev(h->udh, off, buf, v->usd_len) != 0) {
3330e42deeartem			ret = FSTYP_ERR_IO;
3340e42deeartem			goto out;
3357c478bdstevel@tonic-gate		}
3367c478bdstevel@tonic-gate
3377c478bdstevel@tonic-gate		/* LINTED */
3380e42deeartem		print_usd(fout, (struct unall_spc_desc *)buf);
3397c478bdstevel@tonic-gate	}
3407c478bdstevel@tonic-gate
3417c478bdstevel@tonic-gate	/*
3427c478bdstevel@tonic-gate	 * Logical Volume Integrity Descriptor
3437c478bdstevel@tonic-gate	 */
3440e42deeartem	if (udfs->lvid_len != 0) {
3450e42deeartem		off = udfs->lvid_loc * udfs->lbsize;
3460e42deeartem		if (ud_read_dev(h->udh, off, buf, udfs->lvid_len) != 0) {
3470e42deeartem			ret = FSTYP_ERR_IO;
3480e42deeartem			goto out;
3497c478bdstevel@tonic-gate		}
3507c478bdstevel@tonic-gate
3517c478bdstevel@tonic-gate		/* LINTED */
3520e42deeartem		print_lvid(fout, (struct log_vol_int_desc *)buf);
3537c478bdstevel@tonic-gate	}
3547c478bdstevel@tonic-gate
3557c478bdstevel@tonic-gate	/*
3567c478bdstevel@tonic-gate	 * File Set Descriptor
3577c478bdstevel@tonic-gate	 */
3580e42deeartem	if (udfs->fsd_len != 0) {
3590e42deeartem		off = udfs->fsd_loc * udfs->lbsize;
3600e42deeartem		if (ud_read_dev(h->udh, off, buf, udfs->fsd_len) != 0) {
3610e42deeartem			ret = FSTYP_ERR_IO;
3620e42deeartem			goto out;
3637c478bdstevel@tonic-gate		}
3647c478bdstevel@tonic-gate
3657c478bdstevel@tonic-gate		/* LINTED */
3660e42deeartem		print_fsd(fout, h->udh, (struct file_set_desc *)buf);
3677c478bdstevel@tonic-gate	}
3680e42deeartem	ret = 0;
3697c478bdstevel@tonic-gate
3700e42deeartemout:
3710e42deeartem	free(buf);
3720e42deeartem	return (ret);
3737c478bdstevel@tonic-gate}
374