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