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