1 /*- 2 * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 /* udf_vnops.c */ 30 /* Take care of the vnode side of things */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/namei.h> 35 #include <sys/kernel.h> 36 #include <sys/malloc.h> 37 #include <sys/stat.h> 38 #include <sys/bio.h> 39 #include <sys/conf.h> 40 #include <sys/buf.h> 41 #include <sys/iconv.h> 42 #include <sys/mount.h> 43 #include <sys/vnode.h> 44 #include <sys/dirent.h> 45 #include <sys/queue.h> 46 #include <sys/unistd.h> 47 #include <sys/endian.h> 48 49 #include <vm/uma.h> 50 51 #include <fs/udf/ecma167-udf.h> 52 #include <fs/udf/osta.h> 53 #include <fs/udf/udf.h> 54 #include <fs/udf/udf_mount.h> 55 56 extern struct iconv_functions *udf_iconv; 57 58 static vop_access_t udf_access; 59 static vop_getattr_t udf_getattr; 60 static vop_open_t udf_open; 61 static vop_ioctl_t udf_ioctl; 62 static vop_pathconf_t udf_pathconf; 63 static vop_read_t udf_read; 64 static vop_readdir_t udf_readdir; 65 static vop_readlink_t udf_readlink; 66 static vop_strategy_t udf_strategy; 67 static vop_bmap_t udf_bmap; 68 static vop_cachedlookup_t udf_lookup; 69 static vop_reclaim_t udf_reclaim; 70 static int udf_readatoffset(struct udf_node *node, int *size, off_t offset, 71 struct buf **bp, uint8_t **data); 72 static int udf_bmap_internal(struct udf_node *node, off_t offset, 73 daddr_t *sector, uint32_t *max_size); 74 75 static struct vop_vector udf_vnodeops = { 76 .vop_default = &default_vnodeops, 77 78 .vop_access = udf_access, 79 .vop_bmap = udf_bmap, 80 .vop_cachedlookup = udf_lookup, 81 .vop_getattr = udf_getattr, 82 .vop_ioctl = udf_ioctl, 83 .vop_lookup = vfs_cache_lookup, 84 .vop_open = udf_open, 85 .vop_pathconf = udf_pathconf, 86 .vop_read = udf_read, 87 .vop_readdir = udf_readdir, 88 .vop_readlink = udf_readlink, 89 .vop_reclaim = udf_reclaim, 90 .vop_strategy = udf_strategy, 91 }; 92 93 MALLOC_DEFINE(M_UDFFID, "udf_fid", "UDF FileId structure"); 94 MALLOC_DEFINE(M_UDFDS, "udf_ds", "UDF Dirstream structure"); 95 96 #define UDF_INVALID_BMAP -1 97 98 int 99 udf_allocv(struct mount *mp, struct vnode **vpp, struct thread *td) 100 { 101 int error; 102 struct vnode *vp; 103 104 error = getnewvnode("udf", mp, &udf_vnodeops, &vp); 105 if (error) { 106 printf("udf_allocv: failed to allocate new vnode\n"); 107 return (error); 108 } 109 110 *vpp = vp; 111 return (0); 112 } 113 114 /* Convert file entry permission (5 bits per owner/group/user) to a mode_t */ 115 static mode_t 116 udf_permtomode(struct udf_node *node) 117 { 118 uint32_t perm; 119 uint16_t flags; 120 mode_t mode; 121 122 perm = le32toh(node->fentry->perm); 123 flags = le16toh(node->fentry->icbtag.flags); 124 125 mode = perm & UDF_FENTRY_PERM_USER_MASK; 126 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2); 127 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 128 mode |= ((flags & UDF_ICB_TAG_FLAGS_STICKY) << 4); 129 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETGID) << 6); 130 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETUID) << 8); 131 132 return (mode); 133 } 134 135 static int 136 udf_access(struct vop_access_args *a) 137 { 138 struct vnode *vp; 139 struct udf_node *node; 140 mode_t a_mode, mode; 141 142 vp = a->a_vp; 143 node = VTON(vp); 144 a_mode = a->a_mode; 145 146 if (a_mode & VWRITE) { 147 switch (vp->v_type) { 148 case VDIR: 149 case VLNK: 150 case VREG: 151 return (EROFS); 152 /* NOT REACHED */ 153 default: 154 break; 155 } 156 } 157 158 mode = udf_permtomode(node); 159 160 return (vaccess(vp->v_type, mode, node->fentry->uid, node->fentry->gid, 161 a_mode, a->a_cred, NULL)); 162 } 163 164 static int 165 udf_open(struct vop_open_args *ap) { 166 struct udf_node *np = VTON(ap->a_vp); 167 off_t fsize; 168 169 fsize = le64toh(np->fentry->inf_len); 170 vnode_create_vobject(ap->a_vp, fsize, ap->a_td); 171 return 0; 172 } 173 174 static int mon_lens[2][12] = { 175 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 176 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 177 }; 178 179 static int 180 udf_isaleapyear(int year) 181 { 182 int i; 183 184 i = (year % 4) ? 0 : 1; 185 i &= (year % 100) ? 1 : 0; 186 i |= (year % 400) ? 0 : 1; 187 188 return i; 189 } 190 191 /* 192 * XXX This is just a rough hack. Daylight savings isn't calculated and tv_nsec 193 * is ignored. 194 * Timezone calculation compliments of Julian Elischer <julian@elischer.org>. 195 */ 196 static void 197 udf_timetotimespec(struct timestamp *time, struct timespec *t) 198 { 199 int i, lpyear, daysinyear, year; 200 union { 201 uint16_t u_tz_offset; 202 int16_t s_tz_offset; 203 } tz; 204 205 t->tv_nsec = 0; 206 207 /* DirectCD seems to like using bogus year values */ 208 year = le16toh(time->year); 209 if (year < 1970) { 210 t->tv_sec = 0; 211 return; 212 } 213 214 /* Calculate the time and day */ 215 t->tv_sec = time->second; 216 t->tv_sec += time->minute * 60; 217 t->tv_sec += time->hour * 3600; 218 t->tv_sec += time->day * 3600 * 24; 219 220 /* Calculate the month */ 221 lpyear = udf_isaleapyear(year); 222 for (i = 1; i < time->month; i++) 223 t->tv_sec += mon_lens[lpyear][i] * 3600 * 24; 224 225 /* Speed up the calculation */ 226 if (year > 1979) 227 t->tv_sec += 315532800; 228 if (year > 1989) 229 t->tv_sec += 315619200; 230 if (year > 1999) 231 t->tv_sec += 315532800; 232 for (i = 2000; i < year; i++) { 233 daysinyear = udf_isaleapyear(i) + 365 ; 234 t->tv_sec += daysinyear * 3600 * 24; 235 } 236 237 /* 238 * Calculate the time zone. The timezone is 12 bit signed 2's 239 * complement, so we gotta do some extra magic to handle it right. 240 */ 241 tz.u_tz_offset = le16toh(time->type_tz); 242 tz.u_tz_offset &= 0x0fff; 243 if (tz.u_tz_offset & 0x0800) 244 tz.u_tz_offset |= 0xf000; /* extend the sign to 16 bits */ 245 if ((time->type_tz & 0x1000) && (tz.s_tz_offset != -2047)) 246 t->tv_sec -= tz.s_tz_offset * 60; 247 248 return; 249 } 250 251 static int 252 udf_getattr(struct vop_getattr_args *a) 253 { 254 struct vnode *vp; 255 struct udf_node *node; 256 struct vattr *vap; 257 struct file_entry *fentry; 258 struct timespec ts; 259 260 ts.tv_sec = 0; 261 262 vp = a->a_vp; 263 vap = a->a_vap; 264 node = VTON(vp); 265 fentry = node->fentry; 266 267 vap->va_fsid = dev2udev(node->udfmp->im_dev); 268 vap->va_fileid = node->hash_id; 269 vap->va_mode = udf_permtomode(node); 270 vap->va_nlink = le16toh(fentry->link_cnt); 271 /* 272 * XXX The spec says that -1 is valid for uid/gid and indicates an 273 * invalid uid/gid. How should this be represented? 274 */ 275 vap->va_uid = (le32toh(fentry->uid) == -1) ? 0 : le32toh(fentry->uid); 276 vap->va_gid = (le32toh(fentry->gid) == -1) ? 0 : le32toh(fentry->gid); 277 udf_timetotimespec(&fentry->atime, &vap->va_atime); 278 udf_timetotimespec(&fentry->mtime, &vap->va_mtime); 279 vap->va_ctime = vap->va_mtime; /* XXX Stored as an Extended Attribute */ 280 vap->va_rdev = 0; /* XXX */ 281 if (vp->v_type & VDIR) { 282 /* 283 * Directories that are recorded within their ICB will show 284 * as having 0 blocks recorded. Since tradition dictates 285 * that directories consume at least one logical block, 286 * make it appear so. 287 */ 288 if (fentry->logblks_rec != 0) { 289 vap->va_size = 290 le64toh(fentry->logblks_rec) * node->udfmp->bsize; 291 } else { 292 vap->va_size = node->udfmp->bsize; 293 } 294 } else { 295 vap->va_size = le64toh(fentry->inf_len); 296 } 297 vap->va_flags = 0; 298 vap->va_gen = 1; 299 vap->va_blocksize = node->udfmp->bsize; 300 vap->va_bytes = le64toh(fentry->inf_len); 301 vap->va_type = vp->v_type; 302 vap->va_filerev = 0; /* XXX */ 303 return (0); 304 } 305 306 /* 307 * File specific ioctls. 308 */ 309 static int 310 udf_ioctl(struct vop_ioctl_args *a) 311 { 312 printf("%s called\n", __func__); 313 return (ENOTTY); 314 } 315 316 /* 317 * I'm not sure that this has much value in a read-only filesystem, but 318 * cd9660 has it too. 319 */ 320 static int 321 udf_pathconf(struct vop_pathconf_args *a) 322 { 323 324 switch (a->a_name) { 325 case _PC_LINK_MAX: 326 *a->a_retval = 65535; 327 return (0); 328 case _PC_NAME_MAX: 329 *a->a_retval = NAME_MAX; 330 return (0); 331 case _PC_PATH_MAX: 332 *a->a_retval = PATH_MAX; 333 return (0); 334 case _PC_NO_TRUNC: 335 *a->a_retval = 1; 336 return (0); 337 default: 338 return (EINVAL); 339 } 340 } 341 342 static int 343 udf_read(struct vop_read_args *a) 344 { 345 struct vnode *vp = a->a_vp; 346 struct uio *uio = a->a_uio; 347 struct udf_node *node = VTON(vp); 348 struct buf *bp; 349 uint8_t *data; 350 off_t fsize, offset; 351 int error = 0; 352 int size; 353 354 if (uio->uio_offset < 0) 355 return (EINVAL); 356 357 fsize = le64toh(node->fentry->inf_len); 358 359 while (uio->uio_offset < fsize && uio->uio_resid > 0) { 360 offset = uio->uio_offset; 361 if (uio->uio_resid + offset <= fsize) 362 size = uio->uio_resid; 363 else 364 size = fsize - offset; 365 error = udf_readatoffset(node, &size, offset, &bp, &data); 366 if (error == 0) 367 error = uiomove(data, size, uio); 368 if (bp != NULL) 369 brelse(bp); 370 if (error) 371 break; 372 }; 373 374 return (error); 375 } 376 377 /* 378 * Call the OSTA routines to translate the name from a CS0 dstring to a 379 * 16-bit Unicode String. Hooks need to be placed in here to translate from 380 * Unicode to the encoding that the kernel/user expects. Return the length 381 * of the translated string. 382 */ 383 static int 384 udf_transname(char *cs0string, char *destname, int len, struct udf_mnt *udfmp) 385 { 386 unicode_t *transname; 387 char *unibuf, *unip; 388 int i, destlen; 389 ssize_t unilen = 0; 390 size_t destleft = MAXNAMLEN; 391 392 /* Convert 16-bit Unicode to destname */ 393 if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) { 394 /* allocate a buffer big enough to hold an 8->16 bit expansion */ 395 unibuf = uma_zalloc(udf_zone_trans, M_WAITOK); 396 unip = unibuf; 397 if ((unilen = (ssize_t)udf_UncompressUnicodeByte(len, cs0string, unibuf)) == -1) { 398 printf("udf: Unicode translation failed\n"); 399 uma_zfree(udf_zone_trans, unibuf); 400 return 0; 401 } 402 403 while (unilen > 0 && destleft > 0) { 404 udf_iconv->conv(udfmp->im_d2l, (const char **)&unibuf, 405 (size_t *)&unilen, (char **)&destname, &destleft); 406 /* Unconverted character found */ 407 if (unilen > 0 && destleft > 0) { 408 *destname++ = '?'; 409 destleft--; 410 unibuf += 2; 411 unilen -= 2; 412 } 413 } 414 uma_zfree(udf_zone_trans, unip); 415 *destname = '\0'; 416 destlen = MAXNAMLEN - (int)destleft; 417 } else { 418 /* allocate a buffer big enough to hold an 8->16 bit expansion */ 419 transname = uma_zalloc(udf_zone_trans, M_WAITOK); 420 421 if ((unilen = (ssize_t)udf_UncompressUnicode(len, cs0string, transname)) == -1) { 422 printf("udf: Unicode translation failed\n"); 423 uma_zfree(udf_zone_trans, transname); 424 return 0; 425 } 426 427 for (i = 0; i < unilen ; i++) { 428 if (transname[i] & 0xff00) { 429 destname[i] = '.'; /* Fudge the 16bit chars */ 430 } else { 431 destname[i] = transname[i] & 0xff; 432 } 433 } 434 uma_zfree(udf_zone_trans, transname); 435 destname[unilen] = 0; 436 destlen = (int)unilen; 437 } 438 439 return (destlen); 440 } 441 442 /* 443 * Compare a CS0 dstring with a name passed in from the VFS layer. Return 444 * 0 on a successful match, nonzero otherwise. Unicode work may need to be done 445 * here also. 446 */ 447 static int 448 udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct udf_mnt *udfmp) 449 { 450 char *transname; 451 int error = 0; 452 453 /* This is overkill, but not worth creating a new zone */ 454 transname = uma_zalloc(udf_zone_trans, M_WAITOK); 455 456 cs0len = udf_transname(cs0string, transname, cs0len, udfmp); 457 458 /* Easy check. If they aren't the same length, they aren't equal */ 459 if ((cs0len == 0) || (cs0len != cmplen)) 460 error = -1; 461 else 462 error = bcmp(transname, cmpname, cmplen); 463 464 uma_zfree(udf_zone_trans, transname); 465 return (error); 466 } 467 468 struct udf_uiodir { 469 struct dirent *dirent; 470 u_long *cookies; 471 int ncookies; 472 int acookies; 473 int eofflag; 474 }; 475 476 static int 477 udf_uiodir(struct udf_uiodir *uiodir, int de_size, struct uio *uio, long cookie) 478 { 479 if (uiodir->cookies != NULL) { 480 if (++uiodir->acookies > uiodir->ncookies) { 481 uiodir->eofflag = 0; 482 return (-1); 483 } 484 *uiodir->cookies++ = cookie; 485 } 486 487 if (uio->uio_resid < de_size) { 488 uiodir->eofflag = 0; 489 return (-1); 490 } 491 492 return (uiomove(uiodir->dirent, de_size, uio)); 493 } 494 495 static struct udf_dirstream * 496 udf_opendir(struct udf_node *node, int offset, int fsize, struct udf_mnt *udfmp) 497 { 498 struct udf_dirstream *ds; 499 500 ds = uma_zalloc(udf_zone_ds, M_WAITOK | M_ZERO); 501 502 ds->node = node; 503 ds->offset = offset; 504 ds->udfmp = udfmp; 505 ds->fsize = fsize; 506 507 return (ds); 508 } 509 510 static struct fileid_desc * 511 udf_getfid(struct udf_dirstream *ds) 512 { 513 struct fileid_desc *fid; 514 int error, frag_size = 0, total_fid_size; 515 516 /* End of directory? */ 517 if (ds->offset + ds->off >= ds->fsize) { 518 ds->error = 0; 519 return (NULL); 520 } 521 522 /* Grab the first extent of the directory */ 523 if (ds->off == 0) { 524 ds->size = 0; 525 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 526 &ds->bp, &ds->data); 527 if (error) { 528 ds->error = error; 529 if (ds->bp != NULL) 530 brelse(ds->bp); 531 return (NULL); 532 } 533 } 534 535 /* 536 * Clean up from a previous fragmented FID. 537 * XXX Is this the right place for this? 538 */ 539 if (ds->fid_fragment && ds->buf != NULL) { 540 ds->fid_fragment = 0; 541 FREE(ds->buf, M_UDFFID); 542 } 543 544 fid = (struct fileid_desc*)&ds->data[ds->off]; 545 546 /* 547 * Check to see if the fid is fragmented. The first test 548 * ensures that we don't wander off the end of the buffer 549 * looking for the l_iu and l_fi fields. 550 */ 551 if (ds->off + UDF_FID_SIZE > ds->size || 552 ds->off + le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE > ds->size){ 553 554 /* Copy what we have of the fid into a buffer */ 555 frag_size = ds->size - ds->off; 556 if (frag_size >= ds->udfmp->bsize) { 557 printf("udf: invalid FID fragment\n"); 558 ds->error = EINVAL; 559 return (NULL); 560 } 561 562 /* 563 * File ID descriptors can only be at most one 564 * logical sector in size. 565 */ 566 MALLOC(ds->buf, uint8_t*, ds->udfmp->bsize, M_UDFFID, 567 M_WAITOK | M_ZERO); 568 bcopy(fid, ds->buf, frag_size); 569 570 /* Reduce all of the casting magic */ 571 fid = (struct fileid_desc*)ds->buf; 572 573 if (ds->bp != NULL) 574 brelse(ds->bp); 575 576 /* Fetch the next allocation */ 577 ds->offset += ds->size; 578 ds->size = 0; 579 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 580 &ds->bp, &ds->data); 581 if (error) { 582 ds->error = error; 583 return (NULL); 584 } 585 586 /* 587 * If the fragment was so small that we didn't get 588 * the l_iu and l_fi fields, copy those in. 589 */ 590 if (frag_size < UDF_FID_SIZE) 591 bcopy(ds->data, &ds->buf[frag_size], 592 UDF_FID_SIZE - frag_size); 593 594 /* 595 * Now that we have enough of the fid to work with, 596 * copy in the rest of the fid from the new 597 * allocation. 598 */ 599 total_fid_size = UDF_FID_SIZE + le16toh(fid->l_iu) + fid->l_fi; 600 if (total_fid_size > ds->udfmp->bsize) { 601 printf("udf: invalid FID\n"); 602 ds->error = EIO; 603 return (NULL); 604 } 605 bcopy(ds->data, &ds->buf[frag_size], 606 total_fid_size - frag_size); 607 608 ds->fid_fragment = 1; 609 } else { 610 total_fid_size = le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE; 611 } 612 613 /* 614 * Update the offset. Align on a 4 byte boundary because the 615 * UDF spec says so. 616 */ 617 ds->this_off = ds->off; 618 if (!ds->fid_fragment) { 619 ds->off += (total_fid_size + 3) & ~0x03; 620 } else { 621 ds->off = (total_fid_size - frag_size + 3) & ~0x03; 622 } 623 624 return (fid); 625 } 626 627 static void 628 udf_closedir(struct udf_dirstream *ds) 629 { 630 631 if (ds->bp != NULL) 632 brelse(ds->bp); 633 634 if (ds->fid_fragment && ds->buf != NULL) 635 FREE(ds->buf, M_UDFFID); 636 637 uma_zfree(udf_zone_ds, ds); 638 } 639 640 static int 641 udf_readdir(struct vop_readdir_args *a) 642 { 643 struct vnode *vp; 644 struct uio *uio; 645 struct dirent dir; 646 struct udf_node *node; 647 struct udf_mnt *udfmp; 648 struct fileid_desc *fid; 649 struct udf_uiodir uiodir; 650 struct udf_dirstream *ds; 651 u_long *cookies = NULL; 652 int ncookies; 653 int error = 0; 654 655 vp = a->a_vp; 656 uio = a->a_uio; 657 node = VTON(vp); 658 udfmp = node->udfmp; 659 uiodir.eofflag = 1; 660 661 if (a->a_ncookies != NULL) { 662 /* 663 * Guess how many entries are needed. If we run out, this 664 * function will be called again and thing will pick up were 665 * it left off. 666 */ 667 ncookies = uio->uio_resid / 8; 668 MALLOC(cookies, u_long *, sizeof(u_long) * ncookies, 669 M_TEMP, M_WAITOK); 670 if (cookies == NULL) 671 return (ENOMEM); 672 uiodir.ncookies = ncookies; 673 uiodir.cookies = cookies; 674 uiodir.acookies = 0; 675 } else { 676 uiodir.cookies = NULL; 677 } 678 679 /* 680 * Iterate through the file id descriptors. Give the parent dir 681 * entry special attention. 682 */ 683 ds = udf_opendir(node, uio->uio_offset, le64toh(node->fentry->inf_len), 684 node->udfmp); 685 686 while ((fid = udf_getfid(ds)) != NULL) { 687 688 /* XXX Should we return an error on a bad fid? */ 689 if (udf_checktag(&fid->tag, TAGID_FID)) { 690 printf("Invalid FID tag\n"); 691 hexdump(fid, UDF_FID_SIZE, NULL, 0); 692 error = EIO; 693 break; 694 } 695 696 /* Is this a deleted file? */ 697 if (fid->file_char & UDF_FILE_CHAR_DEL) 698 continue; 699 700 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 701 /* Do up the '.' and '..' entries. Dummy values are 702 * used for the cookies since the offset here is 703 * usually zero, and NFS doesn't like that value 704 */ 705 dir.d_fileno = node->hash_id; 706 dir.d_type = DT_DIR; 707 dir.d_name[0] = '.'; 708 dir.d_name[1] = '\0'; 709 dir.d_namlen = 1; 710 dir.d_reclen = GENERIC_DIRSIZ(&dir); 711 uiodir.dirent = &dir; 712 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1); 713 if (error) 714 break; 715 716 dir.d_fileno = udf_getid(&fid->icb); 717 dir.d_type = DT_DIR; 718 dir.d_name[0] = '.'; 719 dir.d_name[1] = '.'; 720 dir.d_name[2] = '\0'; 721 dir.d_namlen = 2; 722 dir.d_reclen = GENERIC_DIRSIZ(&dir); 723 uiodir.dirent = &dir; 724 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2); 725 } else { 726 dir.d_namlen = udf_transname(&fid->data[fid->l_iu], 727 &dir.d_name[0], fid->l_fi, udfmp); 728 dir.d_fileno = udf_getid(&fid->icb); 729 dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ? 730 DT_DIR : DT_UNKNOWN; 731 dir.d_reclen = GENERIC_DIRSIZ(&dir); 732 uiodir.dirent = &dir; 733 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 734 ds->this_off); 735 } 736 if (error) { 737 printf("uiomove returned %d\n", error); 738 break; 739 } 740 741 } 742 743 /* tell the calling layer whether we need to be called again */ 744 *a->a_eofflag = uiodir.eofflag; 745 uio->uio_offset = ds->offset + ds->off; 746 747 if (!error) 748 error = ds->error; 749 750 udf_closedir(ds); 751 752 if (a->a_ncookies != NULL) { 753 if (error) 754 FREE(cookies, M_TEMP); 755 else { 756 *a->a_ncookies = uiodir.acookies; 757 *a->a_cookies = cookies; 758 } 759 } 760 761 return (error); 762 } 763 764 /* Are there any implementations out there that do soft-links? */ 765 static int 766 udf_readlink(struct vop_readlink_args *ap) 767 { 768 printf("%s called\n", __func__); 769 return (EOPNOTSUPP); 770 } 771 772 static int 773 udf_strategy(struct vop_strategy_args *a) 774 { 775 struct buf *bp; 776 struct vnode *vp; 777 struct udf_node *node; 778 int maxsize; 779 struct bufobj *bo; 780 781 bp = a->a_bp; 782 vp = a->a_vp; 783 node = VTON(vp); 784 785 /* cd9660 has this test reversed, but it seems more logical this way */ 786 if (bp->b_blkno != bp->b_lblkno) { 787 /* 788 * Files that are embedded in the fentry don't translate well 789 * to a block number. Reject. 790 */ 791 if (udf_bmap_internal(node, bp->b_lblkno * node->udfmp->bsize, 792 &bp->b_lblkno, &maxsize)) { 793 clrbuf(bp); 794 bp->b_blkno = -1; 795 } 796 } 797 if ((long)bp->b_blkno == -1) { 798 bufdone(bp); 799 return (0); 800 } 801 bo = node->udfmp->im_bo; 802 bp->b_iooffset = dbtob(bp->b_blkno); 803 BO_STRATEGY(bo, bp); 804 return (0); 805 } 806 807 static int 808 udf_bmap(struct vop_bmap_args *a) 809 { 810 struct udf_node *node; 811 uint32_t max_size; 812 daddr_t lsector; 813 int error; 814 815 node = VTON(a->a_vp); 816 817 if (a->a_bop != NULL) 818 *a->a_bop = &node->udfmp->im_devvp->v_bufobj; 819 if (a->a_bnp == NULL) 820 return (0); 821 if (a->a_runb) 822 *a->a_runb = 0; 823 824 error = udf_bmap_internal(node, a->a_bn * node->udfmp->bsize, &lsector, 825 &max_size); 826 if (error) 827 return (error); 828 829 /* Translate logical to physical sector number */ 830 *a->a_bnp = lsector << (node->udfmp->bshift - DEV_BSHIFT); 831 832 /* Punt on read-ahead for now */ 833 if (a->a_runp) 834 *a->a_runp = 0; 835 836 return (0); 837 } 838 839 /* 840 * The all powerful VOP_LOOKUP(). 841 */ 842 static int 843 udf_lookup(struct vop_cachedlookup_args *a) 844 { 845 struct vnode *dvp; 846 struct vnode *tdp = NULL; 847 struct vnode **vpp = a->a_vpp; 848 struct udf_node *node; 849 struct udf_mnt *udfmp; 850 struct fileid_desc *fid = NULL; 851 struct udf_dirstream *ds; 852 struct thread *td; 853 u_long nameiop; 854 u_long flags; 855 char *nameptr; 856 long namelen; 857 ino_t id = 0; 858 int offset, error = 0; 859 int numdirpasses, fsize; 860 861 dvp = a->a_dvp; 862 node = VTON(dvp); 863 udfmp = node->udfmp; 864 nameiop = a->a_cnp->cn_nameiop; 865 flags = a->a_cnp->cn_flags; 866 nameptr = a->a_cnp->cn_nameptr; 867 namelen = a->a_cnp->cn_namelen; 868 fsize = le64toh(node->fentry->inf_len); 869 td = a->a_cnp->cn_thread; 870 871 /* 872 * If this is a LOOKUP and we've already partially searched through 873 * the directory, pick up where we left off and flag that the 874 * directory may need to be searched twice. For a full description, 875 * see /sys/isofs/cd9660/cd9660_lookup.c:cd9660_lookup() 876 */ 877 if (nameiop != LOOKUP || node->diroff == 0 || node->diroff > fsize) { 878 offset = 0; 879 numdirpasses = 1; 880 } else { 881 offset = node->diroff; 882 numdirpasses = 2; 883 nchstats.ncs_2passes++; 884 } 885 886 lookloop: 887 ds = udf_opendir(node, offset, fsize, udfmp); 888 889 while ((fid = udf_getfid(ds)) != NULL) { 890 891 /* XXX Should we return an error on a bad fid? */ 892 if (udf_checktag(&fid->tag, TAGID_FID)) { 893 printf("udf_lookup: Invalid tag\n"); 894 error = EIO; 895 break; 896 } 897 898 /* Is this a deleted file? */ 899 if (fid->file_char & UDF_FILE_CHAR_DEL) 900 continue; 901 902 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 903 if (flags & ISDOTDOT) { 904 id = udf_getid(&fid->icb); 905 break; 906 } 907 } else { 908 if (!(udf_cmpname(&fid->data[fid->l_iu], 909 nameptr, fid->l_fi, namelen, udfmp))) { 910 id = udf_getid(&fid->icb); 911 break; 912 } 913 } 914 } 915 916 if (!error) 917 error = ds->error; 918 919 /* XXX Bail out here? */ 920 if (error) { 921 udf_closedir(ds); 922 return (error); 923 } 924 925 /* Did we have a match? */ 926 if (id) { 927 if (flags & ISDOTDOT) 928 VOP_UNLOCK(dvp, 0, a->a_cnp->cn_thread); 929 error = udf_vget(udfmp->im_mountp, id, LK_EXCLUSIVE, &tdp); 930 if (flags & ISDOTDOT) 931 vn_lock(dvp, LK_EXCLUSIVE|LK_RETRY, a->a_cnp->cn_thread); 932 if (!error) { 933 /* 934 * Remember where this entry was if it's the final 935 * component. 936 */ 937 if ((flags & ISLASTCN) && nameiop == LOOKUP) 938 node->diroff = ds->offset + ds->off; 939 if (numdirpasses == 2) 940 nchstats.ncs_pass2++; 941 *vpp = tdp; 942 /* Put this entry in the cache */ 943 if (flags & MAKEENTRY) 944 cache_enter(dvp, *vpp, a->a_cnp); 945 } 946 } else { 947 /* Name wasn't found on this pass. Do another pass? */ 948 if (numdirpasses == 2) { 949 numdirpasses--; 950 offset = 0; 951 udf_closedir(ds); 952 goto lookloop; 953 } 954 955 /* Enter name into cache as non-existant */ 956 if (flags & MAKEENTRY) 957 cache_enter(dvp, *vpp, a->a_cnp); 958 959 if ((flags & ISLASTCN) && 960 (nameiop == CREATE || nameiop == RENAME)) { 961 error = EROFS; 962 } else { 963 error = ENOENT; 964 } 965 } 966 967 udf_closedir(ds); 968 return (error); 969 } 970 971 static int 972 udf_reclaim(struct vop_reclaim_args *a) 973 { 974 struct vnode *vp; 975 struct udf_node *unode; 976 977 vp = a->a_vp; 978 unode = VTON(vp); 979 980 /* 981 * Destroy the vm object and flush associated pages. 982 */ 983 vnode_destroy_vobject(vp); 984 985 if (unode != NULL) { 986 vfs_hash_remove(vp); 987 988 if (unode->fentry != NULL) 989 FREE(unode->fentry, M_UDFFENTRY); 990 uma_zfree(udf_zone_node, unode); 991 vp->v_data = NULL; 992 } 993 994 return (0); 995 } 996 997 /* 998 * Read the block and then set the data pointer to correspond with the 999 * offset passed in. Only read in at most 'size' bytes, and then set 'size' 1000 * to the number of bytes pointed to. If 'size' is zero, try to read in a 1001 * whole extent. 1002 * 1003 * Note that *bp may be assigned error or not. 1004 * 1005 */ 1006 static int 1007 udf_readatoffset(struct udf_node *node, int *size, off_t offset, 1008 struct buf **bp, uint8_t **data) 1009 { 1010 struct udf_mnt *udfmp; 1011 struct file_entry *fentry = NULL; 1012 struct buf *bp1; 1013 uint32_t max_size; 1014 daddr_t sector; 1015 int error; 1016 1017 udfmp = node->udfmp; 1018 1019 *bp = NULL; 1020 error = udf_bmap_internal(node, offset, §or, &max_size); 1021 if (error == UDF_INVALID_BMAP) { 1022 /* 1023 * This error means that the file *data* is stored in the 1024 * allocation descriptor field of the file entry. 1025 */ 1026 fentry = node->fentry; 1027 *data = &fentry->data[le32toh(fentry->l_ea)]; 1028 *size = le32toh(fentry->l_ad); 1029 return (0); 1030 } else if (error != 0) { 1031 return (error); 1032 } 1033 1034 /* Adjust the size so that it is within range */ 1035 if (*size == 0 || *size > max_size) 1036 *size = max_size; 1037 *size = min(*size, MAXBSIZE); 1038 1039 if ((error = udf_readlblks(udfmp, sector, *size, bp))) { 1040 printf("warning: udf_readlblks returned error %d\n", error); 1041 /* note: *bp may be non-NULL */ 1042 return (error); 1043 } 1044 1045 bp1 = *bp; 1046 *data = (uint8_t *)&bp1->b_data[offset % udfmp->bsize]; 1047 return (0); 1048 } 1049 1050 /* 1051 * Translate a file offset into a logical block and then into a physical 1052 * block. 1053 */ 1054 static int 1055 udf_bmap_internal(struct udf_node *node, off_t offset, daddr_t *sector, 1056 uint32_t *max_size) 1057 { 1058 struct udf_mnt *udfmp; 1059 struct file_entry *fentry; 1060 void *icb; 1061 struct icb_tag *tag; 1062 uint32_t icblen = 0; 1063 daddr_t lsector; 1064 int ad_offset, ad_num = 0; 1065 int i, p_offset; 1066 1067 udfmp = node->udfmp; 1068 fentry = node->fentry; 1069 tag = &fentry->icbtag; 1070 1071 switch (le16toh(tag->strat_type)) { 1072 case 4: 1073 break; 1074 1075 case 4096: 1076 printf("Cannot deal with strategy4096 yet!\n"); 1077 return (ENODEV); 1078 1079 default: 1080 printf("Unknown strategy type %d\n", tag->strat_type); 1081 return (ENODEV); 1082 } 1083 1084 switch (le16toh(tag->flags) & 0x7) { 1085 case 0: 1086 /* 1087 * The allocation descriptor field is filled with short_ad's. 1088 * If the offset is beyond the current extent, look for the 1089 * next extent. 1090 */ 1091 do { 1092 offset -= icblen; 1093 ad_offset = sizeof(struct short_ad) * ad_num; 1094 if (ad_offset > le32toh(fentry->l_ad)) { 1095 printf("File offset out of bounds\n"); 1096 return (EINVAL); 1097 } 1098 icb = GETICB(short_ad, fentry, 1099 le32toh(fentry->l_ea) + ad_offset); 1100 icblen = GETICBLEN(short_ad, icb); 1101 ad_num++; 1102 } while(offset >= icblen); 1103 1104 lsector = (offset >> udfmp->bshift) + 1105 le32toh(((struct short_ad *)(icb))->pos); 1106 1107 *max_size = GETICBLEN(short_ad, icb); 1108 1109 break; 1110 case 1: 1111 /* 1112 * The allocation descriptor field is filled with long_ad's 1113 * If the offset is beyond the current extent, look for the 1114 * next extent. 1115 */ 1116 do { 1117 offset -= icblen; 1118 ad_offset = sizeof(struct long_ad) * ad_num; 1119 if (ad_offset > le32toh(fentry->l_ad)) { 1120 printf("File offset out of bounds\n"); 1121 return (EINVAL); 1122 } 1123 icb = GETICB(long_ad, fentry, 1124 le32toh(fentry->l_ea) + ad_offset); 1125 icblen = GETICBLEN(long_ad, icb); 1126 ad_num++; 1127 } while(offset >= icblen); 1128 1129 lsector = (offset >> udfmp->bshift) + 1130 le32toh(((struct long_ad *)(icb))->loc.lb_num); 1131 1132 *max_size = GETICBLEN(long_ad, icb); 1133 1134 break; 1135 case 3: 1136 /* 1137 * This type means that the file *data* is stored in the 1138 * allocation descriptor field of the file entry. 1139 */ 1140 *max_size = 0; 1141 *sector = node->hash_id + udfmp->part_start; 1142 1143 return (UDF_INVALID_BMAP); 1144 case 2: 1145 /* DirectCD does not use extended_ad's */ 1146 default: 1147 printf("Unsupported allocation descriptor %d\n", 1148 tag->flags & 0x7); 1149 return (ENODEV); 1150 } 1151 1152 *sector = lsector + udfmp->part_start; 1153 1154 /* 1155 * Check the sparing table. Each entry represents the beginning of 1156 * a packet. 1157 */ 1158 if (udfmp->s_table != NULL) { 1159 for (i = 0; i< udfmp->s_table_entries; i++) { 1160 p_offset = 1161 lsector - le32toh(udfmp->s_table->entries[i].org); 1162 if ((p_offset < udfmp->p_sectors) && (p_offset >= 0)) { 1163 *sector = 1164 le32toh(udfmp->s_table->entries[i].map) + 1165 p_offset; 1166 break; 1167 } 1168 } 1169 } 1170 1171 return (0); 1172 } 1173