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