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