/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * libfstyp module for udfs */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ud_lib.h" typedef struct fstyp_udfs { int fd; ud_handle_t udh; nvlist_t *attr; } fstyp_udfs_t; static int is_udfs(fstyp_udfs_t *h); static int print_vds(fstyp_udfs_t *h, struct vds *, FILE *fout, FILE *ferr); static int get_attr(fstyp_udfs_t *h); int fstyp_mod_init(int fd, off_t offset, fstyp_mod_handle_t *handle); void fstyp_mod_fini(fstyp_mod_handle_t handle); int fstyp_mod_ident(fstyp_mod_handle_t handle); int fstyp_mod_get_attr(fstyp_mod_handle_t handle, nvlist_t **attrp); int fstyp_mod_dump(fstyp_mod_handle_t handle, FILE *fout, FILE *ferr); int fstyp_mod_init(int fd, off_t offset, fstyp_mod_handle_t *handle) { fstyp_udfs_t *h = (fstyp_udfs_t *)handle; if (offset != 0) { return (FSTYP_ERR_OFFSET); } if ((h = calloc(1, sizeof (fstyp_udfs_t))) == NULL) { return (FSTYP_ERR_NOMEM); } h->fd = fd; if (ud_init(h->fd, &h->udh) != 0) { free(h); return (FSTYP_ERR_NOMEM); } *handle = (fstyp_mod_handle_t)h; return (0); } void fstyp_mod_fini(fstyp_mod_handle_t handle) { fstyp_udfs_t *h = (fstyp_udfs_t *)handle; if (h->attr == NULL) { nvlist_free(h->attr); h->attr = NULL; } ud_fini(h->udh); free(h); } int fstyp_mod_ident(fstyp_mod_handle_t handle) { fstyp_udfs_t *h = (fstyp_udfs_t *)handle; return (is_udfs(h)); } int fstyp_mod_get_attr(fstyp_mod_handle_t handle, nvlist_t **attrp) { fstyp_udfs_t *h = (fstyp_udfs_t *)handle; int error; if (h->attr == NULL) { if (nvlist_alloc(&h->attr, NV_UNIQUE_NAME_TYPE, 0)) { return (FSTYP_ERR_NOMEM); } if ((error = get_attr(h)) != 0) { nvlist_free(h->attr); h->attr = NULL; return (error); } } *attrp = h->attr; return (0); } int fstyp_mod_dump(fstyp_mod_handle_t handle, FILE *fout, FILE *ferr) { fstyp_udfs_t *h = (fstyp_udfs_t *)handle; struct udf *udfs = &h->udh->udfs; int ret; (void) fprintf(fout, "Standard Identifier %5s\n", udfs->ecma_id); if (udfs->flags & VALID_MVDS) { ret = print_vds(h, &udfs->mvds, fout, ferr); } else { ret = print_vds(h, &udfs->rvds, fout, ferr); } return (ret); } /* * Assumption is that we will confirm to level-1 */ int is_udfs(fstyp_udfs_t *h) { struct udf *udfs = &h->udh->udfs; int32_t ret; if ((ret = ud_fill_udfs_info(h->udh)) != 0) { return (ret); } if ((udfs->flags & VALID_UDFS) == 0) { return (FSTYP_ERR_NO_MATCH); } return (0); } /* * For now, only return generic attributes. * Will open an RFE to add native attributes. */ static int get_attr(fstyp_udfs_t *h) { struct udf *udfs = &h->udh->udfs; struct vds *v; struct pri_vol_desc *pvd; uint32_t len; uint64_t off; uint8_t *buf; int8_t str[64]; int ret = 0; v = (udfs->flags & VALID_MVDS) ? &udfs->mvds : &udfs->rvds; /* allocate buffer */ len = udfs->lbsize; if (v->pvd_len > len) { len = v->pvd_len; } if ((buf = (uint8_t *)malloc(len)) == NULL) { return (FSTYP_ERR_NOMEM); } (void) nvlist_add_boolean_value(h->attr, "gen_clean", B_TRUE); /* Primary Volume Descriptor */ if (v->pvd_len != 0) { off = v->pvd_loc * udfs->lbsize; if (ud_read_dev(h->udh, off, buf, v->pvd_len) != 0) { ret = FSTYP_ERR_IO; goto out; } /* LINTED */ pvd = (struct pri_vol_desc *)(uint32_t *)buf; ud_convert2local(pvd->pvd_vol_id, str, 32); str[32] = '\0'; (void) nvlist_add_string(h->attr, "gen_volume_label", str); } ret = 0; out: free(buf); return (ret); } /* ARGSUSED */ int print_vds(fstyp_udfs_t *h, struct vds *v, FILE *fout, FILE *ferr) { struct udf *udfs = &h->udh->udfs; int32_t i; uint32_t len; uint64_t off; uint8_t *buf; int ret = 0; /* * All descriptors are 512 bytes * except lvd, usd and lvid * findout the largest and allocate space */ len = udfs->lbsize; if (v->lvd_len > len) { len = v->lvd_len; } if (v->usd_len > len) { len = v->usd_len; } if (udfs->lvid_len > len) { len = udfs->lvid_len; } if ((buf = (uint8_t *)malloc(len)) == NULL) { return (FSTYP_ERR_NOMEM); } /* * Anchor Volume Descriptor */ if (udfs->avdp_len != 0) { off = udfs->avdp_loc * udfs->lbsize; if (ud_read_dev(h->udh, off, buf, udfs->avdp_len) != 0) { ret = FSTYP_ERR_IO; goto out; } /* LINTED */ print_avd(fout, (struct anch_vol_desc_ptr *)buf); } /* * Primary Volume Descriptor */ if (v->pvd_len != 0) { off = v->pvd_loc * udfs->lbsize; if (ud_read_dev(h->udh, off, buf, v->pvd_len) != 0) { ret = FSTYP_ERR_IO; goto out; } /* LINTED */ print_pvd(fout, (struct pri_vol_desc *)buf); } /* * Implementation Use descriptor */ if (v->iud_len != 0) { off = v->iud_loc * udfs->lbsize; if (ud_read_dev(h->udh, off, buf, v->iud_len) != 0) { ret = FSTYP_ERR_IO; goto out; } /* LINTED */ print_iuvd(fout, (struct iuvd_desc *)buf); } /* * Paritions */ for (i = 0; i < h->udh->n_parts; i++) { if (v->part_len[i] != 0) { off = v->part_loc[i] * udfs->lbsize; if (ud_read_dev(h->udh, off, buf, v->part_len[i]) != 0) { ret = FSTYP_ERR_IO; goto out; } /* LINTED */ print_part(fout, (struct part_desc *)buf); } } /* * Logical Volume Descriptor */ if (v->lvd_len != 0) { off = v->lvd_loc * udfs->lbsize; if (ud_read_dev(h->udh, off, buf, v->lvd_len) != 0) { ret = FSTYP_ERR_IO; goto out; } /* LINTED */ print_lvd(fout, (struct log_vol_desc *)buf); } /* * Unallocated Space Descriptor */ if (v->usd_len != 0) { off = v->usd_loc * udfs->lbsize; if (ud_read_dev(h->udh, off, buf, v->usd_len) != 0) { ret = FSTYP_ERR_IO; goto out; } /* LINTED */ print_usd(fout, (struct unall_spc_desc *)buf); } /* * Logical Volume Integrity Descriptor */ if (udfs->lvid_len != 0) { off = udfs->lvid_loc * udfs->lbsize; if (ud_read_dev(h->udh, off, buf, udfs->lvid_len) != 0) { ret = FSTYP_ERR_IO; goto out; } /* LINTED */ print_lvid(fout, (struct log_vol_int_desc *)buf); } /* * File Set Descriptor */ if (udfs->fsd_len != 0) { off = udfs->fsd_loc * udfs->lbsize; if (ud_read_dev(h->udh, off, buf, udfs->fsd_len) != 0) { ret = FSTYP_ERR_IO; goto out; } /* LINTED */ print_fsd(fout, h->udh, (struct file_set_desc *)buf); } ret = 0; out: free(buf); return (ret); }