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