[BACK]Return to hfs_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / hfs

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>