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