1 /* $OpenBSD: udf_vnops.c,v 1.70 2023/04/13 02:19:05 jsg Exp $ */ 2 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: src/sys/fs/udf/udf_vnops.c,v 1.50 2005/01/28 14:42:16 phk Exp $ 29 */ 30 31 /* 32 * Ported to OpenBSD by Pedro Martelletto in February 2005. 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/namei.h> 38 #include <sys/malloc.h> 39 #include <sys/mutex.h> 40 #include <sys/stat.h> 41 #include <sys/buf.h> 42 #include <sys/pool.h> 43 #include <sys/lock.h> 44 #include <sys/mount.h> 45 #include <sys/vnode.h> 46 #include <sys/dirent.h> 47 #include <sys/queue.h> 48 #include <sys/endian.h> 49 #include <sys/specdev.h> 50 #include <sys/unistd.h> 51 52 #include <crypto/siphash.h> 53 54 #include <isofs/udf/ecma167-udf.h> 55 #include <isofs/udf/udf.h> 56 #include <isofs/udf/udf_extern.h> 57 58 int udf_bmap_internal(struct unode *, off_t, daddr_t *, uint32_t *); 59 60 const struct vops udf_vops = { 61 .vop_access = udf_access, 62 .vop_bmap = udf_bmap, 63 .vop_lookup = udf_lookup, 64 .vop_getattr = udf_getattr, 65 .vop_open = udf_open, 66 .vop_close = udf_close, 67 .vop_ioctl = udf_ioctl, 68 .vop_read = udf_read, 69 .vop_readdir = udf_readdir, 70 .vop_readlink = udf_readlink, 71 .vop_inactive = udf_inactive, 72 .vop_reclaim = udf_reclaim, 73 .vop_strategy = udf_strategy, 74 .vop_lock = udf_lock, 75 .vop_unlock = udf_unlock, 76 .vop_pathconf = udf_pathconf, 77 .vop_islocked = udf_islocked, 78 .vop_print = udf_print 79 }; 80 81 #define UDF_INVALID_BMAP -1 82 83 /* Look up a unode based on the udfino_t passed in and return its vnode */ 84 int 85 udf_hashlookup(struct umount *ump, udfino_t id, int flags, struct vnode **vpp) 86 { 87 struct unode *up; 88 struct udf_hash_lh *lh; 89 int error; 90 91 *vpp = NULL; 92 93 loop: 94 mtx_enter(&ump->um_hashmtx); 95 lh = &ump->um_hashtbl[SipHash24(&ump->um_hashkey, &id, sizeof(id)) & 96 ump->um_hashsz]; 97 if (lh == NULL) { 98 mtx_leave(&ump->um_hashmtx); 99 return (ENOENT); 100 } 101 102 LIST_FOREACH(up, lh, u_le) { 103 if (up->u_ino == id) { 104 mtx_leave(&ump->um_hashmtx); 105 error = vget(up->u_vnode, flags); 106 if (error == ENOENT) 107 goto loop; 108 if (error) 109 return (error); 110 *vpp = up->u_vnode; 111 return (0); 112 } 113 } 114 115 mtx_leave(&ump->um_hashmtx); 116 117 return (0); 118 } 119 120 int 121 udf_hashins(struct unode *up) 122 { 123 struct umount *ump; 124 struct udf_hash_lh *lh; 125 126 ump = up->u_ump; 127 128 vn_lock(up->u_vnode, LK_EXCLUSIVE | LK_RETRY); 129 mtx_enter(&ump->um_hashmtx); 130 lh = &ump->um_hashtbl[SipHash24(&ump->um_hashkey, 131 &up->u_ino, sizeof(up->u_ino)) & ump->um_hashsz]; 132 if (lh == NULL) 133 panic("hash entry is NULL, up->u_ino = %d", up->u_ino); 134 LIST_INSERT_HEAD(lh, up, u_le); 135 mtx_leave(&ump->um_hashmtx); 136 137 return (0); 138 } 139 140 int 141 udf_hashrem(struct unode *up) 142 { 143 struct umount *ump; 144 struct udf_hash_lh *lh; 145 146 ump = up->u_ump; 147 148 mtx_enter(&ump->um_hashmtx); 149 lh = &ump->um_hashtbl[SipHash24(&ump->um_hashkey, 150 &up->u_ino, sizeof(up->u_ino)) & ump->um_hashsz]; 151 if (lh == NULL) 152 panic("hash entry is NULL, up->u_ino = %d", up->u_ino); 153 LIST_REMOVE(up, u_le); 154 mtx_leave(&ump->um_hashmtx); 155 156 return (0); 157 } 158 159 int 160 udf_allocv(struct mount *mp, struct vnode **vpp, struct proc *p) 161 { 162 int error; 163 struct vnode *vp; 164 165 error = getnewvnode(VT_UDF, mp, &udf_vops, &vp); 166 if (error) { 167 printf("udf_allocv: failed to allocate new vnode\n"); 168 return (error); 169 } 170 171 *vpp = vp; 172 return (0); 173 } 174 175 /* Convert file entry permission (5 bits per owner/group/user) to a mode_t */ 176 static mode_t 177 udf_permtomode(struct unode *up) 178 { 179 uint32_t perm; 180 uint16_t flags; 181 mode_t mode; 182 183 perm = letoh32(up->u_fentry->perm); 184 flags = letoh16(up->u_fentry->icbtag.flags); 185 186 mode = perm & UDF_FENTRY_PERM_USER_MASK; 187 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2); 188 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 189 mode |= ((flags & UDF_ICB_TAG_FLAGS_STICKY) << 4); 190 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETGID) << 6); 191 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETUID) << 8); 192 193 return (mode); 194 } 195 196 int 197 udf_access(void *v) 198 { 199 struct vop_access_args *ap = v; 200 struct vnode *vp; 201 struct unode *up; 202 mode_t a_mode, mode; 203 204 vp = ap->a_vp; 205 up = VTOU(vp); 206 a_mode = ap->a_mode; 207 208 if (a_mode & VWRITE) { 209 switch (vp->v_type) { 210 case VDIR: 211 case VLNK: 212 case VREG: 213 return (EROFS); 214 /* NOTREACHED */ 215 default: 216 break; 217 } 218 } 219 220 mode = udf_permtomode(up); 221 222 return (vaccess(vp->v_type, mode, up->u_fentry->uid, up->u_fentry->gid, 223 a_mode, ap->a_cred)); 224 } 225 226 static int mon_lens[2][12] = { 227 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 228 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 229 }; 230 231 static int 232 udf_isaleapyear(int year) 233 { 234 int i; 235 236 i = (year % 4) ? 0 : 1; 237 i &= (year % 100) ? 1 : 0; 238 i |= (year % 400) ? 0 : 1; 239 240 return (i); 241 } 242 243 /* 244 * This is just a rough hack. Daylight savings isn't calculated and tv_nsec 245 * is ignored. 246 * Timezone calculation compliments of Julian Elischer <julian@elischer.org>. 247 */ 248 static void 249 udf_timetotimespec(struct timestamp *time, struct timespec *t) 250 { 251 int i, lpyear, daysinyear, year; 252 union { 253 uint16_t u_tz_offset; 254 int16_t s_tz_offset; 255 } tz; 256 257 /* DirectCD seems to like using bogus year values */ 258 year = letoh16(time->year); 259 if (year < 1970) { 260 t->tv_sec = 0; 261 t->tv_nsec = 0; 262 return; 263 } 264 265 /* Calculate the time and day */ 266 t->tv_nsec = 1000 * time->usec + 100000 * time->hund_usec 267 + 10000000 * time->centisec; 268 t->tv_sec = time->second; 269 t->tv_sec += time->minute * 60; 270 t->tv_sec += time->hour * 3600; 271 t->tv_sec += time->day * 3600 * 24; 272 273 /* Calculate the month */ 274 lpyear = udf_isaleapyear(year); 275 for (i = 1; i < time->month; i++) 276 t->tv_sec += mon_lens[lpyear][i] * 3600 * 24; 277 278 /* Speed up the calculation */ 279 if (year > 1979) 280 t->tv_sec += 315532800; 281 if (year > 1989) 282 t->tv_sec += 315619200; 283 if (year > 1999) 284 t->tv_sec += 315532800; 285 for (i = 2000; i < year; i++) { 286 daysinyear = udf_isaleapyear(i) + 365 ; 287 t->tv_sec += daysinyear * 3600 * 24; 288 } 289 290 /* 291 * Calculate the time zone. The timezone is 12 bit signed 2's 292 * compliment, so we gotta do some extra magic to handle it right. 293 */ 294 tz.u_tz_offset = letoh16(time->type_tz); 295 tz.u_tz_offset &= 0x0fff; 296 if (tz.u_tz_offset & 0x0800) 297 tz.u_tz_offset |= 0xf000; /* extend the sign to 16 bits */ 298 if ((time->type_tz & 0x1000) && (tz.s_tz_offset != -2047)) 299 t->tv_sec -= tz.s_tz_offset * 60; 300 301 return; 302 } 303 304 int 305 udf_getattr(void *v) 306 { 307 struct vop_getattr_args *ap = v; 308 struct vnode *vp; 309 struct unode *up; 310 struct vattr *vap; 311 struct extfile_entry *xfentry; 312 struct file_entry *fentry; 313 struct timespec ts; 314 315 ts.tv_sec = 0; 316 317 vp = ap->a_vp; 318 vap = ap->a_vap; 319 up = VTOU(vp); 320 321 xfentry = up->u_fentry; 322 fentry = (struct file_entry *)up->u_fentry; 323 324 vap->va_fsid = up->u_dev; 325 vap->va_fileid = up->u_ino; 326 vap->va_mode = udf_permtomode(up); 327 vap->va_nlink = letoh16(fentry->link_cnt); 328 /* 329 * The spec says that -1 is valid for uid/gid and indicates an 330 * invalid uid/gid. How should this be represented? 331 */ 332 vap->va_uid = (letoh32(fentry->uid) == -1) ? 0 : letoh32(fentry->uid); 333 vap->va_gid = (letoh32(fentry->gid) == -1) ? 0 : letoh32(fentry->gid); 334 vap->va_rdev = 0; 335 if (vp->v_type & VDIR) { 336 vap->va_nlink++; /* Count a reference to ourselves */ 337 /* 338 * Directories that are recorded within their ICB will show 339 * as having 0 blocks recorded. Since tradition dictates 340 * that directories consume at least one logical block, 341 * make it appear so. 342 */ 343 vap->va_size = up->u_ump->um_bsize; 344 } else 345 vap->va_size = letoh64(fentry->inf_len); 346 if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0) { 347 udf_timetotimespec(&xfentry->atime, &vap->va_atime); 348 udf_timetotimespec(&xfentry->mtime, &vap->va_mtime); 349 if ((vp->v_type & VDIR) && xfentry->logblks_rec != 0) 350 vap->va_size = 351 letoh64(xfentry->logblks_rec) * up->u_ump->um_bsize; 352 } else { 353 udf_timetotimespec(&fentry->atime, &vap->va_atime); 354 udf_timetotimespec(&fentry->mtime, &vap->va_mtime); 355 if ((vp->v_type & VDIR) && fentry->logblks_rec != 0) 356 vap->va_size = 357 letoh64(fentry->logblks_rec) * up->u_ump->um_bsize; 358 } 359 vap->va_ctime = vap->va_mtime; /* Stored as an Extended Attribute */ 360 vap->va_flags = 0; 361 vap->va_gen = 1; 362 vap->va_blocksize = up->u_ump->um_bsize; 363 vap->va_bytes = letoh64(fentry->inf_len); 364 vap->va_type = vp->v_type; 365 vap->va_filerev = 0; 366 367 return (0); 368 } 369 370 int 371 udf_open(void *v) 372 { 373 return (0); /* Nothing to be done at this point */ 374 } 375 376 int 377 udf_close(void *v) 378 { 379 return (0); /* Nothing to be done at this point */ 380 } 381 382 /* 383 * File specific ioctls. 384 */ 385 int 386 udf_ioctl(void *v) 387 { 388 return (ENOTTY); 389 } 390 391 /* 392 * I'm not sure that this has much value in a read-only filesystem, but 393 * cd9660 has it too. 394 */ 395 int 396 udf_pathconf(void *v) 397 { 398 struct vop_pathconf_args *ap = v; 399 int error = 0; 400 401 switch (ap->a_name) { 402 case _PC_LINK_MAX: 403 *ap->a_retval = 65535; 404 break; 405 case _PC_NAME_MAX: 406 *ap->a_retval = NAME_MAX; 407 break; 408 case _PC_CHOWN_RESTRICTED: 409 *ap->a_retval = 1; 410 break; 411 case _PC_NO_TRUNC: 412 *ap->a_retval = 1; 413 break; 414 case _PC_TIMESTAMP_RESOLUTION: 415 *ap->a_retval = 1000; /* 1 microsecond */ 416 break; 417 default: 418 error = EINVAL; 419 break; 420 } 421 422 return (error); 423 } 424 425 int 426 udf_read(void *v) 427 { 428 struct vop_read_args *ap = v; 429 struct vnode *vp = ap->a_vp; 430 struct uio *uio = ap->a_uio; 431 struct unode *up = VTOU(vp); 432 struct buf *bp; 433 uint8_t *data; 434 off_t fsize, offset; 435 int error = 0; 436 int size; 437 438 if (uio->uio_offset < 0) 439 return (EINVAL); 440 441 fsize = letoh64(up->u_fentry->inf_len); 442 443 while (uio->uio_offset < fsize && uio->uio_resid > 0) { 444 offset = uio->uio_offset; 445 size = ulmin(uio->uio_resid, MAXBSIZE); 446 if (size > fsize - offset) 447 size = fsize - offset; 448 error = udf_readatoffset(up, &size, offset, &bp, &data); 449 if (error == 0) 450 error = uiomove(data, (size_t)size, uio); 451 if (bp != NULL) { 452 brelse(bp); 453 bp = NULL; 454 } 455 if (error) 456 break; 457 }; 458 459 return (error); 460 } 461 462 /* 463 * Translate the name from a CS0 dstring to a 16-bit Unicode String. 464 * Hooks need to be placed in here to translate from Unicode to the encoding 465 * that the kernel/user expects. Return the length of the translated string. 466 */ 467 int 468 udf_transname(char *cs0string, char *destname, int len, struct umount *ump) 469 { 470 unicode_t *transname; 471 int i, unilen = 0, destlen; 472 473 if (len > MAXNAMLEN) { 474 #ifdef DIAGNOSTIC 475 printf("udf_transname(): name too long\n"); 476 #endif 477 return (0); 478 } 479 480 /* allocate a buffer big enough to hold an 8->16 bit expansion */ 481 transname = pool_get(&udf_trans_pool, PR_WAITOK); 482 483 if ((unilen = udf_rawnametounicode(len, cs0string, transname)) == -1) { 484 #ifdef DIAGNOSTIC 485 printf("udf_transname(): Unicode translation failed\n"); 486 #endif 487 pool_put(&udf_trans_pool, transname); 488 return (0); 489 } 490 491 /* Pack it back to 8-bit Unicode. */ 492 for (i = 0; i < unilen ; i++) 493 if (transname[i] & 0xff00) 494 destname[i] = '?'; /* Fudge the 16bit chars */ 495 else 496 destname[i] = transname[i] & 0xff; 497 498 pool_put(&udf_trans_pool, transname); 499 500 /* Don't forget to terminate the string. */ 501 destname[unilen] = 0; 502 destlen = unilen; 503 504 return (destlen); 505 } 506 507 /* 508 * Compare a CS0 dstring with a name passed in from the VFS layer. Return 509 * 0 on a successful match, nonzero otherwise. Unicode work may need to be 510 * done here also. 511 */ 512 static int 513 udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct umount *ump) 514 { 515 char *transname; 516 int error = 0; 517 518 /* This is overkill, but not worth creating a new pool */ 519 transname = pool_get(&udf_trans_pool, PR_WAITOK); 520 521 cs0len = udf_transname(cs0string, transname, cs0len, ump); 522 523 /* Easy check. If they aren't the same length, they aren't equal */ 524 if ((cs0len == 0) || (cs0len != cmplen)) 525 error = -1; 526 else 527 error = bcmp(transname, cmpname, cmplen); 528 529 pool_put(&udf_trans_pool, transname); 530 531 return (error); 532 } 533 534 struct udf_uiodir { 535 struct dirent *dirent; 536 int eofflag; 537 }; 538 539 static int 540 udf_uiodir(struct udf_uiodir *uiodir, struct uio *uio, long off) 541 { 542 size_t de_size = DIRENT_SIZE(uiodir->dirent); 543 544 if (uio->uio_resid < de_size) { 545 uiodir->eofflag = 0; 546 return (-1); 547 } 548 uiodir->dirent->d_off = off; 549 uiodir->dirent->d_reclen = de_size; 550 551 return (uiomove(uiodir->dirent, de_size, uio)); 552 } 553 554 static struct udf_dirstream * 555 udf_opendir(struct unode *up, int offset, int fsize, struct umount *ump) 556 { 557 struct udf_dirstream *ds; 558 559 ds = pool_get(&udf_ds_pool, PR_WAITOK | PR_ZERO); 560 561 ds->node = up; 562 ds->offset = offset; 563 ds->ump = ump; 564 ds->fsize = fsize; 565 566 return (ds); 567 } 568 569 static struct fileid_desc * 570 udf_getfid(struct udf_dirstream *ds) 571 { 572 struct fileid_desc *fid; 573 int error, frag_size = 0, total_fid_size; 574 575 /* End of directory? */ 576 if (ds->offset + ds->off >= ds->fsize) { 577 ds->error = 0; 578 return (NULL); 579 } 580 581 /* Grab the first extent of the directory */ 582 if (ds->off == 0) { 583 ds->size = 0; 584 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 585 &ds->bp, &ds->data); 586 if (error) { 587 ds->error = error; 588 if (ds->bp != NULL) { 589 brelse(ds->bp); 590 ds->bp = NULL; 591 } 592 return (NULL); 593 } 594 } 595 596 /* 597 * Clean up from a previous fragmented FID. 598 * Is this the right place for this? 599 */ 600 if (ds->fid_fragment && ds->buf != NULL) { 601 ds->fid_fragment = 0; 602 free(ds->buf, M_UDFFID, 0); 603 } 604 605 fid = (struct fileid_desc*)&ds->data[ds->off]; 606 607 /* 608 * Check to see if the fid is fragmented. The first test 609 * ensures that we don't wander off the end of the buffer 610 * looking for the l_iu and l_fi fields. 611 */ 612 if (ds->off + UDF_FID_SIZE > ds->size || 613 ds->off + letoh16(fid->l_iu) + fid->l_fi + UDF_FID_SIZE > ds->size){ 614 615 /* Copy what we have of the fid into a buffer */ 616 frag_size = ds->size - ds->off; 617 if (frag_size >= ds->ump->um_bsize) { 618 printf("udf: invalid FID fragment\n"); 619 ds->error = EINVAL; 620 return (NULL); 621 } 622 623 /* 624 * File ID descriptors can only be at most one 625 * logical sector in size. 626 */ 627 ds->buf = malloc(ds->ump->um_bsize, M_UDFFID, M_WAITOK|M_ZERO); 628 bcopy(fid, ds->buf, frag_size); 629 630 /* Reduce all of the casting magic */ 631 fid = (struct fileid_desc*)ds->buf; 632 633 if (ds->bp != NULL) { 634 brelse(ds->bp); 635 ds->bp = NULL; 636 } 637 638 /* Fetch the next allocation */ 639 ds->offset += ds->size; 640 ds->size = 0; 641 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 642 &ds->bp, &ds->data); 643 if (error) { 644 ds->error = error; 645 if (ds->bp != NULL) { 646 brelse(ds->bp); 647 ds->bp = NULL; 648 } 649 return (NULL); 650 } 651 652 /* 653 * If the fragment was so small that we didn't get 654 * the l_iu and l_fi fields, copy those in. 655 */ 656 if (frag_size < UDF_FID_SIZE) 657 bcopy(ds->data, &ds->buf[frag_size], 658 UDF_FID_SIZE - frag_size); 659 660 /* 661 * Now that we have enough of the fid to work with, 662 * copy in the rest of the fid from the new 663 * allocation. 664 */ 665 total_fid_size = UDF_FID_SIZE + letoh16(fid->l_iu) + fid->l_fi; 666 if (total_fid_size > ds->ump->um_bsize) { 667 printf("udf: invalid FID\n"); 668 ds->error = EIO; 669 return (NULL); 670 } 671 bcopy(ds->data, &ds->buf[frag_size], 672 total_fid_size - frag_size); 673 674 ds->fid_fragment = 1; 675 } else { 676 total_fid_size = letoh16(fid->l_iu) + fid->l_fi + UDF_FID_SIZE; 677 } 678 679 /* 680 * Update the offset. Align on a 4 byte boundary because the 681 * UDF spec says so. 682 */ 683 if (!ds->fid_fragment) { 684 ds->off += (total_fid_size + 3) & ~0x03; 685 } else { 686 ds->off = (total_fid_size - frag_size + 3) & ~0x03; 687 } 688 ds->this_off = ds->offset + ds->off; 689 690 return (fid); 691 } 692 693 static void 694 udf_closedir(struct udf_dirstream *ds) 695 { 696 697 if (ds->bp != NULL) { 698 brelse(ds->bp); 699 ds->bp = NULL; 700 } 701 702 if (ds->fid_fragment && ds->buf != NULL) 703 free(ds->buf, M_UDFFID, 0); 704 705 pool_put(&udf_ds_pool, ds); 706 } 707 708 #define SELF_OFFSET 1 709 #define PARENT_OFFSET 2 710 711 int 712 udf_readdir(void *v) 713 { 714 struct vop_readdir_args *ap = v; 715 struct vnode *vp; 716 struct uio *uio; 717 struct dirent dir; 718 struct unode *up; 719 struct umount *ump; 720 struct fileid_desc *fid; 721 struct udf_uiodir uiodir; 722 struct udf_dirstream *ds; 723 off_t last_off; 724 enum { MODE_NORMAL, MODE_SELF, MODE_PARENT } mode; 725 int error = 0; 726 727 vp = ap->a_vp; 728 uio = ap->a_uio; 729 up = VTOU(vp); 730 ump = up->u_ump; 731 uiodir.eofflag = 1; 732 uiodir.dirent = &dir; 733 memset(&dir, 0, sizeof(dir)); 734 735 /* 736 * if asked to start at SELF_OFFSET or PARENT_OFFSET, search 737 * for the parent ref 738 */ 739 if (uio->uio_offset == SELF_OFFSET) { 740 mode = MODE_SELF; 741 uio->uio_offset = 0; 742 } else if (uio->uio_offset == PARENT_OFFSET) { 743 mode = MODE_PARENT; 744 uio->uio_offset = 0; 745 } else 746 mode = MODE_NORMAL; 747 748 /* 749 * Iterate through the file id descriptors. Give the parent dir 750 * entry special attention. 751 */ 752 if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) { 753 up->u_ump->um_start += up->u_ump->um_meta_start; 754 up->u_ump->um_len = up->u_ump->um_meta_len; 755 } 756 ds = udf_opendir(up, uio->uio_offset, 757 letoh64(up->u_fentry->inf_len), up->u_ump); 758 759 last_off = ds->offset + ds->off; 760 while ((fid = udf_getfid(ds)) != NULL) { 761 762 /* Should we return an error on a bad fid? */ 763 if (udf_checktag(&fid->tag, TAGID_FID)) { 764 printf("Invalid FID tag (%d)\n", fid->tag.id); 765 error = EIO; 766 break; 767 } 768 769 /* Is this a deleted file? */ 770 if (fid->file_char & UDF_FILE_CHAR_DEL) 771 continue; 772 773 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 774 /* Do up the '.' and '..' entries. Dummy values are 775 * used for the offset since the offset here is 776 * usually zero, and NFS doesn't like that value 777 */ 778 if (mode == MODE_NORMAL) { 779 dir.d_fileno = up->u_ino; 780 dir.d_type = DT_DIR; 781 dir.d_name[0] = '.'; 782 dir.d_name[1] = '\0'; 783 dir.d_namlen = 1; 784 error = udf_uiodir(&uiodir, uio, SELF_OFFSET); 785 if (error) 786 break; 787 } 788 if (mode != MODE_PARENT) { 789 dir.d_fileno = udf_getid(&fid->icb); 790 dir.d_type = DT_DIR; 791 dir.d_name[0] = '.'; 792 dir.d_name[1] = '.'; 793 dir.d_name[2] = '\0'; 794 dir.d_namlen = 2; 795 error = udf_uiodir(&uiodir, uio, PARENT_OFFSET); 796 } 797 mode = MODE_NORMAL; 798 } else if (mode != MODE_NORMAL) { 799 continue; 800 } else { 801 dir.d_namlen = udf_transname(&fid->data[fid->l_iu], 802 &dir.d_name[0], fid->l_fi, ump); 803 dir.d_fileno = udf_getid(&fid->icb); 804 dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ? 805 DT_DIR : DT_UNKNOWN; 806 error = udf_uiodir(&uiodir, uio, ds->this_off); 807 } 808 if (error) { 809 /* 810 * udf_uiodir() indicates there isn't space for 811 * another entry by returning -1 812 */ 813 if (error == -1) 814 error = 0; 815 break; 816 } 817 last_off = ds->this_off; 818 } 819 820 /* tell the calling layer whether we need to be called again */ 821 *ap->a_eofflag = uiodir.eofflag; 822 uio->uio_offset = last_off; 823 824 if (!error) 825 error = ds->error; 826 827 udf_closedir(ds); 828 if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) { 829 up->u_ump->um_start = up->u_ump->um_realstart; 830 up->u_ump->um_len = up->u_ump->um_reallen; 831 } 832 833 return (error); 834 } 835 836 /* Are there any implementations out there that do soft-links? */ 837 int 838 udf_readlink(void *v) 839 { 840 return (EOPNOTSUPP); 841 } 842 843 int 844 udf_strategy(void *v) 845 { 846 struct vop_strategy_args *ap = v; 847 struct buf *bp; 848 struct vnode *vp; 849 struct unode *up; 850 int maxsize, s, error; 851 852 bp = ap->a_bp; 853 vp = bp->b_vp; 854 up = VTOU(vp); 855 856 /* cd9660 has this test reversed, but it seems more logical this way */ 857 if (bp->b_blkno != bp->b_lblkno) { 858 /* 859 * Files that are embedded in the fentry don't translate well 860 * to a block number. Reject. 861 */ 862 if (udf_bmap_internal(up, bp->b_lblkno * up->u_ump->um_bsize, 863 &bp->b_lblkno, &maxsize)) { 864 clrbuf(bp); 865 bp->b_blkno = -1; 866 } 867 } else { 868 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL); 869 if (error) { 870 bp->b_error = error; 871 bp->b_flags |= B_ERROR; 872 s = splbio(); 873 biodone(bp); 874 splx(s); 875 return (error); 876 } 877 878 if ((long)bp->b_blkno == -1) 879 clrbuf(bp); 880 } 881 882 if ((long)bp->b_blkno == -1) { 883 s = splbio(); 884 biodone(bp); 885 splx(s); 886 } else { 887 bp->b_dev = vp->v_rdev; 888 VOP_STRATEGY(up->u_devvp, bp); 889 } 890 891 return (0); 892 } 893 894 int 895 udf_lock(void *v) 896 { 897 struct vop_lock_args *ap = v; 898 struct vnode *vp = ap->a_vp; 899 900 return rrw_enter(&VTOU(vp)->u_lock, ap->a_flags & LK_RWFLAGS); 901 } 902 903 int 904 udf_unlock(void *v) 905 { 906 struct vop_unlock_args *ap = v; 907 struct vnode *vp = ap->a_vp; 908 909 rrw_exit(&VTOU(vp)->u_lock); 910 return 0; 911 } 912 913 int 914 udf_islocked(void *v) 915 { 916 struct vop_islocked_args *ap = v; 917 918 return rrw_status(&VTOU(ap->a_vp)->u_lock); 919 } 920 921 int 922 udf_print(void *v) 923 { 924 struct vop_print_args *ap = v; 925 struct vnode *vp = ap->a_vp; 926 struct unode *up = VTOU(vp); 927 928 /* 929 * Complete the information given by vprint(). 930 */ 931 printf("tag VT_UDF, hash id %u\n", up->u_ino); 932 #ifdef DIAGNOSTIC 933 printf("\n"); 934 #endif 935 return (0); 936 } 937 938 int 939 udf_bmap(void *v) 940 { 941 struct vop_bmap_args *ap = v; 942 struct unode *up; 943 uint32_t max_size; 944 daddr_t lsector; 945 int error; 946 947 up = VTOU(ap->a_vp); 948 949 if (ap->a_vpp != NULL) 950 *ap->a_vpp = up->u_devvp; 951 if (ap->a_bnp == NULL) 952 return (0); 953 954 error = udf_bmap_internal(up, ap->a_bn * up->u_ump->um_bsize, 955 &lsector, &max_size); 956 if (error) 957 return (error); 958 959 /* Translate logical to physical sector number */ 960 *ap->a_bnp = lsector << (up->u_ump->um_bshift - DEV_BSHIFT); 961 962 /* Punt on read-ahead for now */ 963 if (ap->a_runp) 964 *ap->a_runp = 0; 965 966 return (0); 967 } 968 969 /* 970 * The all powerful VOP_LOOKUP(). 971 */ 972 int 973 udf_lookup(void *v) 974 { 975 struct vop_lookup_args *ap = v; 976 struct vnode *dvp; 977 struct vnode *tdp = NULL; 978 struct vnode **vpp = ap->a_vpp; 979 struct unode *up; 980 struct umount *ump; 981 struct fileid_desc *fid = NULL; 982 struct udf_dirstream *ds; 983 struct proc *p; 984 u_long nameiop; 985 u_long flags; 986 char *nameptr; 987 long namelen; 988 udfino_t id = 0; 989 int offset, error = 0; 990 int numdirpasses, fsize; 991 992 extern struct nchstats nchstats; 993 994 dvp = ap->a_dvp; 995 up = VTOU(dvp); 996 ump = up->u_ump; 997 nameiop = ap->a_cnp->cn_nameiop; 998 flags = ap->a_cnp->cn_flags; 999 nameptr = ap->a_cnp->cn_nameptr; 1000 namelen = ap->a_cnp->cn_namelen; 1001 fsize = letoh64(up->u_fentry->inf_len); 1002 p = ap->a_cnp->cn_proc; 1003 *vpp = NULL; 1004 1005 /* 1006 * Make sure the process can scan the requested directory. 1007 */ 1008 error = VOP_ACCESS(dvp, VEXEC, ap->a_cnp->cn_cred, p); 1009 if (error) 1010 return (error); 1011 1012 /* 1013 * Check if the (directory, name) tuple has been already cached. 1014 */ 1015 error = cache_lookup(dvp, vpp, ap->a_cnp); 1016 if (error >= 0) 1017 return (error); 1018 else 1019 error = 0; 1020 1021 /* 1022 * If dvp is what's being looked up, then return it. 1023 */ 1024 if (ap->a_cnp->cn_namelen == 1 && ap->a_cnp->cn_nameptr[0] == '.') { 1025 vref(dvp); 1026 *vpp = dvp; 1027 return (0); 1028 } 1029 1030 /* 1031 * If this is a LOOKUP and we've already partially searched through 1032 * the directory, pick up where we left off and flag that the 1033 * directory may need to be searched twice. For a full description, 1034 * see /sys/isofs/cd9660/cd9660_lookup.c:cd9660_lookup() 1035 */ 1036 if (nameiop != LOOKUP || up->u_diroff == 0 || up->u_diroff > fsize) { 1037 offset = 0; 1038 numdirpasses = 1; 1039 } else { 1040 offset = up->u_diroff; 1041 numdirpasses = 2; 1042 nchstats.ncs_2passes++; 1043 } 1044 1045 if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) { 1046 up->u_ump->um_start += up->u_ump->um_meta_start; 1047 up->u_ump->um_len = up->u_ump->um_meta_len; 1048 } 1049 lookloop: 1050 ds = udf_opendir(up, offset, fsize, ump); 1051 1052 while ((fid = udf_getfid(ds)) != NULL) { 1053 /* Check for a valid FID tag. */ 1054 if (udf_checktag(&fid->tag, TAGID_FID)) { 1055 printf("udf_lookup: Invalid tag\n"); 1056 error = EIO; 1057 break; 1058 } 1059 1060 /* Is this a deleted file? */ 1061 if (fid->file_char & UDF_FILE_CHAR_DEL) 1062 continue; 1063 1064 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 1065 if (flags & ISDOTDOT) { 1066 id = udf_getid(&fid->icb); 1067 break; 1068 } 1069 } else { 1070 if (!(udf_cmpname(&fid->data[fid->l_iu], 1071 nameptr, fid->l_fi, namelen, ump))) { 1072 id = udf_getid(&fid->icb); 1073 break; 1074 } 1075 } 1076 } 1077 1078 if (!error) 1079 error = ds->error; 1080 1081 if (error) { 1082 udf_closedir(ds); 1083 if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) { 1084 up->u_ump->um_start = up->u_ump->um_realstart; 1085 up->u_ump->um_len = up->u_ump->um_reallen; 1086 } 1087 return (error); 1088 } 1089 1090 /* Did we have a match? */ 1091 if (id) { 1092 error = udf_vget(ump->um_mountp, id, &tdp); 1093 if (!error) { 1094 /* 1095 * Remember where this entry was if it's the final 1096 * component. 1097 */ 1098 if ((flags & ISLASTCN) && nameiop == LOOKUP) 1099 up->u_diroff = ds->offset + ds->off; 1100 if (numdirpasses == 2) 1101 nchstats.ncs_pass2++; 1102 if (!(flags & LOCKPARENT) || !(flags & ISLASTCN)) { 1103 ap->a_cnp->cn_flags |= PDIRUNLOCK; 1104 VOP_UNLOCK(dvp); 1105 } 1106 1107 *vpp = tdp; 1108 } 1109 } else { 1110 /* Name wasn't found on this pass. Do another pass? */ 1111 if (numdirpasses == 2) { 1112 numdirpasses--; 1113 offset = 0; 1114 udf_closedir(ds); 1115 goto lookloop; 1116 } 1117 1118 if ((flags & ISLASTCN) && 1119 (nameiop == CREATE || nameiop == RENAME)) { 1120 error = EROFS; 1121 } else { 1122 error = ENOENT; 1123 } 1124 } 1125 1126 /* 1127 * Cache the result of this lookup. 1128 */ 1129 if (flags & MAKEENTRY) 1130 cache_enter(dvp, *vpp, ap->a_cnp); 1131 1132 udf_closedir(ds); 1133 if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) { 1134 up->u_ump->um_start = up->u_ump->um_realstart; 1135 up->u_ump->um_len = up->u_ump->um_reallen; 1136 } 1137 1138 return (error); 1139 } 1140 1141 int 1142 udf_inactive(void *v) 1143 { 1144 struct vop_inactive_args *ap = v; 1145 struct vnode *vp = ap->a_vp; 1146 1147 /* 1148 * No need to sync anything, so just unlock the vnode and return. 1149 */ 1150 VOP_UNLOCK(vp); 1151 1152 return (0); 1153 } 1154 1155 int 1156 udf_reclaim(void *v) 1157 { 1158 struct vop_reclaim_args *ap = v; 1159 struct vnode *vp; 1160 struct unode *up; 1161 1162 vp = ap->a_vp; 1163 up = VTOU(vp); 1164 1165 if (up != NULL) { 1166 udf_hashrem(up); 1167 if (up->u_devvp) { 1168 vrele(up->u_devvp); 1169 up->u_devvp = 0; 1170 } 1171 1172 if (up->u_fentry != NULL) 1173 free(up->u_fentry, M_UDFFENTRY, 0); 1174 1175 pool_put(&unode_pool, up); 1176 vp->v_data = NULL; 1177 } 1178 1179 return (0); 1180 } 1181 1182 /* 1183 * Read the block and then set the data pointer to correspond with the 1184 * offset passed in. Only read in at most 'size' bytes, and then set 'size' 1185 * to the number of bytes pointed to. If 'size' is zero, try to read in a 1186 * whole extent. 1187 * 1188 * Note that *bp may be assigned error or not. 1189 * 1190 */ 1191 int 1192 udf_readatoffset(struct unode *up, int *size, off_t offset, 1193 struct buf **bp, uint8_t **data) 1194 { 1195 struct umount *ump; 1196 struct extfile_entry *xfentry = NULL; 1197 struct file_entry *fentry = NULL; 1198 struct buf *bp1; 1199 uint32_t max_size; 1200 daddr_t sector; 1201 int error; 1202 1203 ump = up->u_ump; 1204 1205 *bp = NULL; 1206 error = udf_bmap_internal(up, offset, §or, &max_size); 1207 if (error == UDF_INVALID_BMAP) { 1208 /* 1209 * This error means that the file *data* is stored in the 1210 * allocation descriptor field of the file entry. 1211 */ 1212 if (udf_checktag(&up->u_fentry->tag, TAGID_EXTFENTRY) == 0) { 1213 xfentry = up->u_fentry; 1214 *data = &xfentry->data[letoh32(xfentry->l_ea)]; 1215 *size = letoh32(xfentry->l_ad); 1216 } else { 1217 fentry = (struct file_entry *)up->u_fentry; 1218 *data = &fentry->data[letoh32(fentry->l_ea)]; 1219 *size = letoh32(fentry->l_ad); 1220 } 1221 return (0); 1222 } else if (error != 0) { 1223 return (error); 1224 } 1225 1226 /* Adjust the size so that it is within range */ 1227 if (*size == 0 || *size > max_size) 1228 *size = max_size; 1229 *size = min(*size, MAXBSIZE); 1230 1231 if ((error = udf_readlblks(ump, sector, *size, bp))) { 1232 printf("warning: udf_readlblks returned error %d\n", error); 1233 /* note: *bp may be non-NULL */ 1234 return (error); 1235 } 1236 1237 bp1 = *bp; 1238 *data = (uint8_t *)&bp1->b_data[offset % ump->um_bsize]; 1239 return (0); 1240 } 1241 1242 /* 1243 * Translate a file offset into a logical block and then into a physical 1244 * block. 1245 */ 1246 int 1247 udf_bmap_internal(struct unode *up, off_t offset, daddr_t *sector, 1248 uint32_t *max_size) 1249 { 1250 struct umount *ump; 1251 struct extfile_entry *xfentry; 1252 struct file_entry *fentry; 1253 void *icb; 1254 struct icb_tag *tag; 1255 uint32_t icblen = 0; 1256 daddr_t lsector; 1257 int ad_offset, ad_num = 0; 1258 int i, p_offset, l_ea, l_ad; 1259 1260 ump = up->u_ump; 1261 xfentry = up->u_fentry; 1262 fentry = (struct file_entry *)up->u_fentry; 1263 tag = &fentry->icbtag; 1264 if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0) { 1265 l_ea = letoh32(xfentry->l_ea); 1266 l_ad = letoh32(xfentry->l_ad); 1267 } else { 1268 l_ea = letoh32(fentry->l_ea); 1269 l_ad = letoh32(fentry->l_ad); 1270 } 1271 1272 switch (letoh16(tag->strat_type)) { 1273 case 4: 1274 break; 1275 1276 case 4096: 1277 printf("Cannot deal with strategy4096 yet!\n"); 1278 return (ENODEV); 1279 1280 default: 1281 printf("Unknown strategy type %d\n", tag->strat_type); 1282 return (ENODEV); 1283 } 1284 1285 switch (letoh16(tag->flags) & 0x7) { 1286 case 0: 1287 /* 1288 * The allocation descriptor field is filled with short_ad's. 1289 * If the offset is beyond the current extent, look for the 1290 * next extent. 1291 */ 1292 do { 1293 offset -= icblen; 1294 ad_offset = sizeof(struct short_ad) * ad_num; 1295 if (ad_offset > l_ad) { 1296 printf("SFile offset out of bounds (%d > %d)\n", 1297 ad_offset, l_ad); 1298 return (EINVAL); 1299 } 1300 1301 if (udf_checktag(&up->u_fentry->tag, TAGID_EXTFENTRY) == 0) 1302 icb = GETICB(short_ad, xfentry, l_ea + ad_offset); 1303 else 1304 icb = GETICB(short_ad, fentry, l_ea + ad_offset); 1305 1306 icblen = GETICBLEN(short_ad, icb); 1307 ad_num++; 1308 } while(offset >= icblen); 1309 1310 lsector = (offset >> ump->um_bshift) + 1311 letoh32(((struct short_ad *)(icb))->lb_num); 1312 1313 *max_size = GETICBLEN(short_ad, icb); 1314 1315 break; 1316 case 1: 1317 /* 1318 * The allocation descriptor field is filled with long_ad's 1319 * If the offset is beyond the current extent, look for the 1320 * next extent. 1321 */ 1322 do { 1323 offset -= icblen; 1324 ad_offset = sizeof(struct long_ad) * ad_num; 1325 if (ad_offset > l_ad) { 1326 printf("LFile offset out of bounds (%d > %d)\n", 1327 ad_offset, l_ad); 1328 return (EINVAL); 1329 } 1330 if (udf_checktag(&up->u_fentry->tag, TAGID_EXTFENTRY) == 0) 1331 icb = GETICB(long_ad, xfentry, l_ea + ad_offset); 1332 else 1333 icb = GETICB(long_ad, fentry, l_ea + ad_offset); 1334 icblen = GETICBLEN(long_ad, icb); 1335 ad_num++; 1336 } while(offset >= icblen); 1337 1338 lsector = (offset >> ump->um_bshift) + 1339 letoh32(((struct long_ad *)(icb))->loc.lb_num); 1340 1341 *max_size = GETICBLEN(long_ad, icb); 1342 1343 break; 1344 case 3: 1345 /* 1346 * This type means that the file *data* is stored in the 1347 * allocation descriptor field of the file entry. 1348 */ 1349 *max_size = 0; 1350 *sector = up->u_ino + ump->um_start; 1351 1352 return (UDF_INVALID_BMAP); 1353 case 2: 1354 /* DirectCD does not use extended_ad's */ 1355 default: 1356 printf("Unsupported allocation descriptor %d\n", 1357 tag->flags & 0x7); 1358 return (ENODEV); 1359 } 1360 1361 *sector = lsector + ump->um_start; 1362 1363 /* 1364 * Check the sparing table. Each entry represents the beginning of 1365 * a packet. 1366 */ 1367 if (ump->um_stbl != NULL) { 1368 for (i = 0; i< ump->um_stbl_len; i++) { 1369 p_offset = 1370 lsector - letoh32(ump->um_stbl->entries[i].org); 1371 if ((p_offset < ump->um_psecs) && (p_offset >= 0)) { 1372 *sector = 1373 letoh32(ump->um_stbl->entries[i].map) + 1374 p_offset; 1375 break; 1376 } 1377 } 1378 } 1379 1380 return (0); 1381 } 1382