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