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 56extern struct iconv_functions *udf_iconv; 57 58static vop_access_t udf_access; 59static vop_getattr_t udf_getattr; 60static vop_ioctl_t udf_ioctl; 61static vop_pathconf_t udf_pathconf; 62static vop_read_t udf_read; 63static vop_readdir_t udf_readdir; 64static vop_readlink_t udf_readlink; 65static vop_strategy_t udf_strategy; 66static vop_bmap_t udf_bmap; 67static vop_cachedlookup_t udf_lookup; 68static vop_reclaim_t udf_reclaim; 69static int udf_readatoffset(struct udf_node *node, int *size, off_t offset, 70 struct buf **bp, uint8_t **data); 71static int udf_bmap_internal(struct udf_node *node, off_t offset, 72 daddr_t *sector, uint32_t *max_size); 73 74static struct vop_vector udf_vnodeops = { 75 .vop_default = &default_vnodeops, 76 77 .vop_access = udf_access, 78 .vop_bmap = udf_bmap, 79 .vop_cachedlookup = udf_lookup, 80 .vop_getattr = udf_getattr, 81 .vop_ioctl = udf_ioctl, 82 .vop_lookup = vfs_cache_lookup, 83 .vop_pathconf = udf_pathconf, 84 .vop_read = udf_read, 85 .vop_readdir = udf_readdir, 86 .vop_readlink = udf_readlink, 87 .vop_reclaim = udf_reclaim, 88 .vop_strategy = udf_strategy, 89}; 90 91MALLOC_DEFINE(M_UDFFID, "UDF FID", "UDF FileId structure"); 92MALLOC_DEFINE(M_UDFDS, "UDF DS", "UDF Dirstream structure"); 93 94#define UDF_INVALID_BMAP -1 95 96int 97udf_allocv(struct mount *mp, struct vnode **vpp, struct thread *td) 98{ 99 int error; 100 struct vnode *vp; 101 102 error = getnewvnode("udf", mp, &udf_vnodeops, &vp); 103 if (error) { 104 printf("udf_allocv: failed to allocate new vnode\n"); 105 return (error); 106 } 107 108 *vpp = vp; 109 return (0); 110} 111 112/* Convert file entry permission (5 bits per owner/group/user) to a mode_t */ 113static mode_t 114udf_permtomode(struct udf_node *node) 115{ 116 uint32_t perm; 117 uint16_t flags; 118 mode_t mode; 119 120 perm = le32toh(node->fentry->perm); 121 flags = le16toh(node->fentry->icbtag.flags); 122 123 mode = perm & UDF_FENTRY_PERM_USER_MASK; 124 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2); 125 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 126 mode |= ((flags & UDF_ICB_TAG_FLAGS_STICKY) << 4); 127 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETGID) << 6); 128 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETUID) << 8); 129 130 return (mode); 131} 132 133static int 134udf_access(struct vop_access_args *a) 135{ 136 struct vnode *vp; 137 struct udf_node *node; 138 mode_t a_mode, mode; 139 140 vp = a->a_vp; 141 node = VTON(vp); 142 a_mode = a->a_mode; 143 144 if (a_mode & VWRITE) { 145 switch (vp->v_type) { 146 case VDIR: 147 case VLNK: 148 case VREG: 149 return (EROFS); 150 /* NOT REACHED */ 151 default: 152 break; 153 } 154 } 155 156 mode = udf_permtomode(node); 157 158 return (vaccess(vp->v_type, mode, node->fentry->uid, node->fentry->gid, 159 a_mode, a->a_cred, NULL)); 160} 161 162static int mon_lens[2][12] = { 163 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 164 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 165}; 166 167static int 168udf_isaleapyear(int year) 169{ 170 int i; 171 172 i = (year % 4) ? 0 : 1; 173 i &= (year % 100) ? 1 : 0; 174 i |= (year % 400) ? 0 : 1; 175 176 return i; 177} 178 179/* 180 * XXX This is just a rough hack. Daylight savings isn't calculated and tv_nsec 181 * is ignored. 182 * Timezone calculation compliments of Julian Elischer <julian@elischer.org>. 183 */ 184static void 185udf_timetotimespec(struct timestamp *time, struct timespec *t) 186{ 187 int i, lpyear, daysinyear, year; 188 union { 189 uint16_t u_tz_offset; 190 int16_t s_tz_offset; 191 } tz; 192 193 t->tv_nsec = 0; 194 195 /* DirectCD seems to like using bogus year values */ 196 year = le16toh(time->year); 197 if (year < 1970) { 198 t->tv_sec = 0; 199 return; 200 } 201 202 /* Calculate the time and day */ 203 t->tv_sec = time->second; 204 t->tv_sec += time->minute * 60; 205 t->tv_sec += time->hour * 3600; 206 t->tv_sec += time->day * 3600 * 24; 207 208 /* Calclulate the month */ 209 lpyear = udf_isaleapyear(year); 210 for (i = 1; i < time->month; i++) 211 t->tv_sec += mon_lens[lpyear][i] * 3600 * 24; 212 213 /* Speed up the calculation */ 214 if (year > 1979) 215 t->tv_sec += 315532800; 216 if (year > 1989) 217 t->tv_sec += 315619200; 218 if (year > 1999) 219 t->tv_sec += 315532800; 220 for (i = 2000; i < year; i++) { 221 daysinyear = udf_isaleapyear(i) + 365 ; 222 t->tv_sec += daysinyear * 3600 * 24; 223 } 224 225 /* 226 * Calculate the time zone. The timezone is 12 bit signed 2's 227 * compliment, so we gotta do some extra magic to handle it right. 228 */ 229 tz.u_tz_offset = le16toh(time->type_tz); 230 tz.u_tz_offset &= 0x0fff; 231 if (tz.u_tz_offset & 0x0800) 232 tz.u_tz_offset |= 0xf000; /* extend the sign to 16 bits */ 233 if ((time->type_tz & 0x1000) && (tz.s_tz_offset != -2047)) 234 t->tv_sec -= tz.s_tz_offset * 60; 235 236 return; 237} 238 239static int 240udf_getattr(struct vop_getattr_args *a) 241{ 242 struct vnode *vp; 243 struct udf_node *node; 244 struct vattr *vap; 245 struct file_entry *fentry; 246 struct timespec ts; 247 248 ts.tv_sec = 0; 249 250 vp = a->a_vp; 251 vap = a->a_vap; 252 node = VTON(vp); 253 fentry = node->fentry; 254 255 vap->va_fsid = dev2udev(node->udfmp->im_dev); 256 vap->va_fileid = node->hash_id; 257 vap->va_mode = udf_permtomode(node); 258 vap->va_nlink = le16toh(fentry->link_cnt); 259 /* 260 * XXX The spec says that -1 is valid for uid/gid and indicates an 261 * invalid uid/gid. How should this be represented? 262 */ 263 vap->va_uid = (le32toh(fentry->uid) == -1) ? 0 : le32toh(fentry->uid); 264 vap->va_gid = (le32toh(fentry->gid) == -1) ? 0 : le32toh(fentry->gid); 265 udf_timetotimespec(&fentry->atime, &vap->va_atime); 266 udf_timetotimespec(&fentry->mtime, &vap->va_mtime); 267 vap->va_ctime = vap->va_mtime; /* XXX Stored as an Extended Attribute */ 268 vap->va_rdev = 0; /* XXX */ 269 if (vp->v_type & VDIR) { 270 /* 271 * Directories that are recorded within their ICB will show 272 * as having 0 blocks recorded. Since tradition dictates 273 * that directories consume at least one logical block, 274 * make it appear so. 275 */ 276 if (fentry->logblks_rec != 0) { 277 vap->va_size = 278 le64toh(fentry->logblks_rec) * node->udfmp->bsize; 279 } else { 280 vap->va_size = node->udfmp->bsize; 281 } 282 } else { 283 vap->va_size = le64toh(fentry->inf_len); 284 } 285 vap->va_flags = 0; 286 vap->va_gen = 1; 287 vap->va_blocksize = node->udfmp->bsize; 288 vap->va_bytes = le64toh(fentry->inf_len); 289 vap->va_type = vp->v_type; 290 vap->va_filerev = 0; /* XXX */ 291 return (0); 292} 293 294/* 295 * File specific ioctls. 296 */ 297static int 298udf_ioctl(struct vop_ioctl_args *a) 299{ 300 printf("%s called\n", __func__); 301 return (ENOTTY); 302} 303 304/* 305 * I'm not sure that this has much value in a read-only filesystem, but 306 * cd9660 has it too. 307 */ 308static int 309udf_pathconf(struct vop_pathconf_args *a) 310{ 311 312 switch (a->a_name) { 313 case _PC_LINK_MAX: 314 *a->a_retval = 65535; 315 return (0); 316 case _PC_NAME_MAX: 317 *a->a_retval = NAME_MAX; 318 return (0); 319 case _PC_PATH_MAX: 320 *a->a_retval = PATH_MAX; 321 return (0); 322 case _PC_NO_TRUNC: 323 *a->a_retval = 1; 324 return (0); 325 default: 326 return (EINVAL); 327 } 328} 329 330static int 331udf_read(struct vop_read_args *a) 332{ 333 struct vnode *vp = a->a_vp; 334 struct uio *uio = a->a_uio; 335 struct udf_node *node = VTON(vp); 336 struct buf *bp; 337 uint8_t *data; 338 off_t fsize, offset; 339 int error = 0; 340 int size; 341 342 if (uio->uio_offset < 0) 343 return (EINVAL); 344 345 fsize = le64toh(node->fentry->inf_len); 346 347 while (uio->uio_offset < fsize && uio->uio_resid > 0) { 348 offset = uio->uio_offset; 349 if (uio->uio_resid + offset <= fsize) 350 size = uio->uio_resid; 351 else 352 size = fsize - offset; 353 error = udf_readatoffset(node, &size, offset, &bp, &data); 354 if (error == 0) 355 error = uiomove(data, size, uio); 356 if (bp != NULL) 357 brelse(bp); 358 if (error) 359 break; 360 }; 361 362 return (error); 363} 364 365/* 366 * Call the OSTA routines to translate the name from a CS0 dstring to a 367 * 16-bit Unicode String. Hooks need to be placed in here to translate from 368 * Unicode to the encoding that the kernel/user expects. Return the length 369 * of the translated string. 370 */ 371static int 372udf_transname(char *cs0string, char *destname, int len, struct udf_mnt *udfmp) 373{ 374 unicode_t *transname; 375 char *unibuf, *unip; 376 int i, unilen = 0, destlen; 377 size_t destleft = MAXNAMLEN; 378 379 /* Convert 16-bit Unicode to destname */ 380 if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) { 381 /* allocate a buffer big enough to hold an 8->16 bit expansion */ 382 unibuf = uma_zalloc(udf_zone_trans, M_WAITOK); 383 unip = unibuf; 384 if ((unilen = udf_UncompressUnicodeByte(len, cs0string, unibuf)) == -1) { 385 printf("udf: Unicode translation failed\n"); 386 uma_zfree(udf_zone_trans, unibuf); 387 return 0; 388 } 389 390 while (unilen > 0 && destleft > 0) { 391 udf_iconv->conv(udfmp->im_d2l, (const char **)&unibuf, 392 (size_t *)&unilen, (char **)&destname, &destleft); 393 /* Unconverted character found */ 394 if (unilen > 0 && destleft > 0) { 395 *destname++ = '?'; 396 destleft--; 397 unibuf += 2; 398 unilen -= 2; 399 } 400 } 401 uma_zfree(udf_zone_trans, unip); 402 *destname = '\0'; 403 destlen = MAXNAMLEN - (int)destleft; 404 } else { 405 /* allocate a buffer big enough to hold an 8->16 bit expansion */ 406 transname = uma_zalloc(udf_zone_trans, M_WAITOK); 407 408 if ((unilen = udf_UncompressUnicode(len, cs0string, transname)) == -1) { 409 printf("udf: Unicode translation failed\n"); 410 uma_zfree(udf_zone_trans, transname); 411 return 0; 412 } 413 414 for (i = 0; i < unilen ; i++) { 415 if (transname[i] & 0xff00) { 416 destname[i] = '.'; /* Fudge the 16bit chars */ 417 } else { 418 destname[i] = transname[i] & 0xff; 419 } 420 } 421 uma_zfree(udf_zone_trans, transname); 422 destname[unilen] = 0; 423 destlen = unilen; 424 } 425 426 return (destlen); 427} 428 429/* 430 * Compare a CS0 dstring with a name passed in from the VFS layer. Return 431 * 0 on a successful match, nonzero therwise. Unicode work may need to be done 432 * here also. 433 */ 434static int 435udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct udf_mnt *udfmp) 436{ 437 char *transname; 438 int error = 0; 439 440 /* This is overkill, but not worth creating a new zone */ 441 transname = uma_zalloc(udf_zone_trans, M_WAITOK); 442 443 cs0len = udf_transname(cs0string, transname, cs0len, udfmp); 444 445 /* Easy check. If they aren't the same length, they aren't equal */ 446 if ((cs0len == 0) || (cs0len != cmplen)) 447 error = -1; 448 else 449 error = bcmp(transname, cmpname, cmplen); 450 451 uma_zfree(udf_zone_trans, transname); 452 return (error); 453} 454 455struct udf_uiodir { 456 struct dirent *dirent; 457 u_long *cookies; 458 int ncookies; 459 int acookies; 460 int eofflag; 461}; 462 463static int 464udf_uiodir(struct udf_uiodir *uiodir, int de_size, struct uio *uio, long cookie) 465{ 466 if (uiodir->cookies != NULL) { 467 if (++uiodir->acookies > uiodir->ncookies) { 468 uiodir->eofflag = 0; 469 return (-1); 470 } 471 *uiodir->cookies++ = cookie; 472 } 473 474 if (uio->uio_resid < de_size) { 475 uiodir->eofflag = 0; 476 return (-1); 477 } 478 479 return (uiomove(uiodir->dirent, de_size, uio)); 480} 481 482static struct udf_dirstream * 483udf_opendir(struct udf_node *node, int offset, int fsize, struct udf_mnt *udfmp) 484{ 485 struct udf_dirstream *ds; 486 487 ds = uma_zalloc(udf_zone_ds, M_WAITOK | M_ZERO); 488 489 ds->node = node; 490 ds->offset = offset; 491 ds->udfmp = udfmp; 492 ds->fsize = fsize; 493 494 return (ds); 495} 496 497static struct fileid_desc * 498udf_getfid(struct udf_dirstream *ds) 499{ 500 struct fileid_desc *fid; 501 int error, frag_size = 0, total_fid_size; 502 503 /* End of directory? */ 504 if (ds->offset + ds->off >= ds->fsize) { 505 ds->error = 0; 506 return (NULL); 507 } 508 509 /* Grab the first extent of the directory */ 510 if (ds->off == 0) { 511 ds->size = 0; 512 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 513 &ds->bp, &ds->data); 514 if (error) { 515 ds->error = error; 516 if (ds->bp != NULL) 517 brelse(ds->bp); 518 return (NULL); 519 } 520 } 521 522 /* 523 * Clean up from a previous fragmented FID. 524 * XXX Is this the right place for this? 525 */ 526 if (ds->fid_fragment && ds->buf != NULL) { 527 ds->fid_fragment = 0; 528 FREE(ds->buf, M_UDFFID); 529 } 530 531 fid = (struct fileid_desc*)&ds->data[ds->off]; 532 533 /* 534 * Check to see if the fid is fragmented. The first test 535 * ensures that we don't wander off the end of the buffer 536 * looking for the l_iu and l_fi fields. 537 */ 538 if (ds->off + UDF_FID_SIZE > ds->size || 539 ds->off + le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE > ds->size){ 540 541 /* Copy what we have of the fid into a buffer */ 542 frag_size = ds->size - ds->off; 543 if (frag_size >= ds->udfmp->bsize) { 544 printf("udf: invalid FID fragment\n"); 545 ds->error = EINVAL; 546 return (NULL); 547 } 548 549 /* 550 * File ID descriptors can only be at most one 551 * logical sector in size. 552 */ 553 MALLOC(ds->buf, uint8_t*, ds->udfmp->bsize, M_UDFFID, 554 M_WAITOK | M_ZERO); 555 bcopy(fid, ds->buf, frag_size); 556 557 /* Reduce all of the casting magic */ 558 fid = (struct fileid_desc*)ds->buf; 559 560 if (ds->bp != NULL) 561 brelse(ds->bp); 562 563 /* Fetch the next allocation */ 564 ds->offset += ds->size; 565 ds->size = 0; 566 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 567 &ds->bp, &ds->data); 568 if (error) { 569 ds->error = error; 570 return (NULL); 571 } 572 573 /* 574 * If the fragment was so small that we didn't get 575 * the l_iu and l_fi fields, copy those in. 576 */ 577 if (frag_size < UDF_FID_SIZE) 578 bcopy(ds->data, &ds->buf[frag_size], 579 UDF_FID_SIZE - frag_size); 580 581 /* 582 * Now that we have enough of the fid to work with, 583 * copy in the rest of the fid from the new 584 * allocation. 585 */ 586 total_fid_size = UDF_FID_SIZE + le16toh(fid->l_iu) + fid->l_fi; 587 if (total_fid_size > ds->udfmp->bsize) { 588 printf("udf: invalid FID\n"); 589 ds->error = EIO; 590 return (NULL); 591 } 592 bcopy(ds->data, &ds->buf[frag_size], 593 total_fid_size - frag_size); 594 595 ds->fid_fragment = 1; 596 } else { 597 total_fid_size = le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE; 598 } 599 600 /* 601 * Update the offset. Align on a 4 byte boundary because the 602 * UDF spec says so. 603 */ 604 ds->this_off = ds->off; 605 if (!ds->fid_fragment) { 606 ds->off += (total_fid_size + 3) & ~0x03; 607 } else { 608 ds->off = (total_fid_size - frag_size + 3) & ~0x03; 609 } 610 611 return (fid); 612} 613 614static void 615udf_closedir(struct udf_dirstream *ds) 616{ 617 618 if (ds->bp != NULL) 619 brelse(ds->bp); 620 621 if (ds->fid_fragment && ds->buf != NULL) 622 FREE(ds->buf, M_UDFFID); 623 624 uma_zfree(udf_zone_ds, ds); 625} 626 627static int 628udf_readdir(struct vop_readdir_args *a) 629{ 630 struct vnode *vp; 631 struct uio *uio; 632 struct dirent dir; 633 struct udf_node *node; 634 struct udf_mnt *udfmp; 635 struct fileid_desc *fid; 636 struct udf_uiodir uiodir; 637 struct udf_dirstream *ds; 638 u_long *cookies = NULL; 639 int ncookies; 640 int error = 0; 641 642 vp = a->a_vp; 643 uio = a->a_uio; 644 node = VTON(vp); 645 udfmp = node->udfmp; 646 uiodir.eofflag = 1; 647 648 if (a->a_ncookies != NULL) { 649 /* 650 * Guess how many entries are needed. If we run out, this 651 * function will be called again and thing will pick up were 652 * it left off. 653 */ 654 ncookies = uio->uio_resid / 8; 655 MALLOC(cookies, u_long *, sizeof(u_long) * ncookies, 656 M_TEMP, M_WAITOK); 657 if (cookies == NULL) 658 return (ENOMEM); 659 uiodir.ncookies = ncookies; 660 uiodir.cookies = cookies; 661 uiodir.acookies = 0; 662 } else { 663 uiodir.cookies = NULL; 664 } 665 666 /* 667 * Iterate through the file id descriptors. Give the parent dir 668 * entry special attention. 669 */ 670 ds = udf_opendir(node, uio->uio_offset, le64toh(node->fentry->inf_len), 671 node->udfmp); 672 673 while ((fid = udf_getfid(ds)) != NULL) { 674 675 /* XXX Should we return an error on a bad fid? */ 676 if (udf_checktag(&fid->tag, TAGID_FID)) { 677 printf("Invalid FID tag\n"); 678 hexdump(fid, UDF_FID_SIZE, NULL, 0); 679 error = EIO; 680 break; 681 } 682 683 /* Is this a deleted file? */ 684 if (fid->file_char & UDF_FILE_CHAR_DEL) 685 continue; 686 687 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 688 /* Do up the '.' and '..' entries. Dummy values are 689 * used for the cookies since the offset here is 690 * usually zero, and NFS doesn't like that value 691 */ 692 dir.d_fileno = node->hash_id; 693 dir.d_type = DT_DIR; 694 dir.d_name[0] = '.'; 695 dir.d_name[1] = '\0'; 696 dir.d_namlen = 1; 697 dir.d_reclen = GENERIC_DIRSIZ(&dir); 698 uiodir.dirent = &dir; 699 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1); 700 if (error) 701 break; 702 703 dir.d_fileno = udf_getid(&fid->icb); 704 dir.d_type = DT_DIR; 705 dir.d_name[0] = '.'; 706 dir.d_name[1] = '.'; 707 dir.d_name[2] = '\0'; 708 dir.d_namlen = 2; 709 dir.d_reclen = GENERIC_DIRSIZ(&dir); 710 uiodir.dirent = &dir; 711 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2); 712 } else { 713 dir.d_namlen = udf_transname(&fid->data[fid->l_iu], 714 &dir.d_name[0], fid->l_fi, udfmp); 715 dir.d_fileno = udf_getid(&fid->icb); 716 dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ? 717 DT_DIR : DT_UNKNOWN; 718 dir.d_reclen = GENERIC_DIRSIZ(&dir); 719 uiodir.dirent = &dir; 720 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 721 ds->this_off); 722 } 723 if (error) { 724 printf("uiomove returned %d\n", error); 725 break; 726 } 727 728 } 729 730 /* tell the calling layer whether we need to be called again */ 731 *a->a_eofflag = uiodir.eofflag; 732 uio->uio_offset = ds->offset + ds->off; 733 734 if (!error) 735 error = ds->error; 736 737 udf_closedir(ds); 738 739 if (a->a_ncookies != NULL) { 740 if (error) 741 FREE(cookies, M_TEMP); 742 else { 743 *a->a_ncookies = uiodir.acookies; 744 *a->a_cookies = cookies; 745 } 746 } 747 748 return (error); 749} 750 751/* Are there any implementations out there that do soft-links? */ 752static int 753udf_readlink(struct vop_readlink_args *ap) 754{ 755 printf("%s called\n", __func__); 756 return (EOPNOTSUPP); 757} 758 759static int 760udf_strategy(struct vop_strategy_args *a) 761{ 762 struct buf *bp; 763 struct vnode *vp; 764 struct udf_node *node; 765 int maxsize; 766 struct bufobj *bo; 767 768 bp = a->a_bp; 769 vp = a->a_vp; 770 node = VTON(vp); 771 772 /* cd9660 has this test reversed, but it seems more logical this way */ 773 if (bp->b_blkno != bp->b_lblkno) { 774 /* 775 * Files that are embedded in the fentry don't translate well 776 * to a block number. Reject. 777 */ 778 if (udf_bmap_internal(node, bp->b_lblkno * node->udfmp->bsize, 779 &bp->b_lblkno, &maxsize)) { 780 clrbuf(bp); 781 bp->b_blkno = -1; 782 } 783 } 784 if ((long)bp->b_blkno == -1) { 785 bufdone(bp); 786 return (0); 787 } 788 bo = node->udfmp->im_bo; 789 bp->b_iooffset = dbtob(bp->b_blkno); 790 BO_STRATEGY(bo, bp); 791 return (0); 792} 793 794static int 795udf_bmap(struct vop_bmap_args *a) 796{ 797 struct udf_node *node; 798 uint32_t max_size; 799 daddr_t lsector; 800 int error; 801 802 node = VTON(a->a_vp); 803 804 if (a->a_bop != NULL) 805 *a->a_bop = &node->udfmp->im_devvp->v_bufobj; 806 if (a->a_bnp == NULL) 807 return (0); 808 if (a->a_runb) 809 *a->a_runb = 0; 810 811 error = udf_bmap_internal(node, a->a_bn * node->udfmp->bsize, &lsector, 812 &max_size); 813 if (error) 814 return (error); 815 816 /* Translate logical to physical sector number */ 817 *a->a_bnp = lsector << (node->udfmp->bshift - DEV_BSHIFT); 818 819 /* Punt on read-ahead for now */ 820 if (a->a_runp) 821 *a->a_runp = 0; 822 823 return (0); 824} 825 826/* 827 * The all powerful VOP_LOOKUP(). 828 */ 829static int 830udf_lookup(struct vop_cachedlookup_args *a) 831{ 832 struct vnode *dvp; 833 struct vnode *tdp = NULL; 834 struct vnode **vpp = a->a_vpp; 835 struct udf_node *node; 836 struct udf_mnt *udfmp; 837 struct fileid_desc *fid = NULL; 838 struct udf_dirstream *ds; 839 struct thread *td; 840 u_long nameiop; 841 u_long flags; 842 char *nameptr; 843 long namelen; 844 ino_t id = 0; 845 int offset, error = 0; 846 int numdirpasses, fsize; 847 848 dvp = a->a_dvp; 849 node = VTON(dvp); 850 udfmp = node->udfmp; 851 nameiop = a->a_cnp->cn_nameiop; 852 flags = a->a_cnp->cn_flags; 853 nameptr = a->a_cnp->cn_nameptr; 854 namelen = a->a_cnp->cn_namelen; 855 fsize = le64toh(node->fentry->inf_len); 856 td = a->a_cnp->cn_thread; 857 858 /* 859 * If this is a LOOKUP and we've already partially searched through 860 * the directory, pick up where we left off and flag that the 861 * directory may need to be searched twice. For a full description, 862 * see /sys/isofs/cd9660/cd9660_lookup.c:cd9660_lookup() 863 */ 864 if (nameiop != LOOKUP || node->diroff == 0 || node->diroff > fsize) { 865 offset = 0; 866 numdirpasses = 1; 867 } else { 868 offset = node->diroff; 869 numdirpasses = 2; 870 nchstats.ncs_2passes++; 871 } 872 873lookloop: 874 ds = udf_opendir(node, offset, fsize, udfmp); 875 876 while ((fid = udf_getfid(ds)) != NULL) { 877 878 /* XXX Should we return an error on a bad fid? */ 879 if (udf_checktag(&fid->tag, TAGID_FID)) { 880 printf("udf_lookup: Invalid tag\n"); 881 error = EIO; 882 break; 883 } 884 885 /* Is this a deleted file? */ 886 if (fid->file_char & UDF_FILE_CHAR_DEL) 887 continue; 888 889 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 890 if (flags & ISDOTDOT) { 891 id = udf_getid(&fid->icb); 892 break; 893 } 894 } else { 895 if (!(udf_cmpname(&fid->data[fid->l_iu], 896 nameptr, fid->l_fi, namelen, udfmp))) { 897 id = udf_getid(&fid->icb); 898 break; 899 } 900 } 901 } 902 903 if (!error) 904 error = ds->error; 905 906 /* XXX Bail out here? */ 907 if (error) { 908 udf_closedir(ds); 909 return (error); 910 } 911 912 /* Did we have a match? */ 913 if (id) { 914 if (flags & ISDOTDOT) 915 VOP_UNLOCK(dvp, 0, a->a_cnp->cn_thread); 916 error = udf_vget(udfmp->im_mountp, id, LK_EXCLUSIVE, &tdp);
| 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 56extern struct iconv_functions *udf_iconv; 57 58static vop_access_t udf_access; 59static vop_getattr_t udf_getattr; 60static vop_ioctl_t udf_ioctl; 61static vop_pathconf_t udf_pathconf; 62static vop_read_t udf_read; 63static vop_readdir_t udf_readdir; 64static vop_readlink_t udf_readlink; 65static vop_strategy_t udf_strategy; 66static vop_bmap_t udf_bmap; 67static vop_cachedlookup_t udf_lookup; 68static vop_reclaim_t udf_reclaim; 69static int udf_readatoffset(struct udf_node *node, int *size, off_t offset, 70 struct buf **bp, uint8_t **data); 71static int udf_bmap_internal(struct udf_node *node, off_t offset, 72 daddr_t *sector, uint32_t *max_size); 73 74static struct vop_vector udf_vnodeops = { 75 .vop_default = &default_vnodeops, 76 77 .vop_access = udf_access, 78 .vop_bmap = udf_bmap, 79 .vop_cachedlookup = udf_lookup, 80 .vop_getattr = udf_getattr, 81 .vop_ioctl = udf_ioctl, 82 .vop_lookup = vfs_cache_lookup, 83 .vop_pathconf = udf_pathconf, 84 .vop_read = udf_read, 85 .vop_readdir = udf_readdir, 86 .vop_readlink = udf_readlink, 87 .vop_reclaim = udf_reclaim, 88 .vop_strategy = udf_strategy, 89}; 90 91MALLOC_DEFINE(M_UDFFID, "UDF FID", "UDF FileId structure"); 92MALLOC_DEFINE(M_UDFDS, "UDF DS", "UDF Dirstream structure"); 93 94#define UDF_INVALID_BMAP -1 95 96int 97udf_allocv(struct mount *mp, struct vnode **vpp, struct thread *td) 98{ 99 int error; 100 struct vnode *vp; 101 102 error = getnewvnode("udf", mp, &udf_vnodeops, &vp); 103 if (error) { 104 printf("udf_allocv: failed to allocate new vnode\n"); 105 return (error); 106 } 107 108 *vpp = vp; 109 return (0); 110} 111 112/* Convert file entry permission (5 bits per owner/group/user) to a mode_t */ 113static mode_t 114udf_permtomode(struct udf_node *node) 115{ 116 uint32_t perm; 117 uint16_t flags; 118 mode_t mode; 119 120 perm = le32toh(node->fentry->perm); 121 flags = le16toh(node->fentry->icbtag.flags); 122 123 mode = perm & UDF_FENTRY_PERM_USER_MASK; 124 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2); 125 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 126 mode |= ((flags & UDF_ICB_TAG_FLAGS_STICKY) << 4); 127 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETGID) << 6); 128 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETUID) << 8); 129 130 return (mode); 131} 132 133static int 134udf_access(struct vop_access_args *a) 135{ 136 struct vnode *vp; 137 struct udf_node *node; 138 mode_t a_mode, mode; 139 140 vp = a->a_vp; 141 node = VTON(vp); 142 a_mode = a->a_mode; 143 144 if (a_mode & VWRITE) { 145 switch (vp->v_type) { 146 case VDIR: 147 case VLNK: 148 case VREG: 149 return (EROFS); 150 /* NOT REACHED */ 151 default: 152 break; 153 } 154 } 155 156 mode = udf_permtomode(node); 157 158 return (vaccess(vp->v_type, mode, node->fentry->uid, node->fentry->gid, 159 a_mode, a->a_cred, NULL)); 160} 161 162static int mon_lens[2][12] = { 163 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 164 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 165}; 166 167static int 168udf_isaleapyear(int year) 169{ 170 int i; 171 172 i = (year % 4) ? 0 : 1; 173 i &= (year % 100) ? 1 : 0; 174 i |= (year % 400) ? 0 : 1; 175 176 return i; 177} 178 179/* 180 * XXX This is just a rough hack. Daylight savings isn't calculated and tv_nsec 181 * is ignored. 182 * Timezone calculation compliments of Julian Elischer <julian@elischer.org>. 183 */ 184static void 185udf_timetotimespec(struct timestamp *time, struct timespec *t) 186{ 187 int i, lpyear, daysinyear, year; 188 union { 189 uint16_t u_tz_offset; 190 int16_t s_tz_offset; 191 } tz; 192 193 t->tv_nsec = 0; 194 195 /* DirectCD seems to like using bogus year values */ 196 year = le16toh(time->year); 197 if (year < 1970) { 198 t->tv_sec = 0; 199 return; 200 } 201 202 /* Calculate the time and day */ 203 t->tv_sec = time->second; 204 t->tv_sec += time->minute * 60; 205 t->tv_sec += time->hour * 3600; 206 t->tv_sec += time->day * 3600 * 24; 207 208 /* Calclulate the month */ 209 lpyear = udf_isaleapyear(year); 210 for (i = 1; i < time->month; i++) 211 t->tv_sec += mon_lens[lpyear][i] * 3600 * 24; 212 213 /* Speed up the calculation */ 214 if (year > 1979) 215 t->tv_sec += 315532800; 216 if (year > 1989) 217 t->tv_sec += 315619200; 218 if (year > 1999) 219 t->tv_sec += 315532800; 220 for (i = 2000; i < year; i++) { 221 daysinyear = udf_isaleapyear(i) + 365 ; 222 t->tv_sec += daysinyear * 3600 * 24; 223 } 224 225 /* 226 * Calculate the time zone. The timezone is 12 bit signed 2's 227 * compliment, so we gotta do some extra magic to handle it right. 228 */ 229 tz.u_tz_offset = le16toh(time->type_tz); 230 tz.u_tz_offset &= 0x0fff; 231 if (tz.u_tz_offset & 0x0800) 232 tz.u_tz_offset |= 0xf000; /* extend the sign to 16 bits */ 233 if ((time->type_tz & 0x1000) && (tz.s_tz_offset != -2047)) 234 t->tv_sec -= tz.s_tz_offset * 60; 235 236 return; 237} 238 239static int 240udf_getattr(struct vop_getattr_args *a) 241{ 242 struct vnode *vp; 243 struct udf_node *node; 244 struct vattr *vap; 245 struct file_entry *fentry; 246 struct timespec ts; 247 248 ts.tv_sec = 0; 249 250 vp = a->a_vp; 251 vap = a->a_vap; 252 node = VTON(vp); 253 fentry = node->fentry; 254 255 vap->va_fsid = dev2udev(node->udfmp->im_dev); 256 vap->va_fileid = node->hash_id; 257 vap->va_mode = udf_permtomode(node); 258 vap->va_nlink = le16toh(fentry->link_cnt); 259 /* 260 * XXX The spec says that -1 is valid for uid/gid and indicates an 261 * invalid uid/gid. How should this be represented? 262 */ 263 vap->va_uid = (le32toh(fentry->uid) == -1) ? 0 : le32toh(fentry->uid); 264 vap->va_gid = (le32toh(fentry->gid) == -1) ? 0 : le32toh(fentry->gid); 265 udf_timetotimespec(&fentry->atime, &vap->va_atime); 266 udf_timetotimespec(&fentry->mtime, &vap->va_mtime); 267 vap->va_ctime = vap->va_mtime; /* XXX Stored as an Extended Attribute */ 268 vap->va_rdev = 0; /* XXX */ 269 if (vp->v_type & VDIR) { 270 /* 271 * Directories that are recorded within their ICB will show 272 * as having 0 blocks recorded. Since tradition dictates 273 * that directories consume at least one logical block, 274 * make it appear so. 275 */ 276 if (fentry->logblks_rec != 0) { 277 vap->va_size = 278 le64toh(fentry->logblks_rec) * node->udfmp->bsize; 279 } else { 280 vap->va_size = node->udfmp->bsize; 281 } 282 } else { 283 vap->va_size = le64toh(fentry->inf_len); 284 } 285 vap->va_flags = 0; 286 vap->va_gen = 1; 287 vap->va_blocksize = node->udfmp->bsize; 288 vap->va_bytes = le64toh(fentry->inf_len); 289 vap->va_type = vp->v_type; 290 vap->va_filerev = 0; /* XXX */ 291 return (0); 292} 293 294/* 295 * File specific ioctls. 296 */ 297static int 298udf_ioctl(struct vop_ioctl_args *a) 299{ 300 printf("%s called\n", __func__); 301 return (ENOTTY); 302} 303 304/* 305 * I'm not sure that this has much value in a read-only filesystem, but 306 * cd9660 has it too. 307 */ 308static int 309udf_pathconf(struct vop_pathconf_args *a) 310{ 311 312 switch (a->a_name) { 313 case _PC_LINK_MAX: 314 *a->a_retval = 65535; 315 return (0); 316 case _PC_NAME_MAX: 317 *a->a_retval = NAME_MAX; 318 return (0); 319 case _PC_PATH_MAX: 320 *a->a_retval = PATH_MAX; 321 return (0); 322 case _PC_NO_TRUNC: 323 *a->a_retval = 1; 324 return (0); 325 default: 326 return (EINVAL); 327 } 328} 329 330static int 331udf_read(struct vop_read_args *a) 332{ 333 struct vnode *vp = a->a_vp; 334 struct uio *uio = a->a_uio; 335 struct udf_node *node = VTON(vp); 336 struct buf *bp; 337 uint8_t *data; 338 off_t fsize, offset; 339 int error = 0; 340 int size; 341 342 if (uio->uio_offset < 0) 343 return (EINVAL); 344 345 fsize = le64toh(node->fentry->inf_len); 346 347 while (uio->uio_offset < fsize && uio->uio_resid > 0) { 348 offset = uio->uio_offset; 349 if (uio->uio_resid + offset <= fsize) 350 size = uio->uio_resid; 351 else 352 size = fsize - offset; 353 error = udf_readatoffset(node, &size, offset, &bp, &data); 354 if (error == 0) 355 error = uiomove(data, size, uio); 356 if (bp != NULL) 357 brelse(bp); 358 if (error) 359 break; 360 }; 361 362 return (error); 363} 364 365/* 366 * Call the OSTA routines to translate the name from a CS0 dstring to a 367 * 16-bit Unicode String. Hooks need to be placed in here to translate from 368 * Unicode to the encoding that the kernel/user expects. Return the length 369 * of the translated string. 370 */ 371static int 372udf_transname(char *cs0string, char *destname, int len, struct udf_mnt *udfmp) 373{ 374 unicode_t *transname; 375 char *unibuf, *unip; 376 int i, unilen = 0, destlen; 377 size_t destleft = MAXNAMLEN; 378 379 /* Convert 16-bit Unicode to destname */ 380 if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) { 381 /* allocate a buffer big enough to hold an 8->16 bit expansion */ 382 unibuf = uma_zalloc(udf_zone_trans, M_WAITOK); 383 unip = unibuf; 384 if ((unilen = udf_UncompressUnicodeByte(len, cs0string, unibuf)) == -1) { 385 printf("udf: Unicode translation failed\n"); 386 uma_zfree(udf_zone_trans, unibuf); 387 return 0; 388 } 389 390 while (unilen > 0 && destleft > 0) { 391 udf_iconv->conv(udfmp->im_d2l, (const char **)&unibuf, 392 (size_t *)&unilen, (char **)&destname, &destleft); 393 /* Unconverted character found */ 394 if (unilen > 0 && destleft > 0) { 395 *destname++ = '?'; 396 destleft--; 397 unibuf += 2; 398 unilen -= 2; 399 } 400 } 401 uma_zfree(udf_zone_trans, unip); 402 *destname = '\0'; 403 destlen = MAXNAMLEN - (int)destleft; 404 } else { 405 /* allocate a buffer big enough to hold an 8->16 bit expansion */ 406 transname = uma_zalloc(udf_zone_trans, M_WAITOK); 407 408 if ((unilen = udf_UncompressUnicode(len, cs0string, transname)) == -1) { 409 printf("udf: Unicode translation failed\n"); 410 uma_zfree(udf_zone_trans, transname); 411 return 0; 412 } 413 414 for (i = 0; i < unilen ; i++) { 415 if (transname[i] & 0xff00) { 416 destname[i] = '.'; /* Fudge the 16bit chars */ 417 } else { 418 destname[i] = transname[i] & 0xff; 419 } 420 } 421 uma_zfree(udf_zone_trans, transname); 422 destname[unilen] = 0; 423 destlen = unilen; 424 } 425 426 return (destlen); 427} 428 429/* 430 * Compare a CS0 dstring with a name passed in from the VFS layer. Return 431 * 0 on a successful match, nonzero therwise. Unicode work may need to be done 432 * here also. 433 */ 434static int 435udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct udf_mnt *udfmp) 436{ 437 char *transname; 438 int error = 0; 439 440 /* This is overkill, but not worth creating a new zone */ 441 transname = uma_zalloc(udf_zone_trans, M_WAITOK); 442 443 cs0len = udf_transname(cs0string, transname, cs0len, udfmp); 444 445 /* Easy check. If they aren't the same length, they aren't equal */ 446 if ((cs0len == 0) || (cs0len != cmplen)) 447 error = -1; 448 else 449 error = bcmp(transname, cmpname, cmplen); 450 451 uma_zfree(udf_zone_trans, transname); 452 return (error); 453} 454 455struct udf_uiodir { 456 struct dirent *dirent; 457 u_long *cookies; 458 int ncookies; 459 int acookies; 460 int eofflag; 461}; 462 463static int 464udf_uiodir(struct udf_uiodir *uiodir, int de_size, struct uio *uio, long cookie) 465{ 466 if (uiodir->cookies != NULL) { 467 if (++uiodir->acookies > uiodir->ncookies) { 468 uiodir->eofflag = 0; 469 return (-1); 470 } 471 *uiodir->cookies++ = cookie; 472 } 473 474 if (uio->uio_resid < de_size) { 475 uiodir->eofflag = 0; 476 return (-1); 477 } 478 479 return (uiomove(uiodir->dirent, de_size, uio)); 480} 481 482static struct udf_dirstream * 483udf_opendir(struct udf_node *node, int offset, int fsize, struct udf_mnt *udfmp) 484{ 485 struct udf_dirstream *ds; 486 487 ds = uma_zalloc(udf_zone_ds, M_WAITOK | M_ZERO); 488 489 ds->node = node; 490 ds->offset = offset; 491 ds->udfmp = udfmp; 492 ds->fsize = fsize; 493 494 return (ds); 495} 496 497static struct fileid_desc * 498udf_getfid(struct udf_dirstream *ds) 499{ 500 struct fileid_desc *fid; 501 int error, frag_size = 0, total_fid_size; 502 503 /* End of directory? */ 504 if (ds->offset + ds->off >= ds->fsize) { 505 ds->error = 0; 506 return (NULL); 507 } 508 509 /* Grab the first extent of the directory */ 510 if (ds->off == 0) { 511 ds->size = 0; 512 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 513 &ds->bp, &ds->data); 514 if (error) { 515 ds->error = error; 516 if (ds->bp != NULL) 517 brelse(ds->bp); 518 return (NULL); 519 } 520 } 521 522 /* 523 * Clean up from a previous fragmented FID. 524 * XXX Is this the right place for this? 525 */ 526 if (ds->fid_fragment && ds->buf != NULL) { 527 ds->fid_fragment = 0; 528 FREE(ds->buf, M_UDFFID); 529 } 530 531 fid = (struct fileid_desc*)&ds->data[ds->off]; 532 533 /* 534 * Check to see if the fid is fragmented. The first test 535 * ensures that we don't wander off the end of the buffer 536 * looking for the l_iu and l_fi fields. 537 */ 538 if (ds->off + UDF_FID_SIZE > ds->size || 539 ds->off + le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE > ds->size){ 540 541 /* Copy what we have of the fid into a buffer */ 542 frag_size = ds->size - ds->off; 543 if (frag_size >= ds->udfmp->bsize) { 544 printf("udf: invalid FID fragment\n"); 545 ds->error = EINVAL; 546 return (NULL); 547 } 548 549 /* 550 * File ID descriptors can only be at most one 551 * logical sector in size. 552 */ 553 MALLOC(ds->buf, uint8_t*, ds->udfmp->bsize, M_UDFFID, 554 M_WAITOK | M_ZERO); 555 bcopy(fid, ds->buf, frag_size); 556 557 /* Reduce all of the casting magic */ 558 fid = (struct fileid_desc*)ds->buf; 559 560 if (ds->bp != NULL) 561 brelse(ds->bp); 562 563 /* Fetch the next allocation */ 564 ds->offset += ds->size; 565 ds->size = 0; 566 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 567 &ds->bp, &ds->data); 568 if (error) { 569 ds->error = error; 570 return (NULL); 571 } 572 573 /* 574 * If the fragment was so small that we didn't get 575 * the l_iu and l_fi fields, copy those in. 576 */ 577 if (frag_size < UDF_FID_SIZE) 578 bcopy(ds->data, &ds->buf[frag_size], 579 UDF_FID_SIZE - frag_size); 580 581 /* 582 * Now that we have enough of the fid to work with, 583 * copy in the rest of the fid from the new 584 * allocation. 585 */ 586 total_fid_size = UDF_FID_SIZE + le16toh(fid->l_iu) + fid->l_fi; 587 if (total_fid_size > ds->udfmp->bsize) { 588 printf("udf: invalid FID\n"); 589 ds->error = EIO; 590 return (NULL); 591 } 592 bcopy(ds->data, &ds->buf[frag_size], 593 total_fid_size - frag_size); 594 595 ds->fid_fragment = 1; 596 } else { 597 total_fid_size = le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE; 598 } 599 600 /* 601 * Update the offset. Align on a 4 byte boundary because the 602 * UDF spec says so. 603 */ 604 ds->this_off = ds->off; 605 if (!ds->fid_fragment) { 606 ds->off += (total_fid_size + 3) & ~0x03; 607 } else { 608 ds->off = (total_fid_size - frag_size + 3) & ~0x03; 609 } 610 611 return (fid); 612} 613 614static void 615udf_closedir(struct udf_dirstream *ds) 616{ 617 618 if (ds->bp != NULL) 619 brelse(ds->bp); 620 621 if (ds->fid_fragment && ds->buf != NULL) 622 FREE(ds->buf, M_UDFFID); 623 624 uma_zfree(udf_zone_ds, ds); 625} 626 627static int 628udf_readdir(struct vop_readdir_args *a) 629{ 630 struct vnode *vp; 631 struct uio *uio; 632 struct dirent dir; 633 struct udf_node *node; 634 struct udf_mnt *udfmp; 635 struct fileid_desc *fid; 636 struct udf_uiodir uiodir; 637 struct udf_dirstream *ds; 638 u_long *cookies = NULL; 639 int ncookies; 640 int error = 0; 641 642 vp = a->a_vp; 643 uio = a->a_uio; 644 node = VTON(vp); 645 udfmp = node->udfmp; 646 uiodir.eofflag = 1; 647 648 if (a->a_ncookies != NULL) { 649 /* 650 * Guess how many entries are needed. If we run out, this 651 * function will be called again and thing will pick up were 652 * it left off. 653 */ 654 ncookies = uio->uio_resid / 8; 655 MALLOC(cookies, u_long *, sizeof(u_long) * ncookies, 656 M_TEMP, M_WAITOK); 657 if (cookies == NULL) 658 return (ENOMEM); 659 uiodir.ncookies = ncookies; 660 uiodir.cookies = cookies; 661 uiodir.acookies = 0; 662 } else { 663 uiodir.cookies = NULL; 664 } 665 666 /* 667 * Iterate through the file id descriptors. Give the parent dir 668 * entry special attention. 669 */ 670 ds = udf_opendir(node, uio->uio_offset, le64toh(node->fentry->inf_len), 671 node->udfmp); 672 673 while ((fid = udf_getfid(ds)) != NULL) { 674 675 /* XXX Should we return an error on a bad fid? */ 676 if (udf_checktag(&fid->tag, TAGID_FID)) { 677 printf("Invalid FID tag\n"); 678 hexdump(fid, UDF_FID_SIZE, NULL, 0); 679 error = EIO; 680 break; 681 } 682 683 /* Is this a deleted file? */ 684 if (fid->file_char & UDF_FILE_CHAR_DEL) 685 continue; 686 687 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 688 /* Do up the '.' and '..' entries. Dummy values are 689 * used for the cookies since the offset here is 690 * usually zero, and NFS doesn't like that value 691 */ 692 dir.d_fileno = node->hash_id; 693 dir.d_type = DT_DIR; 694 dir.d_name[0] = '.'; 695 dir.d_name[1] = '\0'; 696 dir.d_namlen = 1; 697 dir.d_reclen = GENERIC_DIRSIZ(&dir); 698 uiodir.dirent = &dir; 699 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1); 700 if (error) 701 break; 702 703 dir.d_fileno = udf_getid(&fid->icb); 704 dir.d_type = DT_DIR; 705 dir.d_name[0] = '.'; 706 dir.d_name[1] = '.'; 707 dir.d_name[2] = '\0'; 708 dir.d_namlen = 2; 709 dir.d_reclen = GENERIC_DIRSIZ(&dir); 710 uiodir.dirent = &dir; 711 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2); 712 } else { 713 dir.d_namlen = udf_transname(&fid->data[fid->l_iu], 714 &dir.d_name[0], fid->l_fi, udfmp); 715 dir.d_fileno = udf_getid(&fid->icb); 716 dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ? 717 DT_DIR : DT_UNKNOWN; 718 dir.d_reclen = GENERIC_DIRSIZ(&dir); 719 uiodir.dirent = &dir; 720 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 721 ds->this_off); 722 } 723 if (error) { 724 printf("uiomove returned %d\n", error); 725 break; 726 } 727 728 } 729 730 /* tell the calling layer whether we need to be called again */ 731 *a->a_eofflag = uiodir.eofflag; 732 uio->uio_offset = ds->offset + ds->off; 733 734 if (!error) 735 error = ds->error; 736 737 udf_closedir(ds); 738 739 if (a->a_ncookies != NULL) { 740 if (error) 741 FREE(cookies, M_TEMP); 742 else { 743 *a->a_ncookies = uiodir.acookies; 744 *a->a_cookies = cookies; 745 } 746 } 747 748 return (error); 749} 750 751/* Are there any implementations out there that do soft-links? */ 752static int 753udf_readlink(struct vop_readlink_args *ap) 754{ 755 printf("%s called\n", __func__); 756 return (EOPNOTSUPP); 757} 758 759static int 760udf_strategy(struct vop_strategy_args *a) 761{ 762 struct buf *bp; 763 struct vnode *vp; 764 struct udf_node *node; 765 int maxsize; 766 struct bufobj *bo; 767 768 bp = a->a_bp; 769 vp = a->a_vp; 770 node = VTON(vp); 771 772 /* cd9660 has this test reversed, but it seems more logical this way */ 773 if (bp->b_blkno != bp->b_lblkno) { 774 /* 775 * Files that are embedded in the fentry don't translate well 776 * to a block number. Reject. 777 */ 778 if (udf_bmap_internal(node, bp->b_lblkno * node->udfmp->bsize, 779 &bp->b_lblkno, &maxsize)) { 780 clrbuf(bp); 781 bp->b_blkno = -1; 782 } 783 } 784 if ((long)bp->b_blkno == -1) { 785 bufdone(bp); 786 return (0); 787 } 788 bo = node->udfmp->im_bo; 789 bp->b_iooffset = dbtob(bp->b_blkno); 790 BO_STRATEGY(bo, bp); 791 return (0); 792} 793 794static int 795udf_bmap(struct vop_bmap_args *a) 796{ 797 struct udf_node *node; 798 uint32_t max_size; 799 daddr_t lsector; 800 int error; 801 802 node = VTON(a->a_vp); 803 804 if (a->a_bop != NULL) 805 *a->a_bop = &node->udfmp->im_devvp->v_bufobj; 806 if (a->a_bnp == NULL) 807 return (0); 808 if (a->a_runb) 809 *a->a_runb = 0; 810 811 error = udf_bmap_internal(node, a->a_bn * node->udfmp->bsize, &lsector, 812 &max_size); 813 if (error) 814 return (error); 815 816 /* Translate logical to physical sector number */ 817 *a->a_bnp = lsector << (node->udfmp->bshift - DEV_BSHIFT); 818 819 /* Punt on read-ahead for now */ 820 if (a->a_runp) 821 *a->a_runp = 0; 822 823 return (0); 824} 825 826/* 827 * The all powerful VOP_LOOKUP(). 828 */ 829static int 830udf_lookup(struct vop_cachedlookup_args *a) 831{ 832 struct vnode *dvp; 833 struct vnode *tdp = NULL; 834 struct vnode **vpp = a->a_vpp; 835 struct udf_node *node; 836 struct udf_mnt *udfmp; 837 struct fileid_desc *fid = NULL; 838 struct udf_dirstream *ds; 839 struct thread *td; 840 u_long nameiop; 841 u_long flags; 842 char *nameptr; 843 long namelen; 844 ino_t id = 0; 845 int offset, error = 0; 846 int numdirpasses, fsize; 847 848 dvp = a->a_dvp; 849 node = VTON(dvp); 850 udfmp = node->udfmp; 851 nameiop = a->a_cnp->cn_nameiop; 852 flags = a->a_cnp->cn_flags; 853 nameptr = a->a_cnp->cn_nameptr; 854 namelen = a->a_cnp->cn_namelen; 855 fsize = le64toh(node->fentry->inf_len); 856 td = a->a_cnp->cn_thread; 857 858 /* 859 * If this is a LOOKUP and we've already partially searched through 860 * the directory, pick up where we left off and flag that the 861 * directory may need to be searched twice. For a full description, 862 * see /sys/isofs/cd9660/cd9660_lookup.c:cd9660_lookup() 863 */ 864 if (nameiop != LOOKUP || node->diroff == 0 || node->diroff > fsize) { 865 offset = 0; 866 numdirpasses = 1; 867 } else { 868 offset = node->diroff; 869 numdirpasses = 2; 870 nchstats.ncs_2passes++; 871 } 872 873lookloop: 874 ds = udf_opendir(node, offset, fsize, udfmp); 875 876 while ((fid = udf_getfid(ds)) != NULL) { 877 878 /* XXX Should we return an error on a bad fid? */ 879 if (udf_checktag(&fid->tag, TAGID_FID)) { 880 printf("udf_lookup: Invalid tag\n"); 881 error = EIO; 882 break; 883 } 884 885 /* Is this a deleted file? */ 886 if (fid->file_char & UDF_FILE_CHAR_DEL) 887 continue; 888 889 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 890 if (flags & ISDOTDOT) { 891 id = udf_getid(&fid->icb); 892 break; 893 } 894 } else { 895 if (!(udf_cmpname(&fid->data[fid->l_iu], 896 nameptr, fid->l_fi, namelen, udfmp))) { 897 id = udf_getid(&fid->icb); 898 break; 899 } 900 } 901 } 902 903 if (!error) 904 error = ds->error; 905 906 /* XXX Bail out here? */ 907 if (error) { 908 udf_closedir(ds); 909 return (error); 910 } 911 912 /* Did we have a match? */ 913 if (id) { 914 if (flags & ISDOTDOT) 915 VOP_UNLOCK(dvp, 0, a->a_cnp->cn_thread); 916 error = udf_vget(udfmp->im_mountp, id, LK_EXCLUSIVE, &tdp);
|