17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0e42dee6Sartem * Common Development and Distribution License (the "License").
6*0e42dee6Sartem * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*0e42dee6Sartem * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
26*0e42dee6Sartem /*
27*0e42dee6Sartem * libfstyp module for udfs
28*0e42dee6Sartem */
297c478bd9Sstevel@tonic-gate #include <fcntl.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <errno.h>
327c478bd9Sstevel@tonic-gate #include <unistd.h>
337c478bd9Sstevel@tonic-gate #include <locale.h>
347c478bd9Sstevel@tonic-gate #include <stdlib.h>
357c478bd9Sstevel@tonic-gate #include <strings.h>
367c478bd9Sstevel@tonic-gate #include <sys/param.h>
377c478bd9Sstevel@tonic-gate #include <sys/stat.h>
387c478bd9Sstevel@tonic-gate #include <sys/time.h>
397c478bd9Sstevel@tonic-gate #include <sys/types.h>
407c478bd9Sstevel@tonic-gate #include <sys/file.h>
41*0e42dee6Sartem #include <libnvpair.h>
42*0e42dee6Sartem #include <libfstyp_module.h>
437c478bd9Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
447c478bd9Sstevel@tonic-gate #include "ud_lib.h"
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate
47*0e42dee6Sartem typedef struct fstyp_udfs {
48*0e42dee6Sartem int fd;
49*0e42dee6Sartem ud_handle_t udh;
50*0e42dee6Sartem nvlist_t *attr;
51*0e42dee6Sartem } fstyp_udfs_t;
527c478bd9Sstevel@tonic-gate
53*0e42dee6Sartem static int is_udfs(fstyp_udfs_t *h);
54*0e42dee6Sartem static int print_vds(fstyp_udfs_t *h, struct vds *,
55*0e42dee6Sartem FILE *fout, FILE *ferr);
56*0e42dee6Sartem static int get_attr(fstyp_udfs_t *h);
57*0e42dee6Sartem
58*0e42dee6Sartem int fstyp_mod_init(int fd, off_t offset, fstyp_mod_handle_t *handle);
59*0e42dee6Sartem void fstyp_mod_fini(fstyp_mod_handle_t handle);
60*0e42dee6Sartem int fstyp_mod_ident(fstyp_mod_handle_t handle);
61*0e42dee6Sartem int fstyp_mod_get_attr(fstyp_mod_handle_t handle, nvlist_t **attrp);
62*0e42dee6Sartem int fstyp_mod_dump(fstyp_mod_handle_t handle, FILE *fout, FILE *ferr);
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate int
fstyp_mod_init(int fd,off_t offset,fstyp_mod_handle_t * handle)66*0e42dee6Sartem fstyp_mod_init(int fd, off_t offset, fstyp_mod_handle_t *handle)
677c478bd9Sstevel@tonic-gate {
68*0e42dee6Sartem fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
69*0e42dee6Sartem
70*0e42dee6Sartem if (offset != 0) {
71*0e42dee6Sartem return (FSTYP_ERR_OFFSET);
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate
74*0e42dee6Sartem if ((h = calloc(1, sizeof (fstyp_udfs_t))) == NULL) {
75*0e42dee6Sartem return (FSTYP_ERR_NOMEM);
767c478bd9Sstevel@tonic-gate }
77*0e42dee6Sartem h->fd = fd;
787c478bd9Sstevel@tonic-gate
79*0e42dee6Sartem if (ud_init(h->fd, &h->udh) != 0) {
80*0e42dee6Sartem free(h);
81*0e42dee6Sartem return (FSTYP_ERR_NOMEM);
827c478bd9Sstevel@tonic-gate }
837c478bd9Sstevel@tonic-gate
84*0e42dee6Sartem *handle = (fstyp_mod_handle_t)h;
85*0e42dee6Sartem return (0);
86*0e42dee6Sartem }
87*0e42dee6Sartem
88*0e42dee6Sartem void
fstyp_mod_fini(fstyp_mod_handle_t handle)89*0e42dee6Sartem fstyp_mod_fini(fstyp_mod_handle_t handle)
90*0e42dee6Sartem {
91*0e42dee6Sartem fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
92*0e42dee6Sartem
93*0e42dee6Sartem if (h->attr == NULL) {
94*0e42dee6Sartem nvlist_free(h->attr);
95*0e42dee6Sartem h->attr = NULL;
96*0e42dee6Sartem }
97*0e42dee6Sartem ud_fini(h->udh);
98*0e42dee6Sartem free(h);
99*0e42dee6Sartem }
100*0e42dee6Sartem
101*0e42dee6Sartem int
fstyp_mod_ident(fstyp_mod_handle_t handle)102*0e42dee6Sartem fstyp_mod_ident(fstyp_mod_handle_t handle)
103*0e42dee6Sartem {
104*0e42dee6Sartem fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
105*0e42dee6Sartem
106*0e42dee6Sartem return (is_udfs(h));
107*0e42dee6Sartem }
108*0e42dee6Sartem
109*0e42dee6Sartem int
fstyp_mod_get_attr(fstyp_mod_handle_t handle,nvlist_t ** attrp)110*0e42dee6Sartem fstyp_mod_get_attr(fstyp_mod_handle_t handle, nvlist_t **attrp)
111*0e42dee6Sartem {
112*0e42dee6Sartem fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
113*0e42dee6Sartem int error;
114*0e42dee6Sartem
115*0e42dee6Sartem if (h->attr == NULL) {
116*0e42dee6Sartem if (nvlist_alloc(&h->attr, NV_UNIQUE_NAME_TYPE, 0)) {
117*0e42dee6Sartem return (FSTYP_ERR_NOMEM);
118*0e42dee6Sartem }
119*0e42dee6Sartem if ((error = get_attr(h)) != 0) {
120*0e42dee6Sartem nvlist_free(h->attr);
121*0e42dee6Sartem h->attr = NULL;
122*0e42dee6Sartem return (error);
123*0e42dee6Sartem }
124*0e42dee6Sartem }
125*0e42dee6Sartem
126*0e42dee6Sartem *attrp = h->attr;
127*0e42dee6Sartem return (0);
128*0e42dee6Sartem }
129*0e42dee6Sartem
130*0e42dee6Sartem int
fstyp_mod_dump(fstyp_mod_handle_t handle,FILE * fout,FILE * ferr)131*0e42dee6Sartem fstyp_mod_dump(fstyp_mod_handle_t handle, FILE *fout, FILE *ferr)
132*0e42dee6Sartem {
133*0e42dee6Sartem fstyp_udfs_t *h = (fstyp_udfs_t *)handle;
134*0e42dee6Sartem struct udf *udfs = &h->udh->udfs;
135*0e42dee6Sartem int ret;
1367c478bd9Sstevel@tonic-gate
137*0e42dee6Sartem (void) fprintf(fout,
138*0e42dee6Sartem "Standard Identifier %5s\n", udfs->ecma_id);
139*0e42dee6Sartem
140*0e42dee6Sartem if (udfs->flags & VALID_MVDS) {
141*0e42dee6Sartem ret = print_vds(h, &udfs->mvds, fout, ferr);
142*0e42dee6Sartem } else {
143*0e42dee6Sartem ret = print_vds(h, &udfs->rvds, fout, ferr);
144*0e42dee6Sartem }
1457c478bd9Sstevel@tonic-gate
146*0e42dee6Sartem return (ret);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate /*
1517c478bd9Sstevel@tonic-gate * Assumption is that we will confirm to level-1
1527c478bd9Sstevel@tonic-gate */
1537c478bd9Sstevel@tonic-gate int
is_udfs(fstyp_udfs_t * h)154*0e42dee6Sartem is_udfs(fstyp_udfs_t *h)
1557c478bd9Sstevel@tonic-gate {
156*0e42dee6Sartem struct udf *udfs = &h->udh->udfs;
1577c478bd9Sstevel@tonic-gate int32_t ret;
1587c478bd9Sstevel@tonic-gate
159*0e42dee6Sartem if ((ret = ud_fill_udfs_info(h->udh)) != 0) {
1607c478bd9Sstevel@tonic-gate return (ret);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate
163*0e42dee6Sartem if ((udfs->flags & VALID_UDFS) == 0) {
164*0e42dee6Sartem return (FSTYP_ERR_NO_MATCH);
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
167*0e42dee6Sartem return (0);
168*0e42dee6Sartem }
169*0e42dee6Sartem
170*0e42dee6Sartem /*
171*0e42dee6Sartem * For now, only return generic attributes.
172*0e42dee6Sartem * Will open an RFE to add native attributes.
173*0e42dee6Sartem */
174*0e42dee6Sartem static int
get_attr(fstyp_udfs_t * h)175*0e42dee6Sartem get_attr(fstyp_udfs_t *h)
176*0e42dee6Sartem {
177*0e42dee6Sartem struct udf *udfs = &h->udh->udfs;
178*0e42dee6Sartem struct vds *v;
179*0e42dee6Sartem struct pri_vol_desc *pvd;
180*0e42dee6Sartem uint32_t len;
181*0e42dee6Sartem uint64_t off;
182*0e42dee6Sartem uint8_t *buf;
183*0e42dee6Sartem int8_t str[64];
184*0e42dee6Sartem int ret = 0;
185*0e42dee6Sartem
186*0e42dee6Sartem v = (udfs->flags & VALID_MVDS) ? &udfs->mvds : &udfs->rvds;
1877c478bd9Sstevel@tonic-gate
188*0e42dee6Sartem /* allocate buffer */
189*0e42dee6Sartem len = udfs->lbsize;
190*0e42dee6Sartem if (v->pvd_len > len) {
191*0e42dee6Sartem len = v->pvd_len;
192*0e42dee6Sartem }
193*0e42dee6Sartem if ((buf = (uint8_t *)malloc(len)) == NULL) {
194*0e42dee6Sartem return (FSTYP_ERR_NOMEM);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate
197*0e42dee6Sartem (void) nvlist_add_boolean_value(h->attr, "gen_clean", B_TRUE);
1987c478bd9Sstevel@tonic-gate
199*0e42dee6Sartem /* Primary Volume Descriptor */
200*0e42dee6Sartem if (v->pvd_len != 0) {
201*0e42dee6Sartem off = v->pvd_loc * udfs->lbsize;
202*0e42dee6Sartem if (ud_read_dev(h->udh, off, buf, v->pvd_len) != 0) {
203*0e42dee6Sartem ret = FSTYP_ERR_IO;
204*0e42dee6Sartem goto out;
205*0e42dee6Sartem }
206*0e42dee6Sartem /* LINTED */
207*0e42dee6Sartem pvd = (struct pri_vol_desc *)(uint32_t *)buf;
208*0e42dee6Sartem
209*0e42dee6Sartem ud_convert2local(pvd->pvd_vol_id, str, 32);
210*0e42dee6Sartem str[32] = '\0';
211*0e42dee6Sartem (void) nvlist_add_string(h->attr, "gen_volume_label", str);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate
214*0e42dee6Sartem ret = 0;
215*0e42dee6Sartem
216*0e42dee6Sartem out:
217*0e42dee6Sartem free(buf);
2187c478bd9Sstevel@tonic-gate return (ret);
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate
221*0e42dee6Sartem /* ARGSUSED */
2227c478bd9Sstevel@tonic-gate int
print_vds(fstyp_udfs_t * h,struct vds * v,FILE * fout,FILE * ferr)223*0e42dee6Sartem print_vds(fstyp_udfs_t *h, struct vds *v, FILE *fout, FILE *ferr)
2247c478bd9Sstevel@tonic-gate {
225*0e42dee6Sartem struct udf *udfs = &h->udh->udfs;
2267c478bd9Sstevel@tonic-gate int32_t i;
2277c478bd9Sstevel@tonic-gate uint32_t len;
2287c478bd9Sstevel@tonic-gate uint64_t off;
2297c478bd9Sstevel@tonic-gate uint8_t *buf;
230*0e42dee6Sartem int ret = 0;
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate /*
2337c478bd9Sstevel@tonic-gate * All descriptors are 512 bytes
2347c478bd9Sstevel@tonic-gate * except lvd, usd and lvid
2357c478bd9Sstevel@tonic-gate * findout the largest and allocate space
2367c478bd9Sstevel@tonic-gate */
237*0e42dee6Sartem len = udfs->lbsize;
2387c478bd9Sstevel@tonic-gate if (v->lvd_len > len) {
2397c478bd9Sstevel@tonic-gate len = v->lvd_len;
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate if (v->usd_len > len) {
2427c478bd9Sstevel@tonic-gate len = v->usd_len;
2437c478bd9Sstevel@tonic-gate }
244*0e42dee6Sartem if (udfs->lvid_len > len) {
245*0e42dee6Sartem len = udfs->lvid_len;
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate if ((buf = (uint8_t *)malloc(len)) == NULL) {
249*0e42dee6Sartem return (FSTYP_ERR_NOMEM);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /*
2537c478bd9Sstevel@tonic-gate * Anchor Volume Descriptor
2547c478bd9Sstevel@tonic-gate */
255*0e42dee6Sartem if (udfs->avdp_len != 0) {
256*0e42dee6Sartem off = udfs->avdp_loc * udfs->lbsize;
257*0e42dee6Sartem if (ud_read_dev(h->udh, off, buf, udfs->avdp_len) != 0) {
258*0e42dee6Sartem ret = FSTYP_ERR_IO;
259*0e42dee6Sartem goto out;
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate /* LINTED */
263*0e42dee6Sartem print_avd(fout, (struct anch_vol_desc_ptr *)buf);
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate * Primary Volume Descriptor
2687c478bd9Sstevel@tonic-gate */
2697c478bd9Sstevel@tonic-gate if (v->pvd_len != 0) {
270*0e42dee6Sartem off = v->pvd_loc * udfs->lbsize;
271*0e42dee6Sartem if (ud_read_dev(h->udh, off, buf, v->pvd_len) != 0) {
272*0e42dee6Sartem ret = FSTYP_ERR_IO;
273*0e42dee6Sartem goto out;
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate /* LINTED */
277*0e42dee6Sartem print_pvd(fout, (struct pri_vol_desc *)buf);
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate /*
2817c478bd9Sstevel@tonic-gate * Implementation Use descriptor
2827c478bd9Sstevel@tonic-gate */
2837c478bd9Sstevel@tonic-gate if (v->iud_len != 0) {
284*0e42dee6Sartem off = v->iud_loc * udfs->lbsize;
285*0e42dee6Sartem if (ud_read_dev(h->udh, off, buf, v->iud_len) != 0) {
286*0e42dee6Sartem ret = FSTYP_ERR_IO;
287*0e42dee6Sartem goto out;
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate /* LINTED */
291*0e42dee6Sartem print_iuvd(fout, (struct iuvd_desc *)buf);
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate /*
2957c478bd9Sstevel@tonic-gate * Paritions
2967c478bd9Sstevel@tonic-gate */
297*0e42dee6Sartem for (i = 0; i < h->udh->n_parts; i++) {
2987c478bd9Sstevel@tonic-gate if (v->part_len[i] != 0) {
299*0e42dee6Sartem off = v->part_loc[i] * udfs->lbsize;
300*0e42dee6Sartem if (ud_read_dev(h->udh, off, buf,
301*0e42dee6Sartem v->part_len[i]) != 0) {
302*0e42dee6Sartem ret = FSTYP_ERR_IO;
303*0e42dee6Sartem goto out;
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate /* LINTED */
307*0e42dee6Sartem print_part(fout, (struct part_desc *)buf);
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate /*
3127c478bd9Sstevel@tonic-gate * Logical Volume Descriptor
3137c478bd9Sstevel@tonic-gate */
3147c478bd9Sstevel@tonic-gate if (v->lvd_len != 0) {
315*0e42dee6Sartem off = v->lvd_loc * udfs->lbsize;
316*0e42dee6Sartem if (ud_read_dev(h->udh, off, buf, v->lvd_len) != 0) {
317*0e42dee6Sartem ret = FSTYP_ERR_IO;
318*0e42dee6Sartem goto out;
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate /* LINTED */
322*0e42dee6Sartem print_lvd(fout, (struct log_vol_desc *)buf);
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate * Unallocated Space Descriptor
3277c478bd9Sstevel@tonic-gate */
3287c478bd9Sstevel@tonic-gate if (v->usd_len != 0) {
329*0e42dee6Sartem off = v->usd_loc * udfs->lbsize;
330*0e42dee6Sartem if (ud_read_dev(h->udh, off, buf, v->usd_len) != 0) {
331*0e42dee6Sartem ret = FSTYP_ERR_IO;
332*0e42dee6Sartem goto out;
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate /* LINTED */
336*0e42dee6Sartem print_usd(fout, (struct unall_spc_desc *)buf);
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /*
3407c478bd9Sstevel@tonic-gate * Logical Volume Integrity Descriptor
3417c478bd9Sstevel@tonic-gate */
342*0e42dee6Sartem if (udfs->lvid_len != 0) {
343*0e42dee6Sartem off = udfs->lvid_loc * udfs->lbsize;
344*0e42dee6Sartem if (ud_read_dev(h->udh, off, buf, udfs->lvid_len) != 0) {
345*0e42dee6Sartem ret = FSTYP_ERR_IO;
346*0e42dee6Sartem goto out;
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate /* LINTED */
350*0e42dee6Sartem print_lvid(fout, (struct log_vol_int_desc *)buf);
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate /*
3547c478bd9Sstevel@tonic-gate * File Set Descriptor
3557c478bd9Sstevel@tonic-gate */
356*0e42dee6Sartem if (udfs->fsd_len != 0) {
357*0e42dee6Sartem off = udfs->fsd_loc * udfs->lbsize;
358*0e42dee6Sartem if (ud_read_dev(h->udh, off, buf, udfs->fsd_len) != 0) {
359*0e42dee6Sartem ret = FSTYP_ERR_IO;
360*0e42dee6Sartem goto out;
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate /* LINTED */
364*0e42dee6Sartem print_fsd(fout, h->udh, (struct file_set_desc *)buf);
3657c478bd9Sstevel@tonic-gate }
366*0e42dee6Sartem ret = 0;
3677c478bd9Sstevel@tonic-gate
368*0e42dee6Sartem out:
369*0e42dee6Sartem free(buf);
370*0e42dee6Sartem return (ret);
3717c478bd9Sstevel@tonic-gate }
372