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