1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 /* udf_vnops.c */ 32 /* Take care of the vnode side of things */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/namei.h> 37 #include <sys/kernel.h> 38 #include <sys/malloc.h> 39 #include <sys/stat.h> 40 #include <sys/bio.h> 41 #include <sys/conf.h> 42 #include <sys/buf.h> 43 #include <sys/iconv.h> 44 #include <sys/mount.h> 45 #include <sys/vnode.h> 46 #include <sys/dirent.h> 47 #include <sys/queue.h> 48 #include <sys/unistd.h> 49 #include <sys/endian.h> 50 51 #include <vm/uma.h> 52 53 #include <fs/udf/ecma167-udf.h> 54 #include <fs/udf/osta.h> 55 #include <fs/udf/udf.h> 56 #include <fs/udf/udf_mount.h> 57 58 extern struct iconv_functions *udf_iconv; 59 60 static vop_access_t udf_access; 61 static vop_getattr_t udf_getattr; 62 static vop_open_t udf_open; 63 static vop_ioctl_t udf_ioctl; 64 static vop_pathconf_t udf_pathconf; 65 static vop_print_t udf_print; 66 static vop_read_t udf_read; 67 static vop_readdir_t udf_readdir; 68 static vop_readlink_t udf_readlink; 69 static vop_setattr_t udf_setattr; 70 static vop_strategy_t udf_strategy; 71 static vop_bmap_t udf_bmap; 72 static vop_cachedlookup_t udf_lookup; 73 static vop_reclaim_t udf_reclaim; 74 static vop_vptofh_t udf_vptofh; 75 static int udf_readatoffset(struct udf_node *node, int *size, off_t offset, 76 struct buf **bp, uint8_t **data); 77 static int udf_bmap_internal(struct udf_node *node, off_t offset, 78 daddr_t *sector, uint32_t *max_size); 79 80 static struct vop_vector udf_vnodeops = { 81 .vop_default = &default_vnodeops, 82 83 .vop_access = udf_access, 84 .vop_bmap = udf_bmap, 85 .vop_cachedlookup = udf_lookup, 86 .vop_getattr = udf_getattr, 87 .vop_ioctl = udf_ioctl, 88 .vop_lookup = vfs_cache_lookup, 89 .vop_open = udf_open, 90 .vop_pathconf = udf_pathconf, 91 .vop_print = udf_print, 92 .vop_read = udf_read, 93 .vop_readdir = udf_readdir, 94 .vop_readlink = udf_readlink, 95 .vop_reclaim = udf_reclaim, 96 .vop_setattr = udf_setattr, 97 .vop_strategy = udf_strategy, 98 .vop_vptofh = udf_vptofh, 99 }; 100 101 struct vop_vector udf_fifoops = { 102 .vop_default = &fifo_specops, 103 .vop_access = udf_access, 104 .vop_getattr = udf_getattr, 105 .vop_print = udf_print, 106 .vop_reclaim = udf_reclaim, 107 .vop_setattr = udf_setattr, 108 .vop_vptofh = udf_vptofh, 109 }; 110 111 static MALLOC_DEFINE(M_UDFFID, "udf_fid", "UDF FileId structure"); 112 static MALLOC_DEFINE(M_UDFDS, "udf_ds", "UDF Dirstream structure"); 113 114 #define UDF_INVALID_BMAP -1 115 116 int 117 udf_allocv(struct mount *mp, struct vnode **vpp, struct thread *td) 118 { 119 int error; 120 struct vnode *vp; 121 122 error = getnewvnode("udf", mp, &udf_vnodeops, &vp); 123 if (error) { 124 printf("udf_allocv: failed to allocate new vnode\n"); 125 return (error); 126 } 127 128 *vpp = vp; 129 return (0); 130 } 131 132 /* Convert file entry permission (5 bits per owner/group/user) to a mode_t */ 133 static mode_t 134 udf_permtomode(struct udf_node *node) 135 { 136 uint32_t perm; 137 uint16_t flags; 138 mode_t mode; 139 140 perm = le32toh(node->fentry->perm); 141 flags = le16toh(node->fentry->icbtag.flags); 142 143 mode = perm & UDF_FENTRY_PERM_USER_MASK; 144 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2); 145 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 146 mode |= ((flags & UDF_ICB_TAG_FLAGS_STICKY) << 4); 147 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETGID) << 6); 148 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETUID) << 8); 149 150 return (mode); 151 } 152 153 static int 154 udf_access(struct vop_access_args *a) 155 { 156 struct vnode *vp; 157 struct udf_node *node; 158 accmode_t accmode; 159 mode_t mode; 160 161 vp = a->a_vp; 162 node = VTON(vp); 163 accmode = a->a_accmode; 164 165 if (accmode & VWRITE) { 166 switch (vp->v_type) { 167 case VDIR: 168 case VLNK: 169 case VREG: 170 return (EROFS); 171 /* NOT REACHED */ 172 default: 173 break; 174 } 175 } 176 177 mode = udf_permtomode(node); 178 179 return (vaccess(vp->v_type, mode, node->fentry->uid, node->fentry->gid, 180 accmode, a->a_cred, NULL)); 181 } 182 183 static int 184 udf_open(struct vop_open_args *ap) { 185 struct udf_node *np = VTON(ap->a_vp); 186 off_t fsize; 187 188 fsize = le64toh(np->fentry->inf_len); 189 vnode_create_vobject(ap->a_vp, fsize, ap->a_td); 190 return 0; 191 } 192 193 static const int mon_lens[2][12] = { 194 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, 195 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335} 196 }; 197 198 static int 199 udf_isaleapyear(int year) 200 { 201 int i; 202 203 i = (year % 4) ? 0 : 1; 204 i &= (year % 100) ? 1 : 0; 205 i |= (year % 400) ? 0 : 1; 206 207 return i; 208 } 209 210 /* 211 * Timezone calculation compliments of Julian Elischer <julian@elischer.org>. 212 */ 213 static void 214 udf_timetotimespec(struct timestamp *time, struct timespec *t) 215 { 216 int i, lpyear, daysinyear, year, startyear; 217 union { 218 uint16_t u_tz_offset; 219 int16_t s_tz_offset; 220 } tz; 221 222 /* 223 * DirectCD seems to like using bogus year values. 224 * Don't trust time->month as it will be used for an array index. 225 */ 226 year = le16toh(time->year); 227 if (year < 1970 || time->month < 1 || time->month > 12) { 228 t->tv_sec = 0; 229 t->tv_nsec = 0; 230 return; 231 } 232 233 /* Calculate the time and day */ 234 t->tv_sec = time->second; 235 t->tv_sec += time->minute * 60; 236 t->tv_sec += time->hour * 3600; 237 t->tv_sec += (time->day - 1) * 3600 * 24; 238 239 /* Calculate the month */ 240 lpyear = udf_isaleapyear(year); 241 t->tv_sec += mon_lens[lpyear][time->month - 1] * 3600 * 24; 242 243 /* Speed up the calculation */ 244 startyear = 1970; 245 if (year > 2009) { 246 t->tv_sec += 1262304000; 247 startyear += 40; 248 } else if (year > 1999) { 249 t->tv_sec += 946684800; 250 startyear += 30; 251 } else if (year > 1989) { 252 t->tv_sec += 631152000; 253 startyear += 20; 254 } else if (year > 1979) { 255 t->tv_sec += 315532800; 256 startyear += 10; 257 } 258 259 daysinyear = (year - startyear) * 365; 260 for (i = startyear; i < year; i++) 261 daysinyear += udf_isaleapyear(i); 262 t->tv_sec += daysinyear * 3600 * 24; 263 264 /* Calculate microseconds */ 265 t->tv_nsec = time->centisec * 10000 + time->hund_usec * 100 + 266 time->usec; 267 268 /* 269 * Calculate the time zone. The timezone is 12 bit signed 2's 270 * complement, so we gotta do some extra magic to handle it right. 271 */ 272 tz.u_tz_offset = le16toh(time->type_tz); 273 tz.u_tz_offset &= 0x0fff; 274 if (tz.u_tz_offset & 0x0800) 275 tz.u_tz_offset |= 0xf000; /* extend the sign to 16 bits */ 276 if ((le16toh(time->type_tz) & 0x1000) && (tz.s_tz_offset != -2047)) 277 t->tv_sec -= tz.s_tz_offset * 60; 278 279 return; 280 } 281 282 static int 283 udf_getattr(struct vop_getattr_args *a) 284 { 285 struct vnode *vp; 286 struct udf_node *node; 287 struct vattr *vap; 288 struct file_entry *fentry; 289 struct timespec ts; 290 291 ts.tv_sec = 0; 292 293 vp = a->a_vp; 294 vap = a->a_vap; 295 node = VTON(vp); 296 fentry = node->fentry; 297 298 vap->va_fsid = dev2udev(node->udfmp->im_dev); 299 vap->va_fileid = node->hash_id; 300 vap->va_mode = udf_permtomode(node); 301 vap->va_nlink = le16toh(fentry->link_cnt); 302 /* 303 * XXX The spec says that -1 is valid for uid/gid and indicates an 304 * invalid uid/gid. How should this be represented? 305 */ 306 vap->va_uid = (le32toh(fentry->uid) == -1) ? 0 : le32toh(fentry->uid); 307 vap->va_gid = (le32toh(fentry->gid) == -1) ? 0 : le32toh(fentry->gid); 308 udf_timetotimespec(&fentry->atime, &vap->va_atime); 309 udf_timetotimespec(&fentry->mtime, &vap->va_mtime); 310 vap->va_ctime = vap->va_mtime; /* XXX Stored as an Extended Attribute */ 311 vap->va_rdev = NODEV; 312 if (vp->v_type & VDIR) { 313 /* 314 * Directories that are recorded within their ICB will show 315 * as having 0 blocks recorded. Since tradition dictates 316 * that directories consume at least one logical block, 317 * make it appear so. 318 */ 319 if (fentry->logblks_rec != 0) { 320 vap->va_size = 321 le64toh(fentry->logblks_rec) * node->udfmp->bsize; 322 } else { 323 vap->va_size = node->udfmp->bsize; 324 } 325 } else { 326 vap->va_size = le64toh(fentry->inf_len); 327 } 328 vap->va_flags = 0; 329 vap->va_gen = 1; 330 vap->va_blocksize = node->udfmp->bsize; 331 vap->va_bytes = le64toh(fentry->inf_len); 332 vap->va_type = vp->v_type; 333 vap->va_filerev = 0; /* XXX */ 334 return (0); 335 } 336 337 static int 338 udf_setattr(struct vop_setattr_args *a) 339 { 340 struct vnode *vp; 341 struct vattr *vap; 342 343 vp = a->a_vp; 344 vap = a->a_vap; 345 if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || 346 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 347 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 348 return (EROFS); 349 if (vap->va_size != (u_quad_t)VNOVAL) { 350 switch (vp->v_type) { 351 case VDIR: 352 return (EISDIR); 353 case VLNK: 354 case VREG: 355 return (EROFS); 356 case VCHR: 357 case VBLK: 358 case VSOCK: 359 case VFIFO: 360 case VNON: 361 case VBAD: 362 case VMARKER: 363 return (0); 364 } 365 } 366 return (0); 367 } 368 369 /* 370 * File specific ioctls. 371 */ 372 static int 373 udf_ioctl(struct vop_ioctl_args *a) 374 { 375 printf("%s called\n", __func__); 376 return (ENOTTY); 377 } 378 379 /* 380 * I'm not sure that this has much value in a read-only filesystem, but 381 * cd9660 has it too. 382 */ 383 static int 384 udf_pathconf(struct vop_pathconf_args *a) 385 { 386 387 switch (a->a_name) { 388 case _PC_FILESIZEBITS: 389 *a->a_retval = 64; 390 return (0); 391 case _PC_LINK_MAX: 392 *a->a_retval = 65535; 393 return (0); 394 case _PC_NAME_MAX: 395 *a->a_retval = NAME_MAX; 396 return (0); 397 case _PC_SYMLINK_MAX: 398 *a->a_retval = MAXPATHLEN; 399 return (0); 400 case _PC_NO_TRUNC: 401 *a->a_retval = 1; 402 return (0); 403 default: 404 return (vop_stdpathconf(a)); 405 } 406 } 407 408 static int 409 udf_print(struct vop_print_args *ap) 410 { 411 struct vnode *vp = ap->a_vp; 412 struct udf_node *node = VTON(vp); 413 414 printf(" ino %lu, on dev %s", (u_long)node->hash_id, 415 devtoname(node->udfmp->im_dev)); 416 if (vp->v_type == VFIFO) 417 fifo_printinfo(vp); 418 printf("\n"); 419 return (0); 420 } 421 422 #define lblkno(udfmp, loc) ((loc) >> (udfmp)->bshift) 423 #define blkoff(udfmp, loc) ((loc) & (udfmp)->bmask) 424 #define lblktosize(udfmp, blk) ((blk) << (udfmp)->bshift) 425 426 static inline int 427 is_data_in_fentry(const struct udf_node *node) 428 { 429 const struct file_entry *fentry = node->fentry; 430 431 return ((le16toh(fentry->icbtag.flags) & 0x7) == 3); 432 } 433 434 static int 435 udf_read(struct vop_read_args *ap) 436 { 437 struct vnode *vp = ap->a_vp; 438 struct uio *uio = ap->a_uio; 439 struct udf_node *node = VTON(vp); 440 struct udf_mnt *udfmp; 441 struct file_entry *fentry; 442 struct buf *bp; 443 uint8_t *data; 444 daddr_t lbn, rablock; 445 off_t diff, fsize; 446 ssize_t n; 447 int error = 0; 448 long size, on; 449 450 if (uio->uio_resid == 0) 451 return (0); 452 if (uio->uio_offset < 0) 453 return (EINVAL); 454 455 if (is_data_in_fentry(node)) { 456 fentry = node->fentry; 457 data = &fentry->data[le32toh(fentry->l_ea)]; 458 fsize = le32toh(fentry->l_ad); 459 460 n = uio->uio_resid; 461 diff = fsize - uio->uio_offset; 462 if (diff <= 0) 463 return (0); 464 if (diff < n) 465 n = diff; 466 error = uiomove(data + uio->uio_offset, (int)n, uio); 467 return (error); 468 } 469 470 fsize = le64toh(node->fentry->inf_len); 471 udfmp = node->udfmp; 472 do { 473 lbn = lblkno(udfmp, uio->uio_offset); 474 on = blkoff(udfmp, uio->uio_offset); 475 n = min((u_int)(udfmp->bsize - on), 476 uio->uio_resid); 477 diff = fsize - uio->uio_offset; 478 if (diff <= 0) 479 return (0); 480 if (diff < n) 481 n = diff; 482 size = udfmp->bsize; 483 rablock = lbn + 1; 484 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 485 if (lblktosize(udfmp, rablock) < fsize) { 486 error = cluster_read(vp, fsize, lbn, size, 487 NOCRED, uio->uio_resid, 488 (ap->a_ioflag >> 16), 0, &bp); 489 } else { 490 error = bread(vp, lbn, size, NOCRED, &bp); 491 } 492 } else { 493 error = bread(vp, lbn, size, NOCRED, &bp); 494 } 495 if (error != 0) { 496 brelse(bp); 497 return (error); 498 } 499 n = min(n, size - bp->b_resid); 500 501 error = uiomove(bp->b_data + on, (int)n, uio); 502 brelse(bp); 503 } while (error == 0 && uio->uio_resid > 0 && n != 0); 504 return (error); 505 } 506 507 /* 508 * Call the OSTA routines to translate the name from a CS0 dstring to a 509 * 16-bit Unicode String. Hooks need to be placed in here to translate from 510 * Unicode to the encoding that the kernel/user expects. Return the length 511 * of the translated string. 512 */ 513 static int 514 udf_transname(char *cs0string, char *destname, int len, struct udf_mnt *udfmp) 515 { 516 unicode_t *transname; 517 char *unibuf, *unip; 518 int i, destlen; 519 ssize_t unilen = 0; 520 size_t destleft = MAXNAMLEN; 521 522 /* Convert 16-bit Unicode to destname */ 523 if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) { 524 /* allocate a buffer big enough to hold an 8->16 bit expansion */ 525 unibuf = uma_zalloc(udf_zone_trans, M_WAITOK); 526 unip = unibuf; 527 if ((unilen = (ssize_t)udf_UncompressUnicodeByte(len, cs0string, unibuf)) == -1) { 528 printf("udf: Unicode translation failed\n"); 529 uma_zfree(udf_zone_trans, unibuf); 530 return 0; 531 } 532 533 while (unilen > 0 && destleft > 0) { 534 udf_iconv->conv(udfmp->im_d2l, __DECONST(const char **, 535 &unibuf), (size_t *)&unilen, (char **)&destname, 536 &destleft); 537 /* Unconverted character found */ 538 if (unilen > 0 && destleft > 0) { 539 *destname++ = '?'; 540 destleft--; 541 unibuf += 2; 542 unilen -= 2; 543 } 544 } 545 uma_zfree(udf_zone_trans, unip); 546 *destname = '\0'; 547 destlen = MAXNAMLEN - (int)destleft; 548 } else { 549 /* allocate a buffer big enough to hold an 8->16 bit expansion */ 550 transname = uma_zalloc(udf_zone_trans, M_WAITOK); 551 552 if ((unilen = (ssize_t)udf_UncompressUnicode(len, cs0string, transname)) == -1) { 553 printf("udf: Unicode translation failed\n"); 554 uma_zfree(udf_zone_trans, transname); 555 return 0; 556 } 557 558 for (i = 0; i < unilen ; i++) { 559 if (transname[i] & 0xff00) { 560 destname[i] = '.'; /* Fudge the 16bit chars */ 561 } else { 562 destname[i] = transname[i] & 0xff; 563 } 564 } 565 uma_zfree(udf_zone_trans, transname); 566 destname[unilen] = 0; 567 destlen = (int)unilen; 568 } 569 570 return (destlen); 571 } 572 573 /* 574 * Compare a CS0 dstring with a name passed in from the VFS layer. Return 575 * 0 on a successful match, nonzero otherwise. Unicode work may need to be done 576 * here also. 577 */ 578 static int 579 udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct udf_mnt *udfmp) 580 { 581 char *transname; 582 int error = 0; 583 584 /* This is overkill, but not worth creating a new zone */ 585 transname = uma_zalloc(udf_zone_trans, M_WAITOK); 586 587 cs0len = udf_transname(cs0string, transname, cs0len, udfmp); 588 589 /* Easy check. If they aren't the same length, they aren't equal */ 590 if ((cs0len == 0) || (cs0len != cmplen)) 591 error = -1; 592 else 593 error = bcmp(transname, cmpname, cmplen); 594 595 uma_zfree(udf_zone_trans, transname); 596 return (error); 597 } 598 599 struct udf_uiodir { 600 struct dirent *dirent; 601 u_long *cookies; 602 int ncookies; 603 int acookies; 604 int eofflag; 605 }; 606 607 static int 608 udf_uiodir(struct udf_uiodir *uiodir, int de_size, struct uio *uio, long cookie) 609 { 610 if (uiodir->cookies != NULL) { 611 if (++uiodir->acookies > uiodir->ncookies) { 612 uiodir->eofflag = 0; 613 return (-1); 614 } 615 *uiodir->cookies++ = cookie; 616 } 617 618 if (uio->uio_resid < de_size) { 619 uiodir->eofflag = 0; 620 return (-1); 621 } 622 623 return (uiomove(uiodir->dirent, de_size, uio)); 624 } 625 626 static struct udf_dirstream * 627 udf_opendir(struct udf_node *node, int offset, int fsize, struct udf_mnt *udfmp) 628 { 629 struct udf_dirstream *ds; 630 631 ds = uma_zalloc(udf_zone_ds, M_WAITOK | M_ZERO); 632 633 ds->node = node; 634 ds->offset = offset; 635 ds->udfmp = udfmp; 636 ds->fsize = fsize; 637 638 return (ds); 639 } 640 641 static struct fileid_desc * 642 udf_getfid(struct udf_dirstream *ds) 643 { 644 struct fileid_desc *fid; 645 int error, frag_size = 0, total_fid_size; 646 647 /* End of directory? */ 648 if (ds->offset + ds->off >= ds->fsize) { 649 ds->error = 0; 650 return (NULL); 651 } 652 653 /* Grab the first extent of the directory */ 654 if (ds->off == 0) { 655 ds->size = 0; 656 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 657 &ds->bp, &ds->data); 658 if (error) { 659 ds->error = error; 660 if (ds->bp != NULL) 661 brelse(ds->bp); 662 return (NULL); 663 } 664 } 665 666 /* 667 * Clean up from a previous fragmented FID. 668 * XXX Is this the right place for this? 669 */ 670 if (ds->fid_fragment && ds->buf != NULL) { 671 ds->fid_fragment = 0; 672 free(ds->buf, M_UDFFID); 673 } 674 675 fid = (struct fileid_desc*)&ds->data[ds->off]; 676 677 /* 678 * Check to see if the fid is fragmented. The first test 679 * ensures that we don't wander off the end of the buffer 680 * looking for the l_iu and l_fi fields. 681 */ 682 if (ds->off + UDF_FID_SIZE > ds->size || 683 ds->off + le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE > ds->size){ 684 685 /* Copy what we have of the fid into a buffer */ 686 frag_size = ds->size - ds->off; 687 if (frag_size >= ds->udfmp->bsize) { 688 printf("udf: invalid FID fragment\n"); 689 ds->error = EINVAL; 690 return (NULL); 691 } 692 693 /* 694 * File ID descriptors can only be at most one 695 * logical sector in size. 696 */ 697 ds->buf = malloc(ds->udfmp->bsize, M_UDFFID, 698 M_WAITOK | M_ZERO); 699 bcopy(fid, ds->buf, frag_size); 700 701 /* Reduce all of the casting magic */ 702 fid = (struct fileid_desc*)ds->buf; 703 704 if (ds->bp != NULL) 705 brelse(ds->bp); 706 707 /* Fetch the next allocation */ 708 ds->offset += ds->size; 709 ds->size = 0; 710 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 711 &ds->bp, &ds->data); 712 if (error) { 713 ds->error = error; 714 return (NULL); 715 } 716 717 /* 718 * If the fragment was so small that we didn't get 719 * the l_iu and l_fi fields, copy those in. 720 */ 721 if (frag_size < UDF_FID_SIZE) 722 bcopy(ds->data, &ds->buf[frag_size], 723 UDF_FID_SIZE - frag_size); 724 725 /* 726 * Now that we have enough of the fid to work with, 727 * copy in the rest of the fid from the new 728 * allocation. 729 */ 730 total_fid_size = UDF_FID_SIZE + le16toh(fid->l_iu) + fid->l_fi; 731 if (total_fid_size > ds->udfmp->bsize) { 732 printf("udf: invalid FID\n"); 733 ds->error = EIO; 734 return (NULL); 735 } 736 bcopy(ds->data, &ds->buf[frag_size], 737 total_fid_size - frag_size); 738 739 ds->fid_fragment = 1; 740 } else { 741 total_fid_size = le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE; 742 } 743 744 /* 745 * Update the offset. Align on a 4 byte boundary because the 746 * UDF spec says so. 747 */ 748 ds->this_off = ds->offset + ds->off; 749 if (!ds->fid_fragment) { 750 ds->off += (total_fid_size + 3) & ~0x03; 751 } else { 752 ds->off = (total_fid_size - frag_size + 3) & ~0x03; 753 } 754 755 return (fid); 756 } 757 758 static void 759 udf_closedir(struct udf_dirstream *ds) 760 { 761 762 if (ds->bp != NULL) 763 brelse(ds->bp); 764 765 if (ds->fid_fragment && ds->buf != NULL) 766 free(ds->buf, M_UDFFID); 767 768 uma_zfree(udf_zone_ds, ds); 769 } 770 771 static int 772 udf_readdir(struct vop_readdir_args *a) 773 { 774 struct vnode *vp; 775 struct uio *uio; 776 struct dirent dir; 777 struct udf_node *node; 778 struct udf_mnt *udfmp; 779 struct fileid_desc *fid; 780 struct udf_uiodir uiodir; 781 struct udf_dirstream *ds; 782 u_long *cookies = NULL; 783 int ncookies; 784 int error = 0; 785 786 vp = a->a_vp; 787 uio = a->a_uio; 788 node = VTON(vp); 789 udfmp = node->udfmp; 790 uiodir.eofflag = 1; 791 792 if (a->a_ncookies != NULL) { 793 /* 794 * Guess how many entries are needed. If we run out, this 795 * function will be called again and thing will pick up were 796 * it left off. 797 */ 798 ncookies = uio->uio_resid / 8; 799 cookies = malloc(sizeof(u_long) * ncookies, 800 M_TEMP, M_WAITOK); 801 if (cookies == NULL) 802 return (ENOMEM); 803 uiodir.ncookies = ncookies; 804 uiodir.cookies = cookies; 805 uiodir.acookies = 0; 806 } else { 807 uiodir.cookies = NULL; 808 } 809 810 /* 811 * Iterate through the file id descriptors. Give the parent dir 812 * entry special attention. 813 */ 814 ds = udf_opendir(node, uio->uio_offset, le64toh(node->fentry->inf_len), 815 node->udfmp); 816 817 while ((fid = udf_getfid(ds)) != NULL) { 818 819 /* XXX Should we return an error on a bad fid? */ 820 if (udf_checktag(&fid->tag, TAGID_FID)) { 821 printf("Invalid FID tag\n"); 822 hexdump(fid, UDF_FID_SIZE, NULL, 0); 823 error = EIO; 824 break; 825 } 826 827 /* Is this a deleted file? */ 828 if (fid->file_char & UDF_FILE_CHAR_DEL) 829 continue; 830 831 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 832 /* Do up the '.' and '..' entries. Dummy values are 833 * used for the cookies since the offset here is 834 * usually zero, and NFS doesn't like that value 835 */ 836 dir.d_fileno = node->hash_id; 837 dir.d_type = DT_DIR; 838 dir.d_name[0] = '.'; 839 dir.d_name[1] = '\0'; 840 dir.d_namlen = 1; 841 dir.d_reclen = GENERIC_DIRSIZ(&dir); 842 uiodir.dirent = &dir; 843 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1); 844 if (error) 845 break; 846 847 dir.d_fileno = udf_getid(&fid->icb); 848 dir.d_type = DT_DIR; 849 dir.d_name[0] = '.'; 850 dir.d_name[1] = '.'; 851 dir.d_name[2] = '\0'; 852 dir.d_namlen = 2; 853 dir.d_reclen = GENERIC_DIRSIZ(&dir); 854 uiodir.dirent = &dir; 855 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2); 856 } else { 857 dir.d_namlen = udf_transname(&fid->data[fid->l_iu], 858 &dir.d_name[0], fid->l_fi, udfmp); 859 dir.d_fileno = udf_getid(&fid->icb); 860 dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ? 861 DT_DIR : DT_UNKNOWN; 862 dir.d_reclen = GENERIC_DIRSIZ(&dir); 863 uiodir.dirent = &dir; 864 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 865 ds->this_off); 866 } 867 if (error) 868 break; 869 uio->uio_offset = ds->offset + ds->off; 870 } 871 872 /* tell the calling layer whether we need to be called again */ 873 *a->a_eofflag = uiodir.eofflag; 874 875 if (error < 0) 876 error = 0; 877 if (!error) 878 error = ds->error; 879 880 udf_closedir(ds); 881 882 if (a->a_ncookies != NULL) { 883 if (error) 884 free(cookies, M_TEMP); 885 else { 886 *a->a_ncookies = uiodir.acookies; 887 *a->a_cookies = cookies; 888 } 889 } 890 891 return (error); 892 } 893 894 static int 895 udf_readlink(struct vop_readlink_args *ap) 896 { 897 struct path_component *pc, *end; 898 struct vnode *vp; 899 struct uio uio; 900 struct iovec iov[1]; 901 struct udf_node *node; 902 void *buf; 903 char *cp; 904 int error, len, root; 905 906 /* 907 * A symbolic link in UDF is a list of variable-length path 908 * component structures. We build a pathname in the caller's 909 * uio by traversing this list. 910 */ 911 vp = ap->a_vp; 912 node = VTON(vp); 913 len = le64toh(node->fentry->inf_len); 914 buf = malloc(len, M_DEVBUF, M_WAITOK); 915 iov[0].iov_len = len; 916 iov[0].iov_base = buf; 917 uio.uio_iov = iov; 918 uio.uio_iovcnt = 1; 919 uio.uio_offset = 0; 920 uio.uio_resid = iov[0].iov_len; 921 uio.uio_segflg = UIO_SYSSPACE; 922 uio.uio_rw = UIO_READ; 923 uio.uio_td = curthread; 924 error = VOP_READ(vp, &uio, 0, ap->a_cred); 925 if (error) 926 goto error; 927 928 pc = buf; 929 end = (void *)((char *)buf + len); 930 root = 0; 931 while (pc < end) { 932 switch (pc->type) { 933 case UDF_PATH_ROOT: 934 /* Only allow this at the beginning of a path. */ 935 if ((void *)pc != buf) { 936 error = EINVAL; 937 goto error; 938 } 939 cp = "/"; 940 len = 1; 941 root = 1; 942 break; 943 case UDF_PATH_DOT: 944 cp = "."; 945 len = 1; 946 break; 947 case UDF_PATH_DOTDOT: 948 cp = ".."; 949 len = 2; 950 break; 951 case UDF_PATH_PATH: 952 if (pc->length == 0) { 953 error = EINVAL; 954 goto error; 955 } 956 /* 957 * XXX: We only support CS8 which appears to map 958 * to ASCII directly. 959 */ 960 switch (pc->identifier[0]) { 961 case 8: 962 cp = pc->identifier + 1; 963 len = pc->length - 1; 964 break; 965 default: 966 error = EOPNOTSUPP; 967 goto error; 968 } 969 break; 970 default: 971 error = EINVAL; 972 goto error; 973 } 974 975 /* 976 * If this is not the first component, insert a path 977 * separator. 978 */ 979 if (pc != buf) { 980 /* If we started with root we already have a "/". */ 981 if (root) 982 goto skipslash; 983 root = 0; 984 if (ap->a_uio->uio_resid < 1) { 985 error = ENAMETOOLONG; 986 goto error; 987 } 988 error = uiomove("/", 1, ap->a_uio); 989 if (error) 990 break; 991 } 992 skipslash: 993 994 /* Append string at 'cp' of length 'len' to our path. */ 995 if (len > ap->a_uio->uio_resid) { 996 error = ENAMETOOLONG; 997 goto error; 998 } 999 error = uiomove(cp, len, ap->a_uio); 1000 if (error) 1001 break; 1002 1003 /* Advance to next component. */ 1004 pc = (void *)((char *)pc + 4 + pc->length); 1005 } 1006 error: 1007 free(buf, M_DEVBUF); 1008 return (error); 1009 } 1010 1011 static int 1012 udf_strategy(struct vop_strategy_args *a) 1013 { 1014 struct buf *bp; 1015 struct vnode *vp; 1016 struct udf_node *node; 1017 struct bufobj *bo; 1018 off_t offset; 1019 uint32_t maxsize; 1020 daddr_t sector; 1021 int error; 1022 1023 bp = a->a_bp; 1024 vp = a->a_vp; 1025 node = VTON(vp); 1026 1027 if (bp->b_blkno == bp->b_lblkno) { 1028 offset = lblktosize(node->udfmp, bp->b_lblkno); 1029 error = udf_bmap_internal(node, offset, §or, &maxsize); 1030 if (error) { 1031 clrbuf(bp); 1032 bp->b_blkno = -1; 1033 bufdone(bp); 1034 return (0); 1035 } 1036 /* bmap gives sector numbers, bio works with device blocks */ 1037 bp->b_blkno = sector << (node->udfmp->bshift - DEV_BSHIFT); 1038 } 1039 bo = node->udfmp->im_bo; 1040 bp->b_iooffset = dbtob(bp->b_blkno); 1041 BO_STRATEGY(bo, bp); 1042 return (0); 1043 } 1044 1045 static int 1046 udf_bmap(struct vop_bmap_args *a) 1047 { 1048 struct udf_node *node; 1049 uint32_t max_size; 1050 daddr_t lsector; 1051 int nblk; 1052 int error; 1053 1054 node = VTON(a->a_vp); 1055 1056 if (a->a_bop != NULL) 1057 *a->a_bop = &node->udfmp->im_devvp->v_bufobj; 1058 if (a->a_bnp == NULL) 1059 return (0); 1060 if (a->a_runb) 1061 *a->a_runb = 0; 1062 1063 /* 1064 * UDF_INVALID_BMAP means data embedded into fentry, this is an internal 1065 * error that should not be propagated to calling code. 1066 * Most obvious mapping for this error is EOPNOTSUPP as we can not truly 1067 * translate block numbers in this case. 1068 * Incidentally, this return code will make vnode pager to use VOP_READ 1069 * to get data for mmap-ed pages and udf_read knows how to do the right 1070 * thing for this kind of files. 1071 */ 1072 error = udf_bmap_internal(node, a->a_bn << node->udfmp->bshift, 1073 &lsector, &max_size); 1074 if (error == UDF_INVALID_BMAP) 1075 return (EOPNOTSUPP); 1076 if (error) 1077 return (error); 1078 1079 /* Translate logical to physical sector number */ 1080 *a->a_bnp = lsector << (node->udfmp->bshift - DEV_BSHIFT); 1081 1082 /* 1083 * Determine maximum number of readahead blocks following the 1084 * requested block. 1085 */ 1086 if (a->a_runp) { 1087 nblk = (max_size >> node->udfmp->bshift) - 1; 1088 if (nblk <= 0) 1089 *a->a_runp = 0; 1090 else if (nblk >= (MAXBSIZE >> node->udfmp->bshift)) 1091 *a->a_runp = (MAXBSIZE >> node->udfmp->bshift) - 1; 1092 else 1093 *a->a_runp = nblk; 1094 } 1095 1096 if (a->a_runb) { 1097 *a->a_runb = 0; 1098 } 1099 1100 return (0); 1101 } 1102 1103 /* 1104 * The all powerful VOP_LOOKUP(). 1105 */ 1106 static int 1107 udf_lookup(struct vop_cachedlookup_args *a) 1108 { 1109 struct vnode *dvp; 1110 struct vnode *tdp = NULL; 1111 struct vnode **vpp = a->a_vpp; 1112 struct udf_node *node; 1113 struct udf_mnt *udfmp; 1114 struct fileid_desc *fid = NULL; 1115 struct udf_dirstream *ds; 1116 u_long nameiop; 1117 u_long flags; 1118 char *nameptr; 1119 long namelen; 1120 ino_t id = 0; 1121 int offset, error = 0; 1122 int fsize, lkflags, ltype, numdirpasses; 1123 1124 dvp = a->a_dvp; 1125 node = VTON(dvp); 1126 udfmp = node->udfmp; 1127 nameiop = a->a_cnp->cn_nameiop; 1128 flags = a->a_cnp->cn_flags; 1129 lkflags = a->a_cnp->cn_lkflags; 1130 nameptr = a->a_cnp->cn_nameptr; 1131 namelen = a->a_cnp->cn_namelen; 1132 fsize = le64toh(node->fentry->inf_len); 1133 1134 /* 1135 * If this is a LOOKUP and we've already partially searched through 1136 * the directory, pick up where we left off and flag that the 1137 * directory may need to be searched twice. For a full description, 1138 * see /sys/fs/cd9660/cd9660_lookup.c:cd9660_lookup() 1139 */ 1140 if (nameiop != LOOKUP || node->diroff == 0 || node->diroff > fsize) { 1141 offset = 0; 1142 numdirpasses = 1; 1143 } else { 1144 offset = node->diroff; 1145 numdirpasses = 2; 1146 nchstats.ncs_2passes++; 1147 } 1148 1149 lookloop: 1150 ds = udf_opendir(node, offset, fsize, udfmp); 1151 1152 while ((fid = udf_getfid(ds)) != NULL) { 1153 1154 /* XXX Should we return an error on a bad fid? */ 1155 if (udf_checktag(&fid->tag, TAGID_FID)) { 1156 printf("udf_lookup: Invalid tag\n"); 1157 error = EIO; 1158 break; 1159 } 1160 1161 /* Is this a deleted file? */ 1162 if (fid->file_char & UDF_FILE_CHAR_DEL) 1163 continue; 1164 1165 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 1166 if (flags & ISDOTDOT) { 1167 id = udf_getid(&fid->icb); 1168 break; 1169 } 1170 } else { 1171 if (!(udf_cmpname(&fid->data[fid->l_iu], 1172 nameptr, fid->l_fi, namelen, udfmp))) { 1173 id = udf_getid(&fid->icb); 1174 break; 1175 } 1176 } 1177 } 1178 1179 if (!error) 1180 error = ds->error; 1181 1182 /* XXX Bail out here? */ 1183 if (error) { 1184 udf_closedir(ds); 1185 return (error); 1186 } 1187 1188 /* Did we have a match? */ 1189 if (id) { 1190 /* 1191 * Remember where this entry was if it's the final 1192 * component. 1193 */ 1194 if ((flags & ISLASTCN) && nameiop == LOOKUP) 1195 node->diroff = ds->offset + ds->off; 1196 if (numdirpasses == 2) 1197 nchstats.ncs_pass2++; 1198 udf_closedir(ds); 1199 1200 if (flags & ISDOTDOT) { 1201 error = vn_vget_ino(dvp, id, lkflags, &tdp); 1202 } else if (node->hash_id == id) { 1203 VREF(dvp); /* we want ourself, ie "." */ 1204 /* 1205 * When we lookup "." we still can be asked to lock it 1206 * differently. 1207 */ 1208 ltype = lkflags & LK_TYPE_MASK; 1209 if (ltype != VOP_ISLOCKED(dvp)) { 1210 if (ltype == LK_EXCLUSIVE) 1211 vn_lock(dvp, LK_UPGRADE | LK_RETRY); 1212 else /* if (ltype == LK_SHARED) */ 1213 vn_lock(dvp, LK_DOWNGRADE | LK_RETRY); 1214 } 1215 tdp = dvp; 1216 } else 1217 error = udf_vget(udfmp->im_mountp, id, lkflags, &tdp); 1218 if (!error) { 1219 *vpp = tdp; 1220 /* Put this entry in the cache */ 1221 if (flags & MAKEENTRY) 1222 cache_enter(dvp, *vpp, a->a_cnp); 1223 } 1224 } else { 1225 /* Name wasn't found on this pass. Do another pass? */ 1226 if (numdirpasses == 2) { 1227 numdirpasses--; 1228 offset = 0; 1229 udf_closedir(ds); 1230 goto lookloop; 1231 } 1232 udf_closedir(ds); 1233 1234 /* Enter name into cache as non-existant */ 1235 if (flags & MAKEENTRY) 1236 cache_enter(dvp, *vpp, a->a_cnp); 1237 1238 if ((flags & ISLASTCN) && 1239 (nameiop == CREATE || nameiop == RENAME)) { 1240 error = EROFS; 1241 } else { 1242 error = ENOENT; 1243 } 1244 } 1245 1246 return (error); 1247 } 1248 1249 static int 1250 udf_reclaim(struct vop_reclaim_args *a) 1251 { 1252 struct vnode *vp; 1253 struct udf_node *unode; 1254 1255 vp = a->a_vp; 1256 unode = VTON(vp); 1257 1258 /* 1259 * Destroy the vm object and flush associated pages. 1260 */ 1261 vnode_destroy_vobject(vp); 1262 1263 if (unode != NULL) { 1264 vfs_hash_remove(vp); 1265 1266 if (unode->fentry != NULL) 1267 free(unode->fentry, M_UDFFENTRY); 1268 uma_zfree(udf_zone_node, unode); 1269 vp->v_data = NULL; 1270 } 1271 1272 return (0); 1273 } 1274 1275 static int 1276 udf_vptofh(struct vop_vptofh_args *a) 1277 { 1278 struct udf_node *node; 1279 struct ifid *ifhp; 1280 1281 node = VTON(a->a_vp); 1282 ifhp = (struct ifid *)a->a_fhp; 1283 ifhp->ifid_len = sizeof(struct ifid); 1284 ifhp->ifid_ino = node->hash_id; 1285 1286 return (0); 1287 } 1288 1289 /* 1290 * Read the block and then set the data pointer to correspond with the 1291 * offset passed in. Only read in at most 'size' bytes, and then set 'size' 1292 * to the number of bytes pointed to. If 'size' is zero, try to read in a 1293 * whole extent. 1294 * 1295 * Note that *bp may be assigned error or not. 1296 * 1297 */ 1298 static int 1299 udf_readatoffset(struct udf_node *node, int *size, off_t offset, 1300 struct buf **bp, uint8_t **data) 1301 { 1302 struct udf_mnt *udfmp = node->udfmp; 1303 struct vnode *vp = node->i_vnode; 1304 struct file_entry *fentry; 1305 struct buf *bp1; 1306 uint32_t max_size; 1307 daddr_t sector; 1308 off_t off; 1309 int adj_size; 1310 int error; 1311 1312 /* 1313 * This call is made *not* only to detect UDF_INVALID_BMAP case, 1314 * max_size is used as an ad-hoc read-ahead hint for "normal" case. 1315 */ 1316 error = udf_bmap_internal(node, offset, §or, &max_size); 1317 if (error == UDF_INVALID_BMAP) { 1318 /* 1319 * This error means that the file *data* is stored in the 1320 * allocation descriptor field of the file entry. 1321 */ 1322 fentry = node->fentry; 1323 *data = &fentry->data[le32toh(fentry->l_ea)]; 1324 *size = le32toh(fentry->l_ad); 1325 if (offset >= *size) 1326 *size = 0; 1327 else { 1328 *data += offset; 1329 *size -= offset; 1330 } 1331 return (0); 1332 } else if (error != 0) { 1333 return (error); 1334 } 1335 1336 /* Adjust the size so that it is within range */ 1337 if (*size == 0 || *size > max_size) 1338 *size = max_size; 1339 1340 /* 1341 * Because we will read starting at block boundary, we need to adjust 1342 * how much we need to read so that all promised data is in. 1343 * Also, we can't promise to read more than MAXBSIZE bytes starting 1344 * from block boundary, so adjust what we promise too. 1345 */ 1346 off = blkoff(udfmp, offset); 1347 *size = min(*size, MAXBSIZE - off); 1348 adj_size = (*size + off + udfmp->bmask) & ~udfmp->bmask; 1349 *bp = NULL; 1350 if ((error = bread(vp, lblkno(udfmp, offset), adj_size, NOCRED, bp))) { 1351 printf("warning: udf_readlblks returned error %d\n", error); 1352 /* note: *bp may be non-NULL */ 1353 return (error); 1354 } 1355 1356 bp1 = *bp; 1357 *data = (uint8_t *)&bp1->b_data[offset & udfmp->bmask]; 1358 return (0); 1359 } 1360 1361 /* 1362 * Translate a file offset into a logical block and then into a physical 1363 * block. 1364 * max_size - maximum number of bytes that can be read starting from given 1365 * offset, rather than beginning of calculated sector number 1366 */ 1367 static int 1368 udf_bmap_internal(struct udf_node *node, off_t offset, daddr_t *sector, 1369 uint32_t *max_size) 1370 { 1371 struct udf_mnt *udfmp; 1372 struct file_entry *fentry; 1373 void *icb; 1374 struct icb_tag *tag; 1375 uint32_t icblen = 0; 1376 daddr_t lsector; 1377 int ad_offset, ad_num = 0; 1378 int i, p_offset; 1379 1380 udfmp = node->udfmp; 1381 fentry = node->fentry; 1382 tag = &fentry->icbtag; 1383 1384 switch (le16toh(tag->strat_type)) { 1385 case 4: 1386 break; 1387 1388 case 4096: 1389 printf("Cannot deal with strategy4096 yet!\n"); 1390 return (ENODEV); 1391 1392 default: 1393 printf("Unknown strategy type %d\n", tag->strat_type); 1394 return (ENODEV); 1395 } 1396 1397 switch (le16toh(tag->flags) & 0x7) { 1398 case 0: 1399 /* 1400 * The allocation descriptor field is filled with short_ad's. 1401 * If the offset is beyond the current extent, look for the 1402 * next extent. 1403 */ 1404 do { 1405 offset -= icblen; 1406 ad_offset = sizeof(struct short_ad) * ad_num; 1407 if (ad_offset > le32toh(fentry->l_ad)) { 1408 printf("File offset out of bounds\n"); 1409 return (EINVAL); 1410 } 1411 icb = GETICB(short_ad, fentry, 1412 le32toh(fentry->l_ea) + ad_offset); 1413 icblen = GETICBLEN(short_ad, icb); 1414 ad_num++; 1415 } while(offset >= icblen); 1416 1417 lsector = (offset >> udfmp->bshift) + 1418 le32toh(((struct short_ad *)(icb))->pos); 1419 1420 *max_size = icblen - offset; 1421 1422 break; 1423 case 1: 1424 /* 1425 * The allocation descriptor field is filled with long_ad's 1426 * If the offset is beyond the current extent, look for the 1427 * next extent. 1428 */ 1429 do { 1430 offset -= icblen; 1431 ad_offset = sizeof(struct long_ad) * ad_num; 1432 if (ad_offset > le32toh(fentry->l_ad)) { 1433 printf("File offset out of bounds\n"); 1434 return (EINVAL); 1435 } 1436 icb = GETICB(long_ad, fentry, 1437 le32toh(fentry->l_ea) + ad_offset); 1438 icblen = GETICBLEN(long_ad, icb); 1439 ad_num++; 1440 } while(offset >= icblen); 1441 1442 lsector = (offset >> udfmp->bshift) + 1443 le32toh(((struct long_ad *)(icb))->loc.lb_num); 1444 1445 *max_size = icblen - offset; 1446 1447 break; 1448 case 3: 1449 /* 1450 * This type means that the file *data* is stored in the 1451 * allocation descriptor field of the file entry. 1452 */ 1453 *max_size = 0; 1454 *sector = node->hash_id + udfmp->part_start; 1455 1456 return (UDF_INVALID_BMAP); 1457 case 2: 1458 /* DirectCD does not use extended_ad's */ 1459 default: 1460 printf("Unsupported allocation descriptor %d\n", 1461 tag->flags & 0x7); 1462 return (ENODEV); 1463 } 1464 1465 *sector = lsector + udfmp->part_start; 1466 1467 /* 1468 * Check the sparing table. Each entry represents the beginning of 1469 * a packet. 1470 */ 1471 if (udfmp->s_table != NULL) { 1472 for (i = 0; i< udfmp->s_table_entries; i++) { 1473 p_offset = 1474 lsector - le32toh(udfmp->s_table->entries[i].org); 1475 if ((p_offset < udfmp->p_sectors) && (p_offset >= 0)) { 1476 *sector = 1477 le32toh(udfmp->s_table->entries[i].map) + 1478 p_offset; 1479 break; 1480 } 1481 } 1482 } 1483 1484 return (0); 1485 } 1486