Annotation of src/sys/fs/hfs/hfs_vnops.c, Revision 1.2.4.2
1.2.4.2 ! rmind 1: /* $NetBSD: hfs_vnops.c,v 1.2.4.1 2007/03/12 06:14:55 rmind Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 2005, 2007 The NetBSD Foundation, Inc.
! 5: * All rights reserved.
! 6: *
! 7: * This code is derived from software contributed to The NetBSD Foundation
! 8: * by Yevgeny Binder and Dieter Baron.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in the
! 17: * documentation and/or other materials provided with the distribution.
! 18: *
! 19: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 29: * POSSIBILITY OF SUCH DAMAGE.
! 30: */
! 31:
! 32: /*
! 33: * Copyright (c) 1992, 1993
! 34: * The Regents of the University of California. All rights reserved.
! 35: *
! 36: * This code is derived from software donated to Berkeley by
! 37: * Jan-Simon Pendry.
! 38: *
! 39: * Redistribution and use in source and binary forms, with or without
! 40: * modification, are permitted provided that the following conditions
! 41: * are met:
! 42: * 1. Redistributions of source code must retain the above copyright
! 43: * notice, this list of conditions and the following disclaimer.
! 44: * 2. Redistributions in binary form must reproduce the above copyright
! 45: * notice, this list of conditions and the following disclaimer in the
! 46: * documentation and/or other materials provided with the distribution.
! 47: * 3. Neither the name of the University nor the names of its contributors
! 48: * may be used to endorse or promote products derived from this software
! 49: * without specific prior written permission.
! 50: *
! 51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 61: * SUCH DAMAGE.
! 62: */
! 63:
! 64: /*
! 65: * Copyright (c) 1982, 1986, 1989, 1993, 1995
! 66: * The Regents of the University of California. All rights reserved.
! 67: * (c) UNIX System Laboratories, Inc.
! 68: * All or some portions of this file are derived from material licensed
! 69: * to the University of California by American Telephone and Telegraph
! 70: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
! 71: * the permission of UNIX System Laboratories, Inc.
! 72: *
! 73: * Redistribution and use in source and binary forms, with or without
! 74: * modification, are permitted provided that the following conditions
! 75: * are met:
! 76: * 1. Redistributions of source code must retain the above copyright
! 77: * notice, this list of conditions and the following disclaimer.
! 78: * 2. Redistributions in binary form must reproduce the above copyright
! 79: * notice, this list of conditions and the following disclaimer in the
! 80: * documentation and/or other materials provided with the distribution.
! 81: * 3. Neither the name of the University nor the names of its contributors
! 82: * may be used to endorse or promote products derived from this software
! 83: * without specific prior written permission.
! 84: *
! 85: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 86: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 87: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 88: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 89: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 90: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 91: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 92: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 93: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 94: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 95: * SUCH DAMAGE.
! 96: */
! 97:
! 98:
! 99: /*
! 100: * Apple HFS+ filesystem
! 101: */
! 102:
! 103: #include <sys/cdefs.h>
! 104: __KERNEL_RCSID(0, "$NetBSD: hfs_vnops.c,v 1.2.4.1 2007/03/12 06:14:55 rmind Exp $");
! 105:
! 106: #ifdef _KERNEL_OPT
! 107: #include "opt_ipsec.h"
! 108: #endif
! 109:
! 110: #include <sys/param.h>
! 111: #include <sys/systm.h>
! 112: #include <sys/kernel.h>
! 113: #include <sys/vmmeter.h>
! 114: #include <sys/time.h>
! 115: #include <sys/proc.h>
! 116: #include <sys/vnode.h>
! 117: #include <sys/malloc.h>
! 118: #include <sys/file.h>
! 119: #include <sys/stat.h>
! 120: #include <sys/mount.h>
! 121: #include <sys/namei.h>
! 122: #include <sys/buf.h>
! 123: #include <sys/dirent.h>
! 124: #include <sys/msgbuf.h>
! 125:
! 126: #include <miscfs/fifofs/fifo.h>
! 127: #include <miscfs/specfs/specdev.h>
! 128:
! 129: #include <fs/hfs/hfs.h>
! 130: #include <fs/hfs/unicode.h>
! 131:
! 132: #include <miscfs/genfs/genfs.h>
! 133:
! 134: int hfs_vop_lookup (void *);
! 135: int hfs_vop_open (void *);
! 136: int hfs_vop_close (void *);
! 137: int hfs_vop_access (void *);
! 138: int hfs_vop_getattr (void *);
! 139: int hfs_vop_setattr (void *);
! 140: int hfs_vop_bmap (void *);
! 141: int hfs_vop_read (void *);
! 142: int hfs_vop_readdir (void *);
! 143: int hfs_vop_readlink (void *);
! 144: int hfs_vop_reclaim (void *);
! 145: int hfs_vop_print (void *);
! 146:
! 147:
! 148: int (**hfs_vnodeop_p) (void *);
! 149: const struct vnodeopv_entry_desc hfs_vnodeop_entries[] = {
! 150: { &vop_default_desc, vn_default_error },
! 151: { &vop_lookup_desc, hfs_vop_lookup }, /* lookup */
! 152: { &vop_create_desc, genfs_eopnotsupp }, /* create */
! 153: { &vop_whiteout_desc, genfs_eopnotsupp }, /* whiteout */
! 154: { &vop_mknod_desc, genfs_eopnotsupp }, /* mknod */
! 155: { &vop_open_desc, hfs_vop_open }, /* open */
! 156: { &vop_close_desc, hfs_vop_close }, /* close */
! 157: { &vop_access_desc, hfs_vop_access }, /* access */
! 158: { &vop_getattr_desc, hfs_vop_getattr }, /* getattr */
! 159: { &vop_setattr_desc, hfs_vop_setattr }, /* setattr */
! 160: { &vop_read_desc, hfs_vop_read }, /* read */
! 161: { &vop_write_desc, genfs_eopnotsupp }, /* write */
! 162: { &vop_lease_desc, genfs_eopnotsupp }, /* lease */
! 163: { &vop_ioctl_desc, genfs_eopnotsupp }, /* ioctl */
! 164: { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
! 165: { &vop_poll_desc, genfs_eopnotsupp }, /* poll */
! 166: { &vop_kqfilter_desc, genfs_kqfilter }, /* kqfilter */
! 167: { &vop_revoke_desc, genfs_eopnotsupp }, /* revoke */
! 168: { &vop_mmap_desc, genfs_mmap }, /* mmap */
! 169: { &vop_fsync_desc, genfs_nullop }, /* fsync */
! 170: { &vop_seek_desc, genfs_seek }, /* seek */
! 171: { &vop_remove_desc, genfs_eopnotsupp }, /* remove */
! 172: { &vop_link_desc, genfs_eopnotsupp }, /* link */
! 173: { &vop_rename_desc, genfs_eopnotsupp }, /* rename */
! 174: { &vop_mkdir_desc, genfs_eopnotsupp }, /* mkdir */
! 175: { &vop_rmdir_desc, genfs_eopnotsupp }, /* rmdir */
! 176: { &vop_symlink_desc, genfs_eopnotsupp }, /* symlink */
! 177: { &vop_readdir_desc, hfs_vop_readdir }, /* readdir */
! 178: { &vop_readlink_desc, hfs_vop_readlink }, /* readlink */
! 179: { &vop_abortop_desc, genfs_abortop }, /* abortop */
! 180: { &vop_inactive_desc, genfs_eopnotsupp }, /* inactive */
! 181: { &vop_reclaim_desc, hfs_vop_reclaim }, /* reclaim */
! 182: { &vop_lock_desc, genfs_lock }, /* lock */
! 183: { &vop_unlock_desc, genfs_unlock }, /* unlock */
! 184: { &vop_bmap_desc, hfs_vop_bmap }, /* bmap */
! 185: { &vop_strategy_desc, genfs_eopnotsupp }, /* strategy */
! 186: { &vop_print_desc, hfs_vop_print }, /* print */
! 187: { &vop_islocked_desc, genfs_islocked }, /* islocked */
! 188: { &vop_pathconf_desc, genfs_eopnotsupp }, /* pathconf */
! 189: { &vop_advlock_desc, genfs_eopnotsupp }, /* advlock */
! 190: { &vop_bwrite_desc, genfs_eopnotsupp }, /* bwrite */
! 191: { &vop_getpages_desc, genfs_getpages }, /* getpages */
! 192: { &vop_putpages_desc, genfs_putpages }, /* putpages */
! 193: { &vop_openextattr_desc, genfs_eopnotsupp }, /* openextattr */
! 194: { &vop_closeextattr_desc, genfs_eopnotsupp }, /* closeextattr */
! 195: { &vop_getextattr_desc, genfs_eopnotsupp }, /* getextattr */
! 196: { &vop_setextattr_desc, genfs_eopnotsupp }, /* setextattr */
! 197: { &vop_listextattr_desc, genfs_eopnotsupp }, /* listextattr */
! 198: { &vop_deleteextattr_desc, genfs_eopnotsupp }, /* deleteextattr */
! 199: { NULL, NULL }
! 200: };
! 201: const struct vnodeopv_desc hfs_vnodeop_opv_desc =
! 202: { &hfs_vnodeop_p, hfs_vnodeop_entries };
! 203:
! 204: int (**hfs_specop_p) (void *);
! 205: const struct vnodeopv_entry_desc hfs_specop_entries[] = {
! 206: { &vop_default_desc, vn_default_error },
! 207: { &vop_lookup_desc, spec_lookup }, /* lookup */
! 208: { &vop_create_desc, spec_create }, /* create */
! 209: { &vop_mknod_desc, spec_mknod }, /* mknod */
! 210: { &vop_open_desc, spec_open }, /* open */
! 211: { &vop_close_desc, spec_close }, /* close */
! 212: { &vop_access_desc, hfs_vop_access }, /* access */
! 213: { &vop_getattr_desc, hfs_vop_getattr }, /* getattr */
! 214: { &vop_setattr_desc, hfs_vop_setattr }, /* setattr */
! 215: { &vop_read_desc, spec_read }, /* read */
! 216: { &vop_write_desc, spec_write }, /* write */
! 217: { &vop_lease_desc, spec_lease_check }, /* lease */
! 218: { &vop_ioctl_desc, spec_ioctl }, /* ioctl */
! 219: { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
! 220: { &vop_poll_desc, spec_poll }, /* poll */
! 221: { &vop_kqfilter_desc, spec_kqfilter }, /* kqfilter */
! 222: { &vop_revoke_desc, spec_revoke }, /* revoke */
! 223: { &vop_mmap_desc, spec_mmap }, /* mmap */
! 224: { &vop_fsync_desc, genfs_nullop }, /* fsync */
! 225: { &vop_seek_desc, spec_seek }, /* seek */
! 226: { &vop_remove_desc, spec_remove }, /* remove */
! 227: { &vop_link_desc, spec_link }, /* link */
! 228: { &vop_rename_desc, spec_rename }, /* rename */
! 229: { &vop_mkdir_desc, spec_mkdir }, /* mkdir */
! 230: { &vop_rmdir_desc, spec_rmdir }, /* rmdir */
! 231: { &vop_symlink_desc, spec_symlink }, /* symlink */
! 232: { &vop_readdir_desc, spec_readdir }, /* readdir */
! 233: { &vop_readlink_desc, spec_readlink }, /* readlink */
! 234: { &vop_abortop_desc, spec_abortop }, /* abortop */
! 235: { &vop_inactive_desc, genfs_eopnotsupp }, /* inactive */
! 236: { &vop_reclaim_desc, hfs_vop_reclaim }, /* reclaim */
! 237: { &vop_lock_desc, genfs_lock }, /* lock */
! 238: { &vop_unlock_desc, genfs_unlock }, /* unlock */
! 239: { &vop_bmap_desc, spec_bmap }, /* bmap */
! 240: { &vop_strategy_desc, spec_strategy }, /* strategy */
! 241: { &vop_print_desc, hfs_vop_print }, /* print */
! 242: { &vop_islocked_desc, genfs_islocked }, /* islocked */
! 243: { &vop_pathconf_desc, spec_pathconf }, /* pathconf */
! 244: { &vop_advlock_desc, spec_advlock }, /* advlock */
! 245: { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
! 246: { &vop_getpages_desc, spec_getpages }, /* getpages */
! 247: { &vop_putpages_desc, spec_putpages }, /* putpages */
! 248: #if 0
! 249: { &vop_openextattr_desc, ffs_openextattr }, /* openextattr */
! 250: { &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */
! 251: { &vop_getextattr_desc, ffs_getextattr }, /* getextattr */
! 252: { &vop_setextattr_desc, ffs_setextattr }, /* setextattr */
! 253: { &vop_listextattr_desc, ffs_listextattr }, /* listextattr */
! 254: { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
! 255: #endif
! 256: { NULL, NULL }
! 257: };
! 258: const struct vnodeopv_desc hfs_specop_opv_desc =
! 259: { &hfs_specop_p, hfs_specop_entries };
! 260:
! 261: int (**hfs_fifoop_p) (void *);
! 262: const struct vnodeopv_entry_desc hfs_fifoop_entries[] = {
! 263: { &vop_default_desc, vn_default_error },
! 264: { &vop_lookup_desc, fifo_lookup }, /* lookup */
! 265: { &vop_create_desc, fifo_create }, /* create */
! 266: { &vop_mknod_desc, fifo_mknod }, /* mknod */
! 267: { &vop_open_desc, fifo_open }, /* open */
! 268: { &vop_close_desc, fifo_close }, /* close */
! 269: { &vop_access_desc, hfs_vop_access }, /* access */
! 270: { &vop_getattr_desc, hfs_vop_getattr }, /* getattr */
! 271: { &vop_setattr_desc, hfs_vop_setattr }, /* setattr */
! 272: { &vop_read_desc, fifo_read }, /* read */
! 273: { &vop_write_desc, fifo_write }, /* write */
! 274: { &vop_lease_desc, fifo_lease_check }, /* lease */
! 275: { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */
! 276: { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
! 277: { &vop_poll_desc, fifo_poll }, /* poll */
! 278: { &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */
! 279: { &vop_revoke_desc, fifo_revoke }, /* revoke */
! 280: { &vop_mmap_desc, fifo_mmap }, /* mmap */
! 281: { &vop_fsync_desc, fifo_fsync }, /* fsync */
! 282: { &vop_seek_desc, fifo_seek }, /* seek */
! 283: { &vop_remove_desc, fifo_remove }, /* remove */
! 284: { &vop_link_desc, fifo_link }, /* link */
! 285: { &vop_rename_desc, fifo_rename }, /* rename */
! 286: { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */
! 287: { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */
! 288: { &vop_symlink_desc, fifo_symlink }, /* symlink */
! 289: { &vop_readdir_desc, fifo_readdir }, /* readdir */
! 290: { &vop_readlink_desc, fifo_readlink }, /* readlink */
! 291: { &vop_abortop_desc, fifo_abortop }, /* abortop */
! 292: { &vop_inactive_desc, genfs_eopnotsupp }, /* inactive */
! 293: { &vop_reclaim_desc, hfs_vop_reclaim }, /* reclaim */
! 294: { &vop_lock_desc, genfs_lock }, /* lock */
! 295: { &vop_unlock_desc, genfs_unlock }, /* unlock */
! 296: { &vop_bmap_desc, fifo_bmap }, /* bmap */
! 297: { &vop_strategy_desc, fifo_strategy }, /* strategy */
! 298: { &vop_print_desc, hfs_vop_print }, /* print */
! 299: { &vop_islocked_desc, genfs_islocked }, /* islocked */
! 300: { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */
! 301: { &vop_advlock_desc, fifo_advlock }, /* advlock */
! 302: { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
! 303: { &vop_putpages_desc, fifo_putpages }, /* putpages */
! 304: #if 0
! 305: { &vop_openextattr_desc, ffs_openextattr }, /* openextattr */
! 306: { &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */
! 307: { &vop_getextattr_desc, ffs_getextattr }, /* getextattr */
! 308: { &vop_setextattr_desc, ffs_setextattr }, /* setextattr */
! 309: { &vop_listextattr_desc, ffs_listextattr }, /* listextattr */
! 310: { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
! 311: #endif
! 312: { NULL, NULL }
! 313: };
! 314: const struct vnodeopv_desc hfs_fifoop_opv_desc =
! 315: { &hfs_fifoop_p, hfs_fifoop_entries };
! 316:
! 317: int
! 318: hfs_vop_lookup(void *v)
! 319: {
! 320: struct vop_lookup_args /* {
! 321: struct vnode * a_dvp;
! 322: struct vnode ** a_vpp;
! 323: struct componentname * a_cnp;
! 324: } */ *ap = v;
! 325: struct buf *bp; /* a buffer of directory entries */
! 326: struct componentname *cnp;
! 327: struct hfsnode *dp; /* hfsnode for directory being searched */
! 328: kauth_cred_t cred;
! 329: struct vnode **vpp; /* resultant vnode */
! 330: struct vnode *pdp; /* saved dp during symlink work */
! 331: struct vnode *tdp; /* returned by VFS_VGET */
! 332: struct vnode *vdp; /* vnode for directory being searched */
! 333: hfs_catalog_key_t key; /* hfs+ catalog search key for requested child */
! 334: hfs_catalog_keyed_record_t rec; /* catalog record of requested child */
! 335: unichar_t* unicn; /* name of component, in Unicode */
! 336: const char *pname;
! 337: int error;
! 338: int flags;
! 339: int lockparent; /* 1 => lockparent flag is set */
! 340: int result; /* result of libhfs operations */
! 341:
! 342: #ifdef HFS_DEBUG
! 343: printf("VOP = hfs_vop_lookup()\n");
! 344: #endif /* HFS_DEBUG */
! 345:
! 346: bp = NULL;
! 347: cnp = ap->a_cnp;
! 348: cred = cnp->cn_cred;
! 349: vdp = ap->a_dvp;
! 350: dp = VTOH(vdp);
! 351: error = 0;
! 352: pname = cnp->cn_nameptr;
! 353: result = 0;
! 354: unicn = NULL;
! 355: vpp = ap->a_vpp;
! 356: *vpp = NULL;
! 357:
! 358: flags = cnp->cn_flags;
! 359: lockparent = flags & LOCKPARENT;
! 360:
! 361:
! 362: /*
! 363: * Check accessiblity of directory.
! 364: */
! 365: if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_lwp)) != 0)
! 366: return error;
! 367:
! 368: if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
! 369: (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
! 370: return EROFS;
! 371:
! 372: /*
! 373: * We now have a segment name to search for, and a directory to search.
! 374: *
! 375: * Before tediously performing a linear scan of the directory,
! 376: * check the name cache to see if the directory/name pair
! 377: * we are looking for is known already.
! 378: */
! 379: /* XXX Cache disabled until we can make sure it works. */
! 380: /* if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
! 381: return error; */
! 382:
! 383:
! 384: /* if (cnp->cn_namelen == 1 && *pname == '.') {
! 385: *vpp = vdp;
! 386: VREF(vdp);
! 387: return (0);
! 388: }*/
! 389:
! 390: pdp = vdp;
! 391: if (flags & ISDOTDOT) {
! 392: /*printf("DOTDOT ");*/
! 393: VOP_UNLOCK(pdp, 0); /* race to get the inode */
! 394: error = VFS_VGET(vdp->v_mount, dp->h_parent, &tdp);
! 395: if (error != 0) {
! 396: vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY);
! 397: goto error;
! 398: }
! 399: if (lockparent && (flags & ISLASTCN)) {
! 400: if ((error = vn_lock(pdp, LK_EXCLUSIVE)) != 0) {
! 401: vput(tdp);
! 402: goto error;
! 403: }
! 404: }
! 405: *vpp = tdp;
! 406: /* } else if (dp->h_rec.cnid == rec.file.cnid) {*/
! 407: } else if (cnp->cn_namelen == 1 && pname[0] == '.') {
! 408: /*printf("DOT ");*/
! 409: VREF(vdp); /* we want ourself, ie "." */
! 410: *vpp = vdp;
! 411: } else {
! 412: hfs_callback_args cbargs;
! 413: hfs_libcb_argsread argsread;
! 414: uint8_t len;
! 415:
! 416: hfslib_init_cbargs(&cbargs);
! 417: argsread.l = cnp->cn_lwp;
! 418: argsread.cred = cnp->cn_cred;
! 419:
! 420: /* XXX: when decomposing, string could grow
! 421: and we have to handle overflow */
! 422: unicn = malloc(cnp->cn_namelen*sizeof(unicn[0]), M_TEMP, M_WAITOK);
! 423: len = utf8_to_utf16(unicn, cnp->cn_namelen,
! 424: cnp->cn_nameptr, cnp->cn_namelen, 0, NULL);
! 425: /* XXX: check conversion errors? */
! 426: if (hfslib_make_catalog_key(VTOH(vdp)->h_rec.cnid, len, unicn,
! 427: &key) == 0) {
! 428: /*printf("ERROR in hfslib_make_catalog_key\n");*/
! 429: error = EINVAL;
! 430: goto error;
! 431: }
! 432:
! 433: result = hfslib_find_catalog_record_with_key(&dp->h_hmp->hm_vol, &key,
! 434: &rec, &cbargs);
! 435: if (result > 0) {
! 436: error = EINVAL;
! 437: goto error;
! 438: }
! 439: if (result < 0) {
! 440: if (cnp->cn_nameiop == CREATE)
! 441: error = EROFS;
! 442: else
! 443: error = ENOENT;
! 444: goto error;
! 445: }
! 446:
! 447: if (rec.file.user_info.file_type == HFS_HARD_LINK_FILE_TYPE
! 448: && rec.file.user_info.file_creator
! 449: == HFS_HFSLUS_CREATOR) {
! 450: if (hfslib_get_hardlink(&dp->h_hmp->hm_vol,
! 451: rec.file.bsd.special.inode_num,
! 452: &rec, &cbargs) != 0) {
! 453: error = EINVAL;
! 454: goto error;
! 455: }
! 456: }
! 457:
! 458: if (rec.type == HFS_REC_FILE
! 459: && strcmp(cnp->cn_nameptr+cnp->cn_namelen, "/rsrc") == 0
! 460: && rec.file.rsrc_fork.logical_size > 0) {
! 461: /* advance namei next pointer to end of stirng */
! 462: cnp->cn_consume = 5;
! 463: cnp->cn_flags &= ~REQUIREDIR; /* XXX: needed? */
! 464: error = hfs_vget_internal(vdp->v_mount, rec.file.cnid,
! 465: HFS_RSRCFORK, &tdp);
! 466: }
! 467: else
! 468: error = VFS_VGET(vdp->v_mount, rec.file.cnid, &tdp);
! 469: if (error != 0)
! 470: goto error;
! 471: if (!lockparent || !(flags & ISLASTCN)) {
! 472: VOP_UNLOCK(pdp, 0);
! 473: }
! 474: *vpp = tdp;
! 475: }
! 476: /*printf("\n");*/
! 477: /*
! 478: * Insert name into cache if appropriate.
! 479: */
! 480: /* XXX Cache disabled until we can make sure it works. */
! 481: /* if (cnp->cn_flags & MAKEENTRY)
! 482: cache_enter(vdp, *vpp, cnp);*/
! 483:
! 484: error = 0;
! 485:
! 486: /* FALLTHROUGH */
! 487: error:
! 488: if (unicn != NULL)
! 489: free(unicn, M_TEMP);
! 490:
! 491: return error;
! 492: }
! 493:
! 494: int
! 495: hfs_vop_open(void *v)
! 496: {
! 497: #if 0
! 498: struct vop_open_args /* {
! 499: struct vnode *a_vp;
! 500: int a_mode;
! 501: kauth_cred_t a_cred;
! 502: struct lwp *a_l;
! 503: } */ *ap = v;
! 504: struct hfsnode *hn = VTOH(ap->a_vp);
! 505: #endif
! 506: #ifdef HFS_DEBUG
! 507: printf("VOP = hfs_vop_open()\n");
! 508: #endif /* HFS_DEBUG */
! 509:
! 510: /*
! 511: * XXX This is a good place to read and cache the file's extents to avoid
! 512: * XXX doing it upon every read/write. Must however keep the cache in sync
! 513: * XXX when the file grows/shrinks. (So would that go in vop_truncate?)
! 514: */
! 515:
! 516: return 0;
! 517: }
! 518:
! 519: int
! 520: hfs_vop_close(void *v)
! 521: {
! 522: #if 0
! 523: struct vop_close_args /* {
! 524: struct vnode *a_vp;
! 525: int a_fflag;
! 526: kauth_cred_t a_cred;
! 527: struct lwp *a_l;
! 528: } */ *ap = v;
! 529: struct hfsnode *hn = VTOH(ap->a_vp);
! 530: #endif
! 531: #ifdef HFS_DEBUG
! 532: printf("VOP = hfs_vop_close()\n");
! 533: #endif /* HFS_DEBUG */
! 534:
! 535: /* Release extents cache here. */
! 536:
! 537: return 0;
! 538: }
! 539:
! 540: int
! 541: hfs_vop_access(void *v)
! 542: {
! 543: struct vop_access_args /* {
! 544: struct vnode *a_vp;
! 545: int a_mode;
! 546: kauth_cred_t a_cred;
! 547: struct lwp *a_l;
! 548: } */ *ap = v;
! 549: struct vattr va;
! 550: int error;
! 551:
! 552: #ifdef HFS_DEBUG
! 553: printf("VOP = hfs_vop_access()\n");
! 554: #endif /* HFS_DEBUG */
! 555:
! 556: /*
! 557: * Disallow writes on files, directories, and symlinks
! 558: * since we have no write support yet.
! 559: */
! 560:
! 561: if (ap->a_mode & VWRITE) {
! 562: switch (ap->a_vp->v_type) {
! 563: case VDIR:
! 564: case VLNK:
! 565: case VREG:
! 566: return EROFS;
! 567: default:
! 568: break;
! 569: }
! 570: }
! 571:
! 572: if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_l)) != 0)
! 573: return error;
! 574:
! 575: return vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
! 576: ap->a_mode, ap->a_cred);
! 577: }
! 578:
! 579: int
! 580: hfs_vop_getattr(void *v)
! 581: {
! 582: struct vop_getattr_args /* {
! 583: struct vnode *a_vp;
! 584: struct vattr *a_vap;
! 585: struct ucred *a_cred;
! 586: struct lwp *a_l;
! 587: } */ *ap = v;
! 588: struct vnode *vp;
! 589: struct hfsnode *hp;
! 590: struct vattr *vap;
! 591: hfs_bsd_data_t *bsd;
! 592: hfs_fork_t *fork;
! 593:
! 594: #ifdef HFS_DEBUG
! 595: printf("VOP = hfs_vop_getattr()\n");
! 596: #endif /* HFS_DEBUG */
! 597:
! 598: vp = ap->a_vp;
! 599: hp = VTOH(vp);
! 600: vap = ap->a_vap;
! 601:
! 602: vattr_null(vap);
! 603:
! 604: /*
! 605: * XXX Cannot trust permissions/modes/flags stored in an HFS+ catalog record
! 606: * XXX record those values are not set on files created under Mac OS 9.
! 607: */
! 608: vap->va_type = ap->a_vp->v_type;
! 609: if (hp->h_rec.rec_type == HFS_REC_FILE) {
! 610: if (hp->h_fork == HFS_RSRCFORK)
! 611: fork = &hp->h_rec.file.rsrc_fork;
! 612: else
! 613: fork = &hp->h_rec.file.data_fork;
! 614: vap->va_fileid = hp->h_rec.file.cnid;
! 615: bsd = &hp->h_rec.file.bsd;
! 616: vap->va_bytes = fork->total_blocks * HFS_BLOCKSIZE(vp);
! 617: vap->va_size = fork->logical_size;
! 618: hfs_time_to_timespec(hp->h_rec.file.date_created, &vap->va_ctime);
! 619: hfs_time_to_timespec(hp->h_rec.file.date_content_mod, &vap->va_mtime);
! 620: hfs_time_to_timespec(hp->h_rec.file.date_accessed, &vap->va_atime);
! 621: vap->va_nlink = 1;
! 622: }
! 623: else if (hp->h_rec.rec_type == HFS_REC_FLDR) {
! 624: vap->va_fileid = hp->h_rec.folder.cnid;
! 625: bsd = &hp->h_rec.folder.bsd;
! 626: vap->va_size = 512; /* XXX Temporary */
! 627: vap->va_bytes = 512; /* XXX Temporary */
! 628: hfs_time_to_timespec(hp->h_rec.folder.date_created, &vap->va_ctime);
! 629: hfs_time_to_timespec(hp->h_rec.folder.date_content_mod,&vap->va_mtime);
! 630: hfs_time_to_timespec(hp->h_rec.folder.date_accessed, &vap->va_atime);
! 631: vap->va_nlink = 2; /* XXX */
! 632: }
! 633: else {
! 634: printf("hfslus: hfs_vop_getattr(): invalid record type %i",
! 635: hp->h_rec.rec_type);
! 636: return EINVAL;
! 637: }
! 638:
! 639: if ((bsd->file_mode & S_IFMT) == 0) {
! 640: /* no bsd permissions recorded, use default values */
! 641: if (hp->h_rec.rec_type == HFS_REC_FILE)
! 642: vap->va_mode = (S_IFREG | HFS_DEFAULT_FILE_MODE);
! 643: else
! 644: vap->va_mode = (S_IFDIR | HFS_DEFAULT_DIR_MODE);
! 645: vap->va_uid = HFS_DEFAULT_UID;
! 646: vap->va_gid = HFS_DEFAULT_GID;
! 647: }
! 648: else {
! 649: vap->va_mode = bsd->file_mode;
! 650: vap->va_uid = bsd->owner_id;
! 651: vap->va_gid = bsd->group_id;
! 652: if ((vap->va_mode & S_IFMT) == S_IFCHR
! 653: || (vap->va_mode & S_IFMT) == S_IFBLK) {
! 654: vap->va_rdev
! 655: = HFS_CONVERT_RDEV(bsd->special.raw_device);
! 656: }
! 657: else if (bsd->special.link_count != 0) {
! 658: /* XXX: only if in metadata directory */
! 659: vap->va_nlink = bsd->special.link_count;
! 660: }
! 661: }
! 662:
! 663: vap->va_fsid = hp->h_dev;
! 664: vap->va_blocksize = hp->h_hmp->hm_vol.vh.block_size;
! 665: vap->va_gen = 1;
! 666: vap->va_flags = 0;
! 667:
! 668: return 0;
! 669: }
! 670:
! 671: int
! 672: hfs_vop_setattr(void *v)
! 673: {
! 674: struct vop_setattr_args /* {
! 675: struct vnode *a_vp;
! 676: struct vattr *a_vap;
! 677: kauth_cred_t a_cred;
! 678: struct lwp *a_l;
! 679: } */ *ap = v;
! 680: struct vattr *vap;
! 681: struct vnode *vp;
! 682:
! 683: vap = ap->a_vap;
! 684: vp = ap->a_vp;
! 685:
! 686: /*
! 687: * Check for unsettable attributes.
! 688: */
! 689: if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
! 690: (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
! 691: (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
! 692: ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
! 693: return EINVAL;
! 694: }
! 695:
! 696: /* XXX: needs revisiting for write support */
! 697: if (vap->va_flags != VNOVAL
! 698: || vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL
! 699: || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL
! 700: || vap->va_birthtime.tv_sec != VNOVAL) {
! 701: return EROFS;
! 702: }
! 703:
! 704: if (vap->va_size != VNOVAL) {
! 705: /*
! 706: * Disallow write attempts on read-only file systems;
! 707: * unless the file is a socket, fifo, or a block or
! 708: * character device resident on the file system.
! 709: */
! 710: switch (vp->v_type) {
! 711: case VDIR:
! 712: return EISDIR;
! 713: case VCHR:
! 714: case VBLK:
! 715: case VFIFO:
! 716: break;
! 717: case VREG:
! 718: return EROFS;
! 719: default:
! 720: return EOPNOTSUPP;
! 721: }
! 722: }
! 723:
! 724: return 0;
! 725: }
! 726:
! 727: int
! 728: hfs_vop_bmap(void *v)
! 729: {
! 730: struct vop_bmap_args /* {
! 731: struct vnode *a_vp;
! 732: daddr_t a_bn;
! 733: struct vnode **a_vpp;
! 734: daddr_t *a_bnp;
! 735: int *a_runp;
! 736: } */ *ap = v;
! 737: struct vnode *vp;
! 738: struct hfsnode *hp;
! 739: daddr_t lblkno;
! 740: hfs_callback_args cbargs;
! 741: hfs_libcb_argsread argsread;
! 742: hfs_extent_descriptor_t *extents;
! 743: uint16_t numextents, i;
! 744: int bshift;
! 745:
! 746: vp = ap->a_vp;
! 747: hp = VTOH(vp);
! 748: lblkno = ap->a_bn;
! 749: bshift = vp->v_mount->mnt_fs_bshift;
! 750:
! 751: /*
! 752: * Check for underlying vnode requests and ensure that logical
! 753: * to physical mapping is requested.
! 754: */
! 755: if (ap->a_vpp != NULL)
! 756: *ap->a_vpp = hp->h_devvp;
! 757: if (ap->a_bnp == NULL)
! 758: return (0);
! 759:
! 760: hfslib_init_cbargs(&cbargs);
! 761: argsread.cred = NULL;
! 762: argsread.l = NULL;
! 763: cbargs.read = &argsread;
! 764:
! 765: numextents = hfslib_get_file_extents(&hp->h_hmp->hm_vol,
! 766: hp->h_rec.cnid, hp->h_fork, &extents, &cbargs);
! 767:
! 768: /* XXX: is this correct for 0-length files? */
! 769: if (numextents == 0)
! 770: return EBADF;
! 771:
! 772: for (i=0; i<numextents; i++) {
! 773: if (lblkno < extents[i].block_count)
! 774: break;
! 775: lblkno -= extents[i].block_count;
! 776: }
! 777:
! 778: if (i == numextents) {
! 779: /* XXX: block number past EOF */
! 780: i--;
! 781: lblkno += extents[i].block_count;
! 782: }
! 783:
! 784: *ap->a_bnp = ((extents[i].start_block + lblkno)
! 785: << (bshift-DEV_BSHIFT)) + hp->h_hmp->offset;
! 786:
! 787: if (ap->a_runp) {
! 788: int nblk;
! 789:
! 790: nblk = extents[i].block_count - lblkno - 1;
! 791: if (nblk <= 0)
! 792: *ap->a_runp = 0;
! 793: else if (nblk > MAXBSIZE >> bshift)
! 794: *ap->a_runp = (MAXBSIZE >> bshift) - 1;
! 795: else
! 796: *ap->a_runp = nblk;
! 797:
! 798: }
! 799:
! 800: free(extents, /*M_HFSMNT*/ M_TEMP);
! 801:
! 802: return 0;
! 803: }
! 804:
! 805: int
! 806: hfs_vop_read(void *v)
! 807: {
! 808: struct vop_read_args /* {
! 809: struct vnode *a_vp;
! 810: struct uio *a_uio;
! 811: int a_ioflag;
! 812: kauth_cred_t a_cred;
! 813: } */ *ap = v;
! 814: struct vnode *vp;
! 815: struct hfsnode *hp;
! 816: struct uio *uio;
! 817: uint64_t fsize; /* logical size of file */
! 818: int advice;
! 819: int error;
! 820:
! 821: vp = ap->a_vp;
! 822: hp = VTOH(vp);
! 823: uio = ap->a_uio;
! 824: if (hp->h_fork == HFS_RSRCFORK)
! 825: fsize = hp->h_rec.file.rsrc_fork.logical_size;
! 826: else
! 827: fsize = hp->h_rec.file.data_fork.logical_size;
! 828: error = 0;
! 829: advice = IO_ADV_DECODE(ap->a_ioflag);
! 830:
! 831: if (uio->uio_offset < 0)
! 832: return EINVAL;
! 833:
! 834: if (uio->uio_resid == 0 || uio->uio_offset >= fsize)
! 835: return 0;
! 836:
! 837: if (vp->v_type != VREG && vp->v_type != VLNK)
! 838: return EINVAL;
! 839:
! 840: error = 0;
! 841: while (uio->uio_resid > 0 && error == 0) {
! 842: int flags;
! 843: vsize_t len;
! 844: void *win;
! 845:
! 846: len = MIN(uio->uio_resid, fsize - uio->uio_offset);
! 847: if (len == 0)
! 848: break;
! 849:
! 850: win = ubc_alloc(&vp->v_uobj, uio->uio_offset, &len,
! 851: advice, UBC_READ);
! 852: error = uiomove(win, len, uio);
! 853: flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0;
! 854: ubc_release(win, flags);
! 855: }
! 856:
! 857: return error;
! 858: }
! 859:
! 860: int
! 861: hfs_vop_readdir(void *v)
! 862: {
! 863: struct vop_readdir_args /* {
! 864: struct vnode *a_vp;
! 865: struct uio *a_uio;
! 866: kauth_cred_t a_cred;
! 867: int *a_eofflag;
! 868: off_t **a_cookies;
! 869: int a_*ncookies;
! 870: } */ *ap = v;
! 871:
! 872: #ifdef HFS_DEBUG
! 873: printf("VOP = hfs_vop_readdir()\n");
! 874: #endif /* HFS_DEBUG */
! 875:
! 876: struct dirent curent; /* the dirent entry we're currently constructing */
! 877: struct hfsnode *hp;
! 878: hfs_catalog_keyed_record_t *children;
! 879: hfs_unistr255_t *childnames;
! 880: hfs_callback_args cbargs;
! 881: hfs_libcb_argsread argsread;
! 882: struct uio *uio;
! 883: off_t bufoff; /* current position in buffer relative to start of dirents */
! 884: uint32_t numchildren;
! 885: uint32_t curchild; /* index of child we're currently stuffing into dirent */
! 886: size_t namlen;
! 887: int error;
! 888: int i; /* dummy variable */
! 889:
! 890: bufoff = 0;
! 891: children = NULL;
! 892: error = 0;
! 893: numchildren = 0;
! 894: hp = VTOH(ap->a_vp);
! 895: uio = ap->a_uio;
! 896:
! 897: if (uio->uio_offset < 0)
! 898: return EINVAL;
! 899: if (ap->a_eofflag != NULL)
! 900: *ap->a_eofflag = 0;
! 901:
! 902: /* XXX Inform that we don't support NFS, for now. */
! 903: /* if(ap->a_eofflag != NULL || ap->a_cookies != NULL || ap->a_ncookies != NULL)
! 904: return EOPNOTSUPP;*/
! 905: /*printf("READDIR uio: offset=%i, resid=%i\n",
! 906: (int)uio->uio_offset, (int)uio->uio_resid);*/
! 907: hfslib_init_cbargs(&cbargs);
! 908: argsread.cred = ap->a_cred;
! 909: argsread.l = NULL;
! 910: cbargs.read = &argsread;
! 911:
! 912: /* XXX Should we cache this? */
! 913: if (hfslib_get_directory_contents(&hp->h_hmp->hm_vol, hp->h_rec.cnid,
! 914: &children, &childnames, &numchildren, &cbargs) != 0) {
! 915: /*printf("NOENT\n");*/
! 916: error = ENOENT;
! 917: goto error;
! 918: }
! 919:
! 920: /*printf("numchildren = %i\n", numchildren);*/
! 921: for (curchild = 0; curchild < numchildren && uio->uio_resid>0; curchild++) {
! 922: namlen = utf16_to_utf8(curent.d_name, MAXNAMLEN,
! 923: childnames[curchild].unicode,
! 924: childnames[curchild].length,
! 925: 0, NULL);
! 926: /* XXX: check conversion errors? */
! 927: if (namlen > MAXNAMLEN) {
! 928: /* XXX: how to handle name too long? */
! 929: continue;
! 930: }
! 931: curent.d_namlen = namlen;
! 932: curent.d_reclen = _DIRENT_SIZE(&curent);
! 933:
! 934: /* Skip to desired dirent. */
! 935: if ((bufoff += curent.d_reclen) - curent.d_reclen < uio->uio_offset)
! 936: continue;
! 937:
! 938: /* Make sure we don't return partial entries. */
! 939: if (uio->uio_resid < curent.d_reclen) {
! 940: /*printf("PARTIAL ENTRY\n");*/
! 941: if (ap->a_eofflag != NULL)
! 942: *ap->a_eofflag = 1;
! 943: break;
! 944: }
! 945:
! 946: curent.d_fileno = children[curchild].file.cnid;
! 947: switch (hfs_catalog_keyed_record_vtype(children+curchild)) {
! 948: case VREG:
! 949: curent.d_type = DT_REG;
! 950: break;
! 951: case VDIR:
! 952: curent.d_type = DT_DIR;
! 953: break;
! 954: case VBLK:
! 955: curent.d_type = DT_BLK;
! 956: break;
! 957: case VCHR:
! 958: curent.d_type = DT_CHR;
! 959: break;
! 960: case VLNK:
! 961: curent.d_type = DT_LNK;
! 962: break;
! 963: case VSOCK:
! 964: curent.d_type = DT_SOCK;
! 965: break;
! 966: case VFIFO:
! 967: curent.d_type = DT_FIFO;
! 968: break;
! 969: default:
! 970: curent.d_type = DT_UNKNOWN;
! 971: break;
! 972: }
! 973: /*printf("curchildname = %s\t\t", curchildname);*/
! 974: /* pad curent.d_name to aligned byte boundary */
! 975: for (i=curent.d_namlen;
! 976: i<curent.d_reclen-_DIRENT_NAMEOFF(&curent); i++)
! 977: curent.d_name[i] = 0;
! 978:
! 979: /*printf("curent.d_name = %s\n", curent.d_name);*/
! 980:
! 981: if ((error = uiomove(&curent, curent.d_reclen, uio)) != 0)
! 982: goto error;
! 983: }
! 984:
! 985:
! 986: /* FALLTHROUGH */
! 987:
! 988: error:
! 989: if (numchildren > 0) {
! 990: if (children != NULL)
! 991: free(children, M_TEMP);
! 992: if (childnames != NULL)
! 993: free(childnames, M_TEMP);
! 994: }
! 995:
! 996: /*if (error)
! 997: printf("ERROR = %i\n", error);*/
! 998: return error;
! 999: }
! 1000:
! 1001: int
! 1002: hfs_vop_readlink(void *v) {
! 1003: struct vop_readlink_args /* {
! 1004: struct vnode *a_vp;
! 1005: struct uio *a_uio;
! 1006: kauth_cred_t a_cred;
! 1007: } */ *ap = v;
! 1008:
! 1009: return VOP_READ(ap->a_vp, ap->a_uio, 0, ap->a_cred);
! 1010: }
! 1011:
! 1012: int
! 1013: hfs_vop_reclaim(void *v)
! 1014: {
! 1015: struct vop_reclaim_args /* {
! 1016: struct vnode *a_vp;
! 1017: struct lwp *a_l;
! 1018: } */ *ap = v;
! 1019: struct vnode *vp;
! 1020: struct hfsnode *hp;
! 1021: struct hfsmount *hmp;
! 1022:
! 1023: #ifdef HFS_DEBUG
! 1024: printf("VOP = hfs_vop_reclaim()\n");
! 1025: #endif /* HFS_DEBUG */
! 1026:
! 1027: vp = ap->a_vp;
! 1028: hp = VTOH(vp);
! 1029: hmp = hp->h_hmp;
! 1030:
! 1031: /* Remove the hfsnode from its hash chain. */
! 1032: hfs_nhashremove(hp);
! 1033:
! 1034: /* Purge name lookup cache. */
! 1035: cache_purge(vp);
! 1036:
! 1037: /* Decrement the reference count to the volume's device. */
! 1038: if (hp->h_devvp) {
! 1039: vrele(hp->h_devvp);
! 1040: hp->h_devvp = 0;
! 1041: }
! 1042:
! 1043: genfs_node_destroy(vp);
! 1044: FREE(vp->v_data, M_TEMP);
! 1045: vp->v_data = 0;
! 1046:
! 1047: return 0;
! 1048: }
! 1049:
! 1050: int
! 1051: hfs_vop_print(void *v)
! 1052: {
! 1053: struct vop_print_args /* {
! 1054: struct vnode *a_vp;
! 1055: } */ *ap = v;
! 1056: struct vnode *vp;
! 1057: struct hfsnode *hp;
! 1058:
! 1059: #ifdef HFS_DEBUG
! 1060: printf("VOP = hfs_vop_print()\n");
! 1061: #endif /* HFS_DEBUG */
! 1062:
! 1063: vp = ap->a_vp;
! 1064: hp = VTOH(vp);
! 1065:
! 1066: printf("dummy = %X\n", (unsigned)hp->dummy);
! 1067: lockmgr_printinfo(&vp->v_lock);
! 1068: printf("\n");
! 1069:
! 1070: return 0;
! 1071: }
CVSweb <webmaster@jp.NetBSD.org>