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