Annotation of XNU/bsd/hfs/hfs_vfsops.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999-2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * Copyright (c) 1991, 1993, 1994
                     24:  *     The Regents of the University of California.  All rights reserved.
                     25:  * (c) UNIX System Laboratories, Inc.
                     26:  * All or some portions of this file are derived from material licensed
                     27:  * to the University of California by American Telephone and Telegraph
                     28:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     29:  * the permission of UNIX System Laboratories, Inc.
                     30:  *
                     31:  * Redistribution and use in source and binary forms, with or without
                     32:  * modification, are permitted provided that the following conditions
                     33:  * are met:
                     34:  * 1. Redistributions of source code must retain the above copyright
                     35:  *    notice, this list of conditions and the following disclaimer.
                     36:  * 2. Redistributions in binary form must reproduce the above copyright
                     37:  *    notice, this list of conditions and the following disclaimer in the
                     38:  *    documentation and/or other materials provided with the distribution.
                     39:  * 3. All advertising materials mentioning features or use of this software
                     40:  *    must display the following acknowledgement:
                     41:  *     This product includes software developed by the University of
                     42:  *     California, Berkeley and its contributors.
                     43:  * 4. Neither the name of the University nor the names of its contributors
                     44:  *    may be used to endorse or promote products derived from this software
                     45:  *    without specific prior written permission.
                     46:  *
                     47:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     48:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     49:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     50:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     51:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     52:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     53:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     54:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     55:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     56:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     57:  * SUCH DAMAGE.
                     58:  *
                     59:  *      hfs_vfsops.c
                     60:  *  derived from       @(#)ufs_vfsops.c        8.8 (Berkeley) 5/20/95
                     61:  *
                     62:  *      (c) Copyright 1997-1998 Apple Computer, Inc. All rights reserved.
                     63:  *
                     64:  *      hfs_vfsops.c -- VFS layer for loadable HFS file system.
                     65:  *
                     66:  *      HISTORY
                     67:  *      9-Nov-1999     Don Brady       Fix error handling in hfs_unmount [2399157].
                     68:  *      9-Sep-1999     Don Brady       Clear system file fcbModified flags in hfs_flushvolumeheader/hfs_flushMDB.
                     69:  *      5-Aug-1999     Pat Dirks       Moved special HFS flag from f_fsid.val[0][0] to mount flags (#2293117).
                     70:  *     23-Jul-1999     Pat Dirks       Added special-case code for root's parent directory in hfs_vget (#2263664).
                     71:  *      9-Jun-1999     Don Brady       Fix hfs_mount for reload and read-only downgrade cases.
                     72:  *      2-Jun-1999     Don Brady       Fix hfs_statfs to return correct f_files value.
                     73:  *      4-May-1999     Don Brady       Remove obsolete loadable module code.
                     74:  *     22-Mar-1999     Don Brady       Hide our private meta data in hfs_vget.
                     75:  *             18-May-1999     Don Brady       Add hfs_mountroot for HFS Plus rooting.
                     76:  *             22-Mar-1999     Don Brady       Hide our private meta data in hfs_vget.
                     77:  *              12-Nov-1998     Pat Dirks       Changed hfs_statfs to return volume's actual log. block size (#2286198).
                     78:  *             22-Aug-1998     Scott Roberts   Assign uid,gid, and mask for default on objects.
                     79:  *             29-Jul-1998     Pat Dirks               Fixed changed hfs_vget() to release complex node when retrying for data fork node.
                     80:  *             27-Jul-1998     Scott Roberts   Changes hfs_vget() to return data forks instead of complex.
                     81:  *         14-Jul-1998  CHW                    Added check for use count of device node in hfs_mountfs
                     82:  *         1-Jul-1998  Don Brady               Always set kHFSVolumeUnmountedMask bit of vcb->vcbAtrb in hfs_unmount.
                     83:  *        30-Jun-1998  Don Brady               Removed hard-coded EINVAL error in hfs_mountfs (for radar #2249539).
                     84:  *        24-Jun-1998  Don Brady               Added setting of timezone to hfs_mount (radar #2226387).
                     85:  *             4-Jun-1998      Don Brady               Use VPUT/VRELE macros instead of vput/vrele.
                     86:  *             6-May-1998      Scott Roberts   Updated hfs_vget with kernel changes.
                     87:  *             29-Apr-1998     Don Brady               Update hfs_statfs to actually fill in statfs fields (radar #2227092).
                     88:  *             23-Apr-1998     Pat Dirks               Cleaned up code to call brelse() on errors from bread().
                     89:  *              4/20/1998      Don Brady               Remove course-grained hfs metadata locking.
                     90:  *              4/18/1998      Don Brady               Add VCB locking.
                     91:  *              4/16/1998      Don Brady       hfs_unmount now flushes the volume bitmap. Add b-tree locking to hfs_vget.
                     92:  *               4/8/1998      Don Brady       Replace hfs_mdbupdate with hfs_flushvolumeheader and hfs_flushMDB.
                     93:  *               4/8/1998      Don Brady       In hfs_unmount call hfs_mdbupdate before trashing metafiles!
                     94:  *               4/3/1998      Don Brady       Call InitCatalogCache instead of PostInitFS.
                     95:  *               4/1/1998      Don Brady       Get rid of gHFSFlags, gReqstVol and gFlushOnlyFlag globals (not used).
                     96:  *              3/30/1998      Don Brady       In hfs_unmount use SKIPSYSTEM option on first vflush.
                     97:  *              3/26/1998      Don Brady       Changed hfs_unmount to call vflush before calling hfsUnmount.
                     98:  *                                                             In hfs_mountfs don't mount hfs-wrapper.
                     99:  *              3/19/1998      Pat Dirks       Fixed bug in hfs_mount where device vnode was being
                    100:  *                                                             released on way out.
                    101:  *      11/14/1997     Pat Dirks       Derived from hfs_vfsops.c
                    102:  */
                    103: #include <sys/param.h>
                    104: #include <sys/systm.h>
                    105: 
                    106: #include <sys/namei.h>
                    107: #include <sys/vnode.h>
                    108: #include <sys/mount.h>
                    109: #include <sys/malloc.h>
                    110: #include <sys/stat.h>
                    111: #include <dev/disk.h>
                    112: #include <sys/lock.h>
                    113: 
                    114: #include <miscfs/specfs/specdev.h>
                    115: #include <kern/mapfs.h>
                    116: 
                    117: #include <hfs/hfs_mount.h>
                    118: 
                    119: #include "hfs.h"
                    120: #include "hfs_dbg.h"
                    121: 
                    122: #include "hfscommon/headers/FileMgrInternal.h"
                    123: 
                    124: #if    HFS_DIAGNOSTIC
                    125: int hfs_dbg_all = 0;
                    126: int hfs_dbg_vfs = 0;
                    127: int hfs_dbg_vop = 0;
                    128: int hfs_dbg_load = 0;
                    129: int hfs_dbg_io = 0;
                    130: int hfs_dbg_utils = 0;
                    131: int hfs_dbg_rw = 0;
                    132: int hfs_dbg_lookup = 0;
                    133: int hfs_dbg_tree = 0;
                    134: int hfs_dbg_err = 0;
                    135: int hfs_dbg_test = 0;
                    136: #endif
                    137: 
                    138: /*
                    139:  * HFS File System globals:
                    140:  */
                    141: Ptr                                    gBufferAddress[BUFFERPTRLISTSIZE];
                    142: struct buf                     *gBufferHeaderPtr[BUFFERPTRLISTSIZE];
                    143: int                                    gBufferListIndex;
                    144: simple_lock_data_t     gBufferPtrListLock;
                    145: 
                    146: //static char hfs_fs_name[MFSNAMELEN] = "hfs";
                    147: 
                    148: /* The following represent information held in low-memory on the MacOS: */
                    149: 
                    150: struct FSVarsRec       *gFSMVars;
                    151: 
                    152: /*
                    153:  * Global variables defined in other modules:
                    154:  */
                    155: extern struct vnodeopv_desc hfs_vnodeop_opv_desc;
                    156: 
                    157: extern struct vnode *hfs_vhashget(dev_t dev, UInt32 nodeID, UInt8 forkType);
                    158: 
                    159: extern OSErr HFSPlusToHFSExtents( const HFSPlusExtentRecord    oldExtents, HFSExtentRecord newExtents);
                    160: 
                    161: 
                    162: extern void inittodr( time_t base);
                    163: extern OSErr GetVolumeNameFromCatalog(ExtendedVCB *vcb);
                    164: extern void CopyCatalogToObjectMeta(struct hfsCatalogInfo *catalogInfo, struct vnode *vp, struct hfsfilemeta *fm);
                    165: extern void CopyCatalogToFCB(struct hfsCatalogInfo *catalogInfo, struct vnode *vp);
                    166: 
                    167: int hfs_changefs(struct mount *mp, struct hfs_mount_args *args, struct proc *p);
                    168: 
                    169: int hfs_reload(struct mount *mp, struct ucred *cred, struct proc *p);
                    170: int hfs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p, struct hfs_mount_args *args);
                    171: int hfs_vget(struct mount *mp, void *objID, struct vnode **vpp);
                    172: void hfs_vhashinit();
                    173: void hfs_converterinit(void);
                    174: 
                    175: 
                    176: static int hfs_statfs();
                    177: 
                    178: 
                    179: /*
                    180:  * Called by vfs_mountroot when mounting HFS Plus as root.
                    181:  */
                    182: int
                    183: hfs_mountroot()
                    184: {
                    185:        extern struct vnode *rootvp;
                    186:        struct mount *mp;
                    187:        struct proc *p = current_proc();        /* XXX */
                    188:        struct hfsmount *hfsmp;
                    189:        int error;
                    190:        
                    191:        /*
                    192:         * Get vnode for rootdev.
                    193:         */
                    194:        if ((error = bdevvp(rootdev, &rootvp))) {
                    195:                printf("hfs_mountroot: can't setup bdevvp");
                    196:                return (error);
                    197:        }
                    198:        if ((error = vfs_rootmountalloc("hfs", "root_device", &mp)))
                    199:                return (error);
                    200:        if ((error = hfs_mountfs(rootvp, mp, p, NULL))) {
                    201:                mp->mnt_vfc->vfc_refcount--;
                    202:                vfs_unbusy(mp, p);
                    203:                _FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
                    204:                return (error);
                    205:        }
                    206:        simple_lock(&mountlist_slock);
                    207:        CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
                    208:        simple_unlock(&mountlist_slock);
                    209:        
                    210:        /* Init hfsmp */
                    211:        hfsmp = VFSTOHFS(mp);
                    212: 
                    213:        hfsmp->hfs_dir_mask = (S_IRWXU|S_IRWXG|S_IRWXO);                /* 0777 */
                    214:        hfsmp->hfs_file_mask = (S_IRWXU|S_IRWXG|S_IRWXO);               /* 0777 */
                    215: 
                    216:        (void)hfs_statfs(mp, &mp->mnt_stat, p);
                    217:        
                    218:        vfs_unbusy(mp, p);
                    219:        inittodr(to_bsd_time(HFSTOVCB(hfsmp)->vcbLsMod));
                    220:        return (0);
                    221: }
                    222: 
                    223: 
                    224: /*
                    225:  * VFS Operations.
                    226:  *
                    227:  * mount system call
                    228:  */
                    229: 
                    230: int
                    231: hfs_mount (mp, path, data, ndp, p)
                    232:        register struct mount *mp;
                    233:        char *path;
                    234:        caddr_t data;
                    235:        struct nameidata *ndp;
                    236:        struct proc *p;
                    237: {
                    238:        struct hfsmount *hfsmp = NULL;
                    239:        struct vnode *devvp;
                    240:        struct hfs_mount_args args;
                    241:        size_t size;
                    242:        int retval = E_NONE;
                    243:        int flags;
                    244:        mode_t accessmode;
                    245:        int loadconv = 0;
                    246: 
                    247:        if ((retval = copyin(data, (caddr_t)&args, sizeof(args))))
                    248:                goto error_exit;
                    249: 
                    250:        /*
                    251:         * If updating, check whether changing from read-only to
                    252:         * read/write; if there is no device name, that's all we do.
                    253:         */
                    254:        if (mp->mnt_flag & MNT_UPDATE) {
                    255: 
                    256:                hfsmp = VFSTOHFS(mp);
                    257:                if (hfsmp->hfs_fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
                    258:                
                    259:                        /* use VFS_SYNC to push out System (btree) files */
                    260:                        retval = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p);
                    261:                        if (retval && (mp->mnt_flag & MNT_FORCE) == 0)
                    262:                                goto error_exit;
                    263:                
                    264:                        flags = WRITECLOSE;
                    265:                        if (mp->mnt_flag & MNT_FORCE)
                    266:                                flags |= FORCECLOSE;
                    267:                                
                    268:                        if ((retval = hfs_flushfiles(mp, flags)))
                    269:                                goto error_exit;
                    270:                        hfsmp->hfs_fs_clean = 1;
                    271:                        hfsmp->hfs_fs_ronly = 1;
                    272:                        if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSPlusSigWord)
                    273:                                retval = hfs_flushvolumeheader(hfsmp, MNT_WAIT);
                    274:                        else
                    275:                                retval = hfs_flushMDB(hfsmp, MNT_WAIT);
                    276: 
                    277:                        /* also get the volume bitmap blocks */
                    278:                        if (!retval)
                    279:                                retval = VOP_FSYNC(hfsmp->hfs_devvp, NOCRED, MNT_WAIT, p);
                    280: 
                    281:                        if (retval) {
                    282:                                hfsmp->hfs_fs_clean = 0;
                    283:                                hfsmp->hfs_fs_ronly = 0;
                    284:                                goto error_exit;
                    285:                        }
                    286:                }
                    287: 
                    288:                if ((mp->mnt_flag & MNT_RELOAD) &&
                    289:                        (retval = hfs_reload(mp, ndp->ni_cnd.cn_cred, p)))
                    290:                        goto error_exit;
                    291: 
                    292:                if (hfsmp->hfs_fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
                    293:                        /*
                    294:                         * If upgrade to read-write by non-root, then verify
                    295:                         * that user has necessary permissions on the device.
                    296:                         */
                    297:                        if (p->p_ucred->cr_uid != 0) {
                    298:                                devvp = hfsmp->hfs_devvp;
                    299:                                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
                    300:                                if ((retval = VOP_ACCESS(devvp, VREAD | VWRITE, p->p_ucred, p))) {
                    301:                                        VOP_UNLOCK(devvp, 0, p);
                    302:                                        goto error_exit;
                    303:                                }
                    304:                                VOP_UNLOCK(devvp, 0, p);
                    305:                        }
                    306:                        if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSPlusSigWord)
                    307:                                retval = hfs_flushvolumeheader(hfsmp, MNT_WAIT);
                    308:                        else
                    309:                                retval = hfs_flushMDB(hfsmp, MNT_WAIT);
                    310:        
                    311:                        if (retval != E_NONE)
                    312:                                goto error_exit;
                    313: 
                    314:                        /* only change hfs_fs_ronly after a successfull write */
                    315:                        hfsmp->hfs_fs_ronly = 0;
                    316:                        hfsmp->hfs_fs_clean = 0;
                    317:                }
                    318: 
                    319:                if (hfsmp->hfs_fs_ronly == 0) {
                    320:                        /* setup private/hidden directory for unlinked files */
                    321:                        hfsmp->hfs_private_metadata_dir = FindMetaDataDirectory(HFSTOVCB(hfsmp));
                    322:                }
                    323: 
                    324: #if 0   /* XXX PPD */
                    325:                if (args.fspec == 0) {
                    326:                        /*
                    327:                         * Process export requests.
                    328:                         */
                    329:                        retval = (vfs_export(mp, &hfsmp->hfs_export, &args.export));
                    330:                }
                    331: #endif
                    332: 
                    333:        }
                    334: 
                    335:        /*
                    336:         * Not an update, or updating the name: look up the name
                    337:         * and verify that it refers to a sensible block device.
                    338:         */
                    339:        NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
                    340:        retval = namei(ndp);
                    341:        if (retval != E_NONE) {
                    342:                DBG_ERR(("hfs_mount: CAN'T GET DEVICE: %s, %x\n", args.fspec, ndp->ni_vp->v_rdev));
                    343:                goto error_exit;
                    344:        }
                    345: 
                    346:        devvp = ndp->ni_vp;
                    347: 
                    348:        if (devvp->v_type != VBLK) {
                    349:                VRELE(devvp);
                    350:                retval = ENOTBLK;
                    351:                goto error_exit;
                    352:        }
                    353:        if (major(devvp->v_rdev) >= nblkdev) {
                    354:                VRELE(devvp);
                    355:                retval = ENXIO;
                    356:                goto error_exit;
                    357:        }
                    358: 
                    359:        /*
                    360:         * If mount by non-root, then verify that user has necessary
                    361:         * permissions on the device.
                    362:         */
                    363:        if (p->p_ucred->cr_uid != 0) {
                    364:                accessmode = VREAD;
                    365:                if ((mp->mnt_flag & MNT_RDONLY) == 0)
                    366:                        accessmode |= VWRITE;
                    367:                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
                    368:                if ((retval = VOP_ACCESS(devvp, accessmode, p->p_ucred, p))) {
                    369:                        VPUT(devvp);
                    370:                        goto error_exit;
                    371:                }
                    372:                VOP_UNLOCK(devvp, 0, p);
                    373:        }
                    374: 
                    375:        if ((mp->mnt_flag & MNT_UPDATE) == 0) {
                    376:                retval = hfs_mountfs(devvp, mp, p, &args);
                    377:                if (retval != E_NONE)
                    378:                        VRELE(devvp);
                    379:        } else {
                    380:                if (devvp != hfsmp->hfs_devvp)
                    381:                        retval = EINVAL;        /* needs translation */
                    382:                else
                    383:                        retval = hfs_changefs(mp, &args, p);
                    384:                VRELE(devvp);
                    385:        }
                    386: 
                    387:        if (retval != E_NONE) {
                    388:                goto error_exit;
                    389:        }
                    390: 
                    391:        
                    392:        /* Set the mount flag to indicate that we support volfs  */
                    393:        mp->mnt_flag |= MNT_DOVOLFS;
                    394:     if (VFSTOVCB(mp)->vcbSigWord == kHFSSigWord) {
                    395:        /* HFS volumes only want roman-encoded names: */
                    396:        mp->mnt_flag |= MNT_ROMANONLY;
                    397:     }
                    398:        (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN-1, &size);
                    399:        bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
                    400:        (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size);
                    401:        bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
                    402:        (void)hfs_statfs(mp, &mp->mnt_stat, p);
                    403:        return (E_NONE);
                    404: 
                    405: error_exit:
                    406: 
                    407:        return (retval);
                    408: }
                    409: 
                    410: 
                    411: /* change fs mount parameters */
                    412: int
                    413: hfs_changefs(mp, args, p)
                    414:        struct mount *mp;
                    415:        struct hfs_mount_args *args;
                    416:        struct proc *p;
                    417: {
                    418:        int retval;
                    419:        int namefix, permfix;
                    420:        struct hfsmount *hfsmp;
                    421:        struct hfsnode *hp;
                    422:        mode_t hfs_file_mask;
                    423:        ExtendedVCB *vcb;
                    424:        register struct vnode *vp, *nvp;
                    425: 
                    426:        namefix = permfix = 0;
                    427:        hfsmp = VFSTOHFS(mp);
                    428:        vcb = HFSTOVCB(hfsmp);
                    429: 
                    430:        /* change the hfs timezone (Note: this affects all hfs volumes) */
                    431:        if ((VFSTOVCB(mp)->vcbSigWord == kHFSSigWord)           &&
                    432:            (args->hfs_timezone.tz_minuteswest != VNOVAL)) {
                    433:                gTimeZone = args->hfs_timezone;
                    434:        }
                    435: 
                    436:        /* change the default uid, gid and/or mask */
                    437:        if (args->hfs_uid != (uid_t)VNOVAL && hfsmp->hfs_uid != args->hfs_uid) {
                    438:                hfsmp->hfs_uid = args->hfs_uid;
                    439:                ++permfix;
                    440:        }
                    441:        if (args->hfs_gid != (gid_t)VNOVAL && hfsmp->hfs_gid != args->hfs_gid) {
                    442:                hfsmp->hfs_gid = args->hfs_gid;
                    443:                ++permfix;
                    444:        }
                    445:        if (args->hfs_mask != (mode_t)VNOVAL) {
                    446:                if (hfsmp->hfs_dir_mask != (args->hfs_mask & ALLPERMS)) {
                    447:                        hfsmp->hfs_dir_mask = args->hfs_mask & ALLPERMS;
                    448:                        hfsmp->hfs_file_mask = args->hfs_mask & ALLPERMS;
                    449:                        if ((args->flags != VNOVAL) && (args->flags & HFSFSMNT_NOXONFILES))
                    450:                                hfsmp->hfs_file_mask = (args->hfs_mask & DEFFILEMODE);
                    451:                        ++permfix;
                    452:                }
                    453:        }
                    454: 
                    455:        /* change the hfs encoding value (hfs only) */
                    456:        if ((HFSTOVCB(hfsmp)->vcbSigWord == kHFSSigWord)        &&
                    457:            (hfsmp->hfs_encoding != (u_long)VNOVAL)             &&
                    458:            (hfsmp->hfs_encoding != args->hfs_encoding)) {
                    459:                hfs_to_unicode_func_t   get_unicode_func;
                    460:                unicode_to_hfs_func_t   get_hfsname_func;
                    461: 
                    462:                retval = hfs_getconverter(args->hfs_encoding, &get_unicode_func, &get_hfsname_func);
                    463:                if (retval) goto error_exit;
                    464: 
                    465:                /* now release the old one */
                    466:                (void) hfs_relconverter(hfsmp->hfs_encoding);
                    467: 
                    468:                hfsmp->hfs_encoding = args->hfs_encoding;
                    469:                hfsmp->hfs_get_unicode = get_unicode_func;
                    470:                hfsmp->hfs_get_hfsname = get_hfsname_func;
                    471:                ++namefix;
                    472:        }
                    473: 
                    474: 
                    475:        if (!(namefix || permfix))
                    476:                goto exit;
                    477: 
                    478:        /*
                    479:         * For each active vnode fix things that changed
                    480:         *
                    481:         * Note that we can visit a vnode more than once
                    482:         * and we can race with fsync.
                    483:         */
                    484:        simple_lock(&mntvnode_slock);
                    485: loop:
                    486:        for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
                    487:                /*
                    488:                 * If the vnode that we are about to fix is no longer
                    489:                 * associated with this mount point, start over.
                    490:                 */
                    491:                if (vp->v_mount != mp)
                    492:                    goto loop;
                    493:         
                    494:                simple_lock(&vp->v_interlock);
                    495:                nvp = vp->v_mntvnodes.le_next;
                    496:                if (vp->v_flag & VSYSTEM) {
                    497:                        simple_unlock(&vp->v_interlock);
                    498:                        continue;
                    499:                }
                    500:                simple_unlock(&mntvnode_slock);
                    501:                retval = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
                    502:                if (retval) {
                    503:                    simple_lock(&mntvnode_slock);
                    504:                    if (retval == ENOENT)
                    505:                        goto loop;
                    506:                    continue;
                    507:                }
                    508:        
                    509:                hp = VTOH(vp);
                    510: 
                    511:                if (permfix && (hp->h_meta->h_metaflags & IN_UNSETACCESS)) {
                    512:                        hp->h_meta->h_uid = hfsmp->hfs_uid;
                    513:                        hp->h_meta->h_gid = hfsmp->hfs_gid;
                    514:                        /* Default access is full read/write/execute: */
                    515:                        hp->h_meta->h_mode = ACCESSPERMS;       /* 0777: rwxrwxrwx */
                    516:                
                    517:                        /* ... but no more than that permitted by the mount point's: */
                    518:                        if ((hp->h_meta->h_mode & IFMT) == IFDIR)
                    519:                                hp->h_meta->h_mode &= hfsmp->hfs_dir_mask;
                    520:                        else
                    521:                                hp->h_meta->h_mode &= hfsmp->hfs_file_mask;
                    522:                }
                    523: 
                    524:                if (namefix) {
                    525:                        hfsCatalogInfo catInfo;
                    526: 
                    527:                        /* lookup by fileID since UTF-8 name will change */
                    528:                        catInfo.hint = kNoHint;
                    529:                        if (hfsLookup(vcb, H_FILEID(hp), NULL, -1, &catInfo) == 0) {
                    530:                                H_HINT(hp) = catInfo.hint;
                    531:                                hfs_set_metaname(catInfo.spec.name, hp->h_meta);
                    532:                        }
                    533:                        H_HINT(hp) = catInfo.hint;
                    534:                        hfs_set_metaname(catInfo.spec.name, hp->h_meta);
                    535:                }
                    536: 
                    537:         VPUT(vp);
                    538:         simple_lock(&mntvnode_slock);
                    539: 
                    540:        } /* end for (vp...) */
                    541:        simple_unlock(&mntvnode_slock);
                    542: 
                    543: 
                    544: exit:  
                    545:        return (0);
                    546: 
                    547: error_exit:
                    548: 
                    549:        return (retval);
                    550: }
                    551: 
                    552: 
                    553: /*
                    554:  * Reload all incore data for a filesystem (used after running fsck on
                    555:  * the root filesystem and finding things to fix). The filesystem must
                    556:  * be mounted read-only.
                    557:  *
                    558:  * Things to do to update the mount:
                    559:  *     1) invalidate all cached meta-data.
                    560:  *     2) re-read volume header from disk.
                    561:  *     3) re-load meta-file info (extents, file size).
                    562:  *     4) invalidate all inactive vnodes.
                    563:  *     5) invalidate all cached file data.
                    564:  *     6) re-read hfsnode data for all active vnodes.
                    565:  */
                    566: int
                    567: hfs_reload(mountp, cred, p)
                    568:        register struct mount *mountp;
                    569:        struct ucred *cred;
                    570:        struct proc *p;
                    571: {
                    572:        register struct vnode *vp, *nvp, *devvp;
                    573:        struct hfsnode *hp;
                    574:        struct buf *bp;
                    575:        int     size, error;
                    576:        struct hfsmount *hfsmp;
                    577:        struct HFSPlusVolumeHeader *vhp;
                    578:        ExtendedVCB *vcb;
                    579:        FCB *fcb;
                    580: 
                    581:        if ((mountp->mnt_flag & MNT_RDONLY) == 0)
                    582:                return (EINVAL);
                    583: 
                    584:        hfsmp = VFSTOHFS(mountp);
                    585:        vcb = HFSTOVCB(hfsmp);
                    586: 
                    587:        if (vcb->vcbSigWord == kHFSSigWord)
                    588:                return (EINVAL);        /* rooting from HFS is not supported! */
                    589: 
                    590:        /*
                    591:         * Step 1: invalidate all cached meta-data.
                    592:         */
                    593:        devvp = hfsmp->hfs_devvp;
                    594:        if (vinvalbuf(devvp, 0, cred, p, 0, 0))
                    595:                panic("hfs_reload: dirty1");
                    596:        InvalidateCatalogCache(vcb);
                    597: 
                    598:        /*
                    599:         * Step 2: re-read VolumeHeader from disk.
                    600:         */
                    601:        size = kMDBSize;
                    602:        error = bread(  hfsmp->hfs_devvp,
                    603:                        IOBLKNOFORBLK((vcb->hfsPlusIOPosOffset / 512) + kMasterDirectoryBlock, size),
                    604:                        IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, size),
                    605:                        NOCRED,
                    606:                        &bp);
                    607:        if (error) {
                    608:                if (bp != NULL)
                    609:                        brelse(bp);
                    610:                return (error);
                    611:        }
                    612: 
                    613:        vhp = (HFSPlusVolumeHeader *) ((char *)bp->b_data +
                    614:                        IOBYTEOFFSETFORBLK((vcb->hfsPlusIOPosOffset / 512) + kMasterDirectoryBlock, size));
                    615: 
                    616:        if ((ValidVolumeHeader(vhp) != 0) || (vcb->blockSize != vhp->blockSize)) {
                    617:                brelse(bp);
                    618:                return (EIO);           /* XXX needs translation */
                    619:        }
                    620:        
                    621:        vcb->vcbCrDate = LocalToUTC(vhp->createDate);
                    622:        vcb->vcbLsMod = vhp->modifyDate;
                    623:        vcb->vcbAtrb = (UInt16) vhp->attributes;        /* VCB only uses lower 16 bits */
                    624:        vcb->vcbClpSiz = vhp->rsrcClumpSize;
                    625:        vcb->vcbNxtCNID = vhp->nextCatalogID;
                    626:        vcb->vcbVolBkUp = vhp->backupDate;
                    627:        vcb->vcbWrCnt = vhp->writeCount;
                    628:        vcb->vcbFilCnt = vhp->fileCount;
                    629:        vcb->vcbDirCnt = vhp->folderCount;
                    630:        vcb->nextAllocation = vhp->nextAllocation;
                    631:        vcb->totalBlocks = vhp->totalBlocks;
                    632:        vcb->freeBlocks = vhp->freeBlocks;
                    633:        vcb->checkedDate = vhp->checkedDate;
                    634:        vcb->encodingsBitmap = vhp->encodingsBitmap;
                    635: 
                    636:        bcopy(vhp->finderInfo, vcb->vcbFndrInfo, sizeof(vhp->finderInfo));    
                    637: 
                    638:        /*
                    639:         * Step 3: re-load meta-file vnode data (extent info, file size, etc).
                    640:         */
                    641:        fcb = VTOFCB((struct vnode *)vcb->extentsRefNum);
                    642:        bcopy(vhp->extentsFile.extents, fcb->fcbExtents, sizeof(HFSPlusExtentRecord));
                    643:        fcb->fcbEOF = vhp->extentsFile.logicalSize;
                    644:        fcb->fcbPLen = vhp->extentsFile.totalBlocks * vcb->blockSize;
                    645:        fcb->fcbClmpSize = vhp->extentsFile.clumpSize;
                    646: 
                    647:        fcb = VTOFCB((struct vnode *)vcb->catalogRefNum);
                    648:        bcopy(vhp->catalogFile.extents, fcb->fcbExtents, sizeof(HFSPlusExtentRecord));
                    649:        fcb->fcbPLen = vhp->catalogFile.logicalSize;
                    650:        fcb->fcbPLen = vhp->catalogFile.totalBlocks * vcb->blockSize;
                    651:        fcb->fcbClmpSize = vhp->catalogFile.clumpSize;
                    652: 
                    653:        fcb = VTOFCB((struct vnode *)vcb->allocationsRefNum);
                    654:        bcopy(vhp->allocationFile.extents, fcb->fcbExtents, sizeof(HFSPlusExtentRecord));
                    655:        fcb->fcbEOF = vhp->allocationFile.logicalSize;
                    656:        fcb->fcbPLen = vhp->allocationFile.totalBlocks * vcb->blockSize;
                    657:        fcb->fcbClmpSize = vhp->allocationFile.clumpSize;
                    658: 
                    659:        /* Now that the catalog vnode is ready, get the volume name */
                    660:        if ((error = MacToVFSError( GetVolumeNameFromCatalog(vcb) ))) { 
                    661:                brelse(bp);
                    662:                return (error);
                    663:        }
                    664: 
                    665:        /* reestablish private/hidden directory for unlinked files */
                    666:        hfsmp->hfs_private_metadata_dir = FindMetaDataDirectory(vcb);
                    667: 
                    668:        brelse(bp);
                    669: 
                    670: loop:
                    671:        simple_lock(&mntvnode_slock);
                    672:        for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
                    673:                if (vp->v_mount != mountp) {
                    674:                        simple_unlock(&mntvnode_slock);
                    675:                        goto loop;
                    676:                }
                    677:                nvp = vp->v_mntvnodes.le_next;
                    678: 
                    679:                /*
                    680:                 * Step 4: invalidate all inactive vnodes.
                    681:                 */
                    682:                if (vrecycle(vp, &mntvnode_slock, p))
                    683:                        goto loop;
                    684: 
                    685:                /*
                    686:                 * Step 5: invalidate all cached file data.
                    687:                 */
                    688:                simple_lock(&vp->v_interlock);
                    689:                simple_unlock(&mntvnode_slock);
                    690:                if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
                    691:                        goto loop;
                    692:                }
                    693:                if (vinvalbuf(vp, 0, cred, p, 0, 0))
                    694:                        panic("hfs_reload: dirty2");
                    695: 
                    696:                /*
                    697:                 * Step 6: re-read hfsnode data for all active vnodes (non-metadata files).
                    698:                 */
                    699:                hp = VTOH(vp);
                    700:                if ((vp->v_flag & VSYSTEM) == 0) {
                    701:                        hfsCatalogInfo catInfo;
                    702: 
                    703:                        /* lookup by fileID since name could have changed */
                    704:                        catInfo.hint = kNoHint;
                    705:                        if ((error = hfsLookup(vcb, H_FILEID(hp), NULL, -1, &catInfo))) {
                    706:                                vput(vp);
                    707:                                return (error);
                    708:                        }
                    709:                        H_HINT(hp) = catInfo.hint;
                    710:             if (hp->h_meta->h_metaflags & IN_LONGNAME)
                    711:                                FREE(H_NAME(hp), M_TEMP);
                    712:                        H_NAME(hp) = NULL;
                    713:                        CopyCatalogToObjectMeta(&catInfo, vp, hp->h_meta);
                    714:                        CopyCatalogToFCB(&catInfo, vp);
                    715:                }
                    716: 
                    717:                vput(vp);
                    718:                simple_lock(&mntvnode_slock);
                    719:        }
                    720:        simple_unlock(&mntvnode_slock);
                    721: 
                    722:        return (0);
                    723: }
                    724: 
                    725: 
                    726: /*
                    727:  * Common code for mount and mountroot
                    728:  */
                    729: int
                    730: hfs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p, struct hfs_mount_args *args)
                    731: {
                    732:     int                         retval = E_NONE;
                    733:     register struct hfsmount   *hfsmp;
                    734:     struct buf                                 *bp;
                    735:     dev_t                       dev;
                    736:     HFSMasterDirectoryBlock            *mdbp;
                    737:     int                         ronly;
                    738:     struct ucred                               *cred;
                    739:        u_long diskBlks;
                    740:        u_long blksize;
                    741:     DBG_VFS(("hfs_mountfs: mp = 0x%lX\n", (u_long)mp));
                    742: 
                    743:     dev = devvp->v_rdev;
                    744:     cred = p ? p->p_ucred : NOCRED;
                    745:     /*
                    746:      * Disallow multiple mounts of the same device.
                    747:      * Disallow mounting of a device that is currently in use
                    748:      * (except for root, which might share swap device for miniroot).
                    749:      * Flush out any old buffers remaining from a previous use.
                    750:      */
                    751:     if ((retval = vfs_mountedon(devvp)))
                    752:         return (retval);
                    753:     if (vcount(devvp) > 1 && devvp != rootvp)
                    754:                 return (EBUSY);
                    755:     if ((retval = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)))
                    756:         return (retval);
                    757: 
                    758:     ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
                    759:     DBG_VFS(("hfs_mountfs: opening device...\n"));
                    760:     if ((retval = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)))
                    761:         return (retval);
                    762: 
                    763:     blksize = kHFSBlockSize;
                    764:     DBG_VFS(("hfs_mountfs: size = %d (DEV_BSIZE = %d).\n", blksize, DEV_BSIZE));
                    765: 
                    766:     bp = NULL;
                    767:     hfsmp = NULL;
                    768: 
                    769:        /*      
                    770:         * XXX SER Currently we only support 512 block size systems. This might change
                    771:         * So this is a place holder to remind us that the mdb might not be 512 aligned
                    772:         * retval = VOP_IOCTL(devvp, DKIOCGETBLOCKSIZE, &blksize, FWRITE, cred, p);
                    773:         * if (retval) return retval;
                    774:         */
                    775: 
                    776:        retval = VOP_IOCTL(devvp, DKIOCSETBLOCKSIZE, &blksize, FWRITE, cred, p);
                    777:        if (retval) return retval;
                    778: 
                    779: 
                    780:     DBG_VFS(("hfs_mountfs: reading MDB [block no. %d + %d bytes, size %d bytes]...\n",
                    781:              IOBLKNOFORBLK(kMasterDirectoryBlock, blksize),
                    782:              IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, blksize),
                    783:              IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, blksize)));
                    784: 
                    785:     if ((retval = bread(devvp, IOBLKNOFORBLK(kMasterDirectoryBlock, blksize),
                    786:                                                   IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, blksize), cred, &bp))) {
                    787:         goto error_exit;
                    788:        };
                    789:     mdbp = (HFSMasterDirectoryBlock*) ((char *)bp->b_data + IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, blksize));
                    790: 
                    791:     MALLOC(hfsmp, struct hfsmount *, sizeof(struct hfsmount), M_HFSMNT, M_WAITOK);
                    792:     bzero(hfsmp, sizeof(struct hfsmount));
                    793: 
                    794:     DBG_VFS(("hfs_mountfs: Initializing hfsmount structure at 0x%lX...\n", (u_long)hfsmp));
                    795:     /*
                    796:      *  Init the volume information structure
                    797:      */
                    798:     mp->mnt_data = (qaddr_t)hfsmp;
                    799:     hfsmp->hfs_mp = mp;                                                /* Make VFSTOHFS work */
                    800:     hfsmp->hfs_vcb.vcb_hfsmp = hfsmp;          /* Make VCBTOHFS work */
                    801:     hfsmp->hfs_raw_dev = devvp->v_rdev;
                    802:     hfsmp->hfs_devvp = devvp;
                    803:     hfsmp->hfs_phys_block_size = blksize;
                    804:     /* The hfs_log_block_size field is updated in the respective hfs_MountHFS[Plus]Volume routine */
                    805:     hfsmp->hfs_logBlockSize = BestBlockSizeFit(mdbp->drAlBlkSiz, MAXBSIZE, hfsmp->hfs_phys_block_size);
                    806:     hfsmp->hfs_fs_ronly = ronly;
                    807:        if (args) {
                    808:                hfsmp->hfs_uid = args->hfs_uid;
                    809:                hfsmp->hfs_gid = args->hfs_gid;
                    810:                hfsmp->hfs_dir_mask = args->hfs_mask & ALLPERMS;
                    811:                if (args->flags & HFSFSMNT_NOXONFILES)
                    812:                        hfsmp->hfs_file_mask = (args->hfs_mask & DEFFILEMODE);
                    813:                else
                    814:                        hfsmp->hfs_file_mask = args->hfs_mask & ALLPERMS;
                    815:        }
                    816:        
                    817:        /*      See above comment for DKIOCGETBLOCKSIZE
                    818:         * retval = VOP_IOCTL(devvp, DKIOCSETBLOCKSIZE, &blksize, FWRITE, cred, p);
                    819:         * if (retval) return retval;
                    820:         */
                    821: 
                    822:        retval = VOP_IOCTL(devvp, DKIOCNUMBLKS, &diskBlks, 0, cred, p);
                    823:        if (retval) return retval;
                    824: 
                    825:        if (mdbp->drSigWord == kHFSPlusSigWord) {
                    826:                /* mount wrapper-less HFS-Plus volume */
                    827:                (void) hfs_getconverter(0, &hfsmp->hfs_get_unicode, &hfsmp->hfs_get_hfsname);
                    828:                retval = hfs_MountHFSPlusVolume(hfsmp, (HFSPlusVolumeHeader*) bp->b_data, 0, diskBlks, p);
                    829: 
                    830:        } else if (mdbp->drEmbedSigWord == kHFSPlusSigWord) {
                    831:                u_long embBlkOffset;
                    832:                HFSPlusVolumeHeader     *vhp;
                    833: 
                    834:                embBlkOffset = mdbp->drAlBlSt +
                    835:                    (mdbp->drEmbedExtent.startBlock * (mdbp->drAlBlkSiz/kHFSBlockSize));
                    836:                /* calculate virtual number of 512-byte sectors */
                    837:                diskBlks = mdbp->drEmbedExtent.blockCount * (mdbp->drAlBlkSiz/kHFSBlockSize);
                    838:                brelse(bp);
                    839:                bp = NULL;              /* done with MDB, go grab Volume Header */
                    840:                mdbp = NULL;
                    841: 
                    842:                retval = bread( devvp,
                    843:                                IOBLKNOFORBLK(kMasterDirectoryBlock+embBlkOffset, blksize),
                    844:                                IOBYTECCNTFORBLK(kMasterDirectoryBlock+embBlkOffset, kMDBSize, blksize),
                    845:                                cred,
                    846:                                &bp);
                    847:                if (retval) {
                    848:                        goto error_exit;
                    849:                };
                    850:                vhp = (HFSPlusVolumeHeader*) ((char *)bp->b_data + IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, blksize));
                    851: 
                    852:                /* mount embedded HFS Plus volume */
                    853:                (void) hfs_getconverter(0, &hfsmp->hfs_get_unicode, &hfsmp->hfs_get_hfsname);
                    854:                retval = hfs_MountHFSPlusVolume(hfsmp, vhp, embBlkOffset, diskBlks, p);
                    855: 
                    856:        } else if (devvp != rootvp) {
                    857:                if (args) {
                    858:                        hfsmp->hfs_encoding = args->hfs_encoding;
                    859: 
                    860:                        /* establish the zimezone (not used by HFS Plus) */
                    861:                        gTimeZone = args->hfs_timezone;
                    862:                }
                    863: 
                    864:                retval = hfs_getconverter(hfsmp->hfs_encoding, &hfsmp->hfs_get_unicode, &hfsmp->hfs_get_hfsname);
                    865:                if (retval) goto error_exit;
                    866: 
                    867:                /* mount HFS volume */
                    868:                retval = hfs_MountHFSVolume( hfsmp, mdbp, diskBlks, p);
                    869:                
                    870:                if (retval)
                    871:                        (void) hfs_relconverter(hfsmp->hfs_encoding);
                    872: 
                    873:        } else {
                    874:                /* sorry, we cannot root from HFS */
                    875:                retval = EINVAL;
                    876:        }
                    877: 
                    878:        if ( retval ) {
                    879:                goto error_exit;
                    880:        }
                    881: 
                    882:     brelse(bp);
                    883:     bp = NULL;
                    884:        
                    885:     mp->mnt_stat.f_fsid.val[0] = (long)dev;
                    886:     mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
                    887:     mp->mnt_maxsymlinklen = 0;
                    888:     devvp->v_specflags |= SI_MOUNTEDON;
                    889: 
                    890:     if (ronly == 0) {
                    891:         hfsmp->hfs_fs_clean = 0;
                    892:         if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSPlusSigWord)
                    893:                (void) hfs_flushvolumeheader(hfsmp, MNT_WAIT);
                    894:         else
                    895:                (void) hfs_flushMDB(hfsmp, MNT_WAIT);
                    896:     }
                    897:     goto std_exit;
                    898: 
                    899: error_exit:
                    900:         DBG_VFS(("hfs_mountfs: exiting with error %d...\n", retval));
                    901: 
                    902:     if (bp)
                    903:         brelse(bp);
                    904:     (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
                    905:     if (hfsmp) {
                    906:         FREE(hfsmp, M_HFSMNT);
                    907:         mp->mnt_data = (qaddr_t)0;
                    908:     }
                    909: 
                    910: std_exit:
                    911:         return (retval);
                    912: }
                    913: 
                    914: 
                    915: /*
                    916:  * Make a filesystem operational.
                    917:  * Nothing to do at the moment.
                    918:  */
                    919: /* ARGSUSED */
                    920: int hfs_start(mp, flags, p)
                    921: struct mount *mp;
                    922: int flags;
                    923: struct proc *p;
                    924: {
                    925:     DBG_FUNC_NAME("hfs_start");
                    926:     DBG_PRINT_FUNC_NAME();
                    927: 
                    928:     return (0);
                    929: }
                    930: 
                    931: 
                    932: /*
                    933:  * unmount system call
                    934:  */
                    935: int
                    936: hfs_unmount(mp, mntflags, p)
                    937:        struct mount *mp;
                    938:        int mntflags;
                    939:        struct proc *p;
                    940: {
                    941:        struct hfsmount *hfsmp = VFSTOHFS(mp);
                    942:        int retval = E_NONE;
                    943:        int flags;
                    944: 
                    945:        flags = 0;
                    946:        if (mntflags & MNT_FORCE)
                    947:                flags |= FORCECLOSE;
                    948: 
                    949:        if ((retval = hfs_flushfiles(mp, flags)))
                    950:                return (retval);
                    951: 
                    952:        /*
                    953:         * Flush out the volume bitmap and MDB/Volume Header
                    954:         */
                    955:        if (hfsmp->hfs_fs_ronly == 0) {
                    956:                if (retval = VOP_FSYNC(hfsmp->hfs_devvp, NOCRED, MNT_WAIT, p)) {
                    957:                        if ((mntflags & MNT_FORCE) == 0)
                    958:                                return (retval);
                    959:                }
                    960:                
                    961:                /* See if this volume is damaged, is so do not unmount cleanly */
                    962:                if (HFSTOVCB(hfsmp)->vcbFlags & kHFS_DamagedVolume) {
                    963:                        hfsmp->hfs_fs_clean = 0;
                    964:                        HFSTOVCB(hfsmp)->vcbAtrb &= ~kHFSVolumeUnmountedMask;
                    965:                } else {
                    966:                hfsmp->hfs_fs_clean = 1;
                    967:                HFSTOVCB(hfsmp)->vcbAtrb |= kHFSVolumeUnmountedMask;
                    968:                }
                    969:                if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSPlusSigWord)
                    970:                        retval = hfs_flushvolumeheader(hfsmp, MNT_WAIT);
                    971:                else
                    972:                        retval = hfs_flushMDB(hfsmp, MNT_WAIT);
                    973:        
                    974:                if (retval) {
                    975:                        hfsmp->hfs_fs_clean = 0;
                    976:                        HFSTOVCB(hfsmp)->vcbAtrb &= ~kHFSVolumeUnmountedMask;
                    977:                        if ((mntflags & MNT_FORCE) == 0)
                    978:                                return (retval);        /* could not flush everything */
                    979:                }
                    980:        }
                    981: 
                    982:        /*
                    983:         *      Invalidate our caches and release metadata vnodes
                    984:         */
                    985:        (void) hfsUnmount(hfsmp, p);
                    986: 
                    987:        if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSSigWord)
                    988:                (void) hfs_relconverter(hfsmp->hfs_encoding);
                    989: 
                    990:        hfsmp->hfs_devvp->v_specflags &= ~SI_MOUNTEDON;
                    991:        retval = VOP_CLOSE(hfsmp->hfs_devvp, hfsmp->hfs_fs_ronly ? FREAD : FREAD|FWRITE,
                    992:                        NOCRED, p);
                    993:        VRELE(hfsmp->hfs_devvp);
                    994: 
                    995:        FREE(hfsmp, M_HFSMNT);
                    996:        mp->mnt_data = (qaddr_t)0;
                    997: 
                    998:        return (retval);
                    999: }
                   1000: 
                   1001: 
                   1002: /*
                   1003:  * Return the root of a filesystem.
                   1004:  *
                   1005:  *              OUT - vpp, should be locked and vget()'d (to increment usecount and lock)
                   1006:  */
                   1007: int hfs_root(mp, vpp)
                   1008: struct mount *mp;
                   1009: struct vnode **vpp;
                   1010: {
                   1011:     struct vnode *nvp;
                   1012:     int retval;
                   1013:     UInt32 rootObjID = kRootDirID;
                   1014: 
                   1015:     DBG_FUNC_NAME("hfs_root");
                   1016:     DBG_PRINT_FUNC_NAME();
                   1017: 
                   1018:     if ((retval = VFS_VGET(mp, &rootObjID, &nvp)))
                   1019:         return (retval);
                   1020: 
                   1021:     *vpp = nvp;
                   1022:     return (0);
                   1023: }
                   1024: 
                   1025: /*
                   1026:  * Do operations associated with quotas
                   1027:  */
                   1028: int hfs_quotactl(mp, cmds, uid, arg, p)
                   1029: struct mount *mp;
                   1030: int cmds;
                   1031: uid_t uid;
                   1032: caddr_t arg;
                   1033: struct proc *p;
                   1034: {
                   1035:     DBG_FUNC_NAME("hfs_quotactl");
                   1036:     DBG_PRINT_FUNC_NAME();
                   1037: 
                   1038:     return (EOPNOTSUPP);
                   1039: }
                   1040: 
                   1041: 
                   1042: 
                   1043: /*
                   1044:  * Get file system statistics.
                   1045:  */
                   1046: static int
                   1047: hfs_statfs(mp, sbp, p)
                   1048:        struct mount *mp;
                   1049:        register struct statfs *sbp;
                   1050:        struct proc *p;
                   1051: {
                   1052:        ExtendedVCB *vcb = VFSTOVCB(mp);
                   1053:        struct hfsmount *hfsmp = VFSTOHFS(mp);
                   1054:        u_long freeCNIDs;
                   1055: 
                   1056:        DBG_FUNC_NAME("hfs_statfs");
                   1057:        DBG_PRINT_FUNC_NAME();
                   1058: 
                   1059:        freeCNIDs = (u_long)0xFFFFFFFF - (u_long)vcb->vcbNxtCNID;
                   1060: 
                   1061:        sbp->f_bsize = vcb->blockSize;
                   1062:        sbp->f_iosize = hfsmp->hfs_logBlockSize;
                   1063:        sbp->f_blocks = vcb->totalBlocks;
                   1064:        sbp->f_bfree = vcb->freeBlocks;
                   1065:        sbp->f_bavail = vcb->freeBlocks;
                   1066:        sbp->f_files = vcb->totalBlocks - 2;  /* max files is constrained by total blocks */
                   1067:        sbp->f_ffree = MIN(freeCNIDs, vcb->freeBlocks);
                   1068:        
                   1069:        sbp->f_type = 0;
                   1070:        if (sbp != &mp->mnt_stat) {
                   1071:                sbp->f_type = mp->mnt_vfc->vfc_typenum;
                   1072:                bcopy((caddr_t)mp->mnt_stat.f_mntonname,
                   1073:                        (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
                   1074:                bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
                   1075:                        (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
                   1076:        }
                   1077:        return (0);
                   1078: }
                   1079: 
                   1080: 
                   1081: /*
                   1082:  * Go through the disk queues to initiate sandbagged IO;
                   1083:  * go through the inodes to write those that have been modified;
                   1084:  * initiate the writing of the super block if it has been modified.
                   1085:  *
                   1086:  * Note: we are always called with the filesystem marked `MPBUSY'.
                   1087:  */
                   1088: static int hfs_sync(mp, waitfor, cred, p)
                   1089: struct mount *mp;
                   1090: int waitfor;
                   1091: struct ucred *cred;
                   1092: struct proc *p;
                   1093: {
                   1094:     struct vnode               *nvp, *vp;
                   1095:     struct hfsnode             *hp;
                   1096:     struct hfsmount            *hfsmp = VFSTOHFS(mp);
                   1097:     ExtendedVCB                        *vcb;
                   1098:     int error, allerror = 0;
                   1099: 
                   1100:     DBG_FUNC_NAME("hfs_sync");
                   1101:     DBG_PRINT_FUNC_NAME();
                   1102: 
                   1103:     hfsmp = VFSTOHFS(mp);
                   1104:     if (hfsmp->hfs_fs_ronly != 0) {
                   1105:         panic("update: rofs mod");
                   1106:     };
                   1107: 
                   1108:     /*
                   1109:      * Write back each 'modified' vnode
                   1110:      */
                   1111:     simple_lock(&mntvnode_slock);
                   1112: 
                   1113: loop:;
                   1114: 
                   1115:     for (vp = mp->mnt_vnodelist.lh_first;
                   1116:          vp != NULL;
                   1117:          vp = nvp) {
                   1118:         /*
                   1119:          * If the vnode that we are about to sync is no longer
                   1120:          * associated with this mount point, start over.
                   1121:          */
                   1122:         if (vp->v_mount != mp)
                   1123:             goto loop;
                   1124:         simple_lock(&vp->v_interlock);
                   1125:         nvp = vp->v_mntvnodes.le_next;
                   1126:         hp = VTOH(vp);
                   1127: 
                   1128:         if ((vp->v_type == VNON) || (((hp->h_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) &&
                   1129:             (vp->v_dirtyblkhd.lh_first == NULL))) {
                   1130:             simple_unlock(&vp->v_interlock);
                   1131:             continue;
                   1132:         }
                   1133: 
                   1134:         simple_unlock(&mntvnode_slock);
                   1135:         error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
                   1136:         if (error) {
                   1137:             simple_lock(&mntvnode_slock);
                   1138:             if (error == ENOENT)
                   1139:                 goto loop;
                   1140:             continue;
                   1141:         }
                   1142:                
                   1143:         if ((error = VOP_FSYNC(vp, cred, waitfor, p))) {
                   1144:             DBG_ERR(("hfs_sync: error %d calling fsync on vnode 0x%X.\n", error, (u_int)vp));
                   1145:             allerror = error;
                   1146:         };
                   1147:         DBG_ASSERT(*((volatile int *)(&(vp)->v_interlock))==0);
                   1148:         VPUT(vp);
                   1149:         simple_lock(&mntvnode_slock);
                   1150:     };
                   1151: 
                   1152:        vcb = HFSTOVCB(hfsmp);
                   1153: 
                   1154:     /* Now reprocess the BTree node, stored above */
                   1155:     {
                   1156:     struct vnode               *btvp;
                   1157:         /*
                   1158:          * If the vnode that we are about to sync is no longer
                   1159:          * associated with this mount point, start over.
                   1160:          */
                   1161:         btvp = vcb->extentsRefNum;
                   1162:         if ((btvp==0) || (btvp->v_type == VNON) || (btvp->v_mount != mp))
                   1163:             goto skipBtree;
                   1164:         simple_lock(&btvp->v_interlock);
                   1165:         hp = VTOH(btvp);
                   1166:         if ((hp->h_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
                   1167:             btvp->v_dirtyblkhd.lh_first == NULL) {
                   1168:             simple_unlock(&btvp->v_interlock);
                   1169:             goto skipBtree;
                   1170:         }
                   1171:         simple_unlock(&mntvnode_slock);
                   1172:         error = vget(btvp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
                   1173:         if (error) {
                   1174:             simple_lock(&mntvnode_slock);
                   1175:             goto skipBtree;
                   1176:         }
                   1177:         if ((error = VOP_FSYNC(btvp, cred, waitfor, p)))
                   1178:             allerror = error;
                   1179:         VOP_UNLOCK(btvp, 0, p);
                   1180:         VRELE(btvp);
                   1181:         simple_lock(&mntvnode_slock);
                   1182:     };
                   1183: 
                   1184: skipBtree:;
                   1185: 
                   1186:     simple_unlock(&mntvnode_slock);
                   1187: 
                   1188:     /*
                   1189:      * Force stale file system control information to be flushed.
                   1190:      */
                   1191:     if ((error = VOP_FSYNC(hfsmp->hfs_devvp, cred, waitfor, p)))
                   1192:         allerror = error;
                   1193:     /*
                   1194:      * Write back modified superblock.
                   1195:      */
                   1196: 
                   1197:     if (IsVCBDirty(vcb)) {
                   1198:        if (vcb->vcbSigWord == kHFSPlusSigWord)
                   1199:                error = hfs_flushvolumeheader(hfsmp, waitfor);
                   1200:        else
                   1201:                error = hfs_flushMDB(hfsmp, waitfor);
                   1202:        
                   1203:         if (error)
                   1204:             allerror = error;
                   1205:     };
                   1206: 
                   1207:     return (allerror);
                   1208: }
                   1209: 
                   1210: 
                   1211: /*
                   1212:  * File handle to vnode
                   1213:  *
                   1214:  * Have to be really careful about stale file handles:
                   1215:  * - check that the hfsnode number is valid
                   1216:  * - call hfs_vget() to get the locked hfsnode
                   1217:  * - check for an unallocated hfsnode (i_mode == 0)
                   1218:  * - check that the given client host has export rights and return
                   1219:  *   those rights via. exflagsp and credanonp
                   1220:  */
                   1221: int
                   1222: hfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
                   1223: register struct mount *mp;
                   1224: struct fid *fhp;
                   1225: struct mbuf *nam;
                   1226: struct vnode **vpp;
                   1227: int *exflagsp;
                   1228: struct ucred **credanonp;
                   1229: {
                   1230:     DBG_FUNC_NAME("hfs_fhtovp");
                   1231:     DBG_PRINT_FUNC_NAME();
                   1232: 
                   1233:     return (EOPNOTSUPP);
                   1234: }
                   1235: 
                   1236: /*
                   1237:  * Vnode pointer to File handle
                   1238:  */
                   1239: /* ARGSUSED */
                   1240: static int hfs_vptofh(vp, fhp)
                   1241: struct vnode *vp;
                   1242: struct fid *fhp;
                   1243: {
                   1244:     DBG_FUNC_NAME("hfs_vptofh");
                   1245:     DBG_PRINT_FUNC_NAME();
                   1246: 
                   1247:     return (EOPNOTSUPP);
                   1248: }
                   1249: 
                   1250: 
                   1251: 
                   1252: /*
                   1253:  * Initial HFS filesystems, done only once.
                   1254:  */
                   1255: int
                   1256: hfs_init(vfsp)
                   1257: struct vfsconf *vfsp;
                   1258: {
                   1259:     int i;
                   1260:     static int done = 0;
                   1261:     OSErr err;
                   1262: 
                   1263:     DBG_FUNC_NAME("hfs_init");
                   1264:     DBG_PRINT_FUNC_NAME();
                   1265: 
                   1266:     if (done)
                   1267:         return (0);
                   1268:     done = 1;
                   1269:     hfs_vhashinit();
                   1270:     hfs_converterinit();
                   1271: 
                   1272:     simple_lock_init (&gBufferPtrListLock);
                   1273: 
                   1274:     for (i = BUFFERPTRLISTSIZE - 1; i >= 0; --i) {
                   1275:         gBufferAddress[i] = NULL;
                   1276:         gBufferHeaderPtr[i] = NULL;
                   1277:     };
                   1278:     gBufferListIndex = 0;
                   1279: 
                   1280:     /*
                   1281:      * Do any initialization that the MacOS/MacOS X shared code relies on
                   1282:      * (normally done as part of MacOS's startup):
                   1283:      */
                   1284:     MALLOC(gFSMVars, FSVarsRec *, sizeof(FSVarsRec), M_TEMP, M_WAITOK);
                   1285:     bzero(gFSMVars, sizeof(FSVarsRec));
                   1286: 
                   1287:        /*
                   1288:         * Allocate Catalog Iterator cache...
                   1289:         */
                   1290:        err = InitCatalogCache();
                   1291: #if HFS_DIAGNOSTIC
                   1292:     if (err) panic("hfs_init: Error returned from InitCatalogCache() call.");
                   1293: #endif
                   1294:        /*
                   1295:         * XXX do we need to setup the following?
                   1296:         *
                   1297:         * GMT offset, Unicode globals, CatSearch Buffers, BTSscanner
                   1298:         */
                   1299: 
                   1300:     return E_NONE;
                   1301: }
                   1302: 
                   1303: /*
                   1304:  * fast filesystem related variables.
                   1305:  */
                   1306: static int hfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
                   1307: int *name;
                   1308: u_int namelen;
                   1309: void *oldp;
                   1310: size_t *oldlenp;
                   1311: void *newp;
                   1312: size_t newlen;
                   1313: struct proc *p;
                   1314: {
                   1315:     DBG_FUNC_NAME("hfs_sysctl");
                   1316:     DBG_PRINT_FUNC_NAME();
                   1317: 
                   1318:     return (EOPNOTSUPP);
                   1319: }
                   1320: 
                   1321: /*     This will return a vnode of either a directory or a data vnode based on an object id. If
                   1322:  *  it is a file id, its data fork will be returned.
                   1323:  */
                   1324: 
                   1325: int hfs_vget(struct mount *mp,
                   1326:              void *ino,
                   1327:              struct vnode **vpp)
                   1328: {
                   1329:     struct hfsmount    *hfsmp;
                   1330:     dev_t                              dev;
                   1331:     hfsCatalogInfo             catInfo;
                   1332:     int                                retval = E_NONE;
                   1333: 
                   1334:     DBG_VFS(("hfs_vget: ino = %ld\n", *(UInt32 *)ino));
                   1335: 
                   1336:        /* Check if unmount in progress */
                   1337:        if (mp->mnt_flag & MNT_UNMOUNT) {
                   1338:                return (EPERM);
                   1339:        }
                   1340: 
                   1341:     hfsmp = VFSTOHFS(mp);
                   1342:     dev = hfsmp->hfs_raw_dev;
                   1343:        
                   1344:        /* First check to see if it is in the cache */
                   1345:     *vpp = hfs_vhashget(dev, *(UInt32 *)ino, kDefault);
                   1346: 
                   1347:        /* hide open files that have been deleted */
                   1348:        if (*vpp != NULL && H_DIRID(VTOH(*vpp)) == hfsmp->hfs_private_metadata_dir) {
                   1349:         vput(*vpp);
                   1350:                retval = ENOENT;
                   1351:                goto Err_Exit;
                   1352:        }
                   1353:        
                   1354:        /* The vnode is not in the cache, so lets make it */
                   1355:     if (*vpp == NULL)
                   1356:       {
                   1357:         struct proc                    *p = current_proc();
                   1358:         UInt8                          forkType;
                   1359: 
                   1360:                /* Special-case the root's parent directory (DirID = 1) because
                   1361:                   it doesn't actually exist in the catalog: */
                   1362:                if ((*vpp == NULL) && (*(UInt32 *)ino == kRootParID)) {
                   1363:                        bzero(&catInfo, sizeof(catInfo));
                   1364:                        catInfo.nodeData.cnd_type = kCatalogFolderNode;
                   1365:                        catInfo.nodeData.cnd_nodeID = kRootParID;
                   1366:                        catInfo.nodeData.cnd_valence = 1;
                   1367:                        catInfo.nodeData.cnd_ownerID = 0;
                   1368:                        catInfo.nodeData.cnd_groupID = 0;
                   1369:                        catInfo.nodeData.cnd_permissions = (S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
                   1370:             } else {
                   1371:             /* lock catalog b-tree */
                   1372:             retval = hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_SHARED, p);
                   1373:             if (retval != E_NONE) goto Err_Exit;
                   1374: 
                   1375:                        catInfo.hint = kNoHint;
                   1376:             retval = hfsLookup(VFSTOVCB(mp), *(UInt32 *)ino, NULL, -1, &catInfo);
                   1377: 
                   1378:             /* unlock catalog b-tree */
                   1379:             (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, p);
                   1380: 
                   1381:             if (retval != E_NONE) goto Err_Exit;
                   1382: 
                   1383:             /* hide open files that have been deleted */
                   1384:             if (catInfo.spec.parID == hfsmp->hfs_private_metadata_dir) {
                   1385:                 retval = ENOENT;
                   1386:                 goto Err_Exit;
                   1387:                 };
                   1388:             };
                   1389:         forkType = (catInfo.nodeData.cnd_type == kCatalogFolderNode) ? kDirectory : kDataFork;
                   1390:         retval = hfs_vcreate(VFSTOVCB(mp), &catInfo, forkType, vpp);
                   1391:       };
                   1392: 
                   1393: #if MACH_NBC
                   1394:     if (*vpp && ((*vpp)->v_type == VREG)  && !((*vpp)->v_vm_info)){
                   1395:         vm_info_init(*vpp);
                   1396:     }
                   1397: #endif /* MACH_NBC */
                   1398: 
                   1399: Err_Exit:
                   1400: 
                   1401:        if (retval != E_NONE) {
                   1402:         DBG_VFS(("hfs_vget: Error returned of %d\n", retval));
                   1403:                }
                   1404:        else {
                   1405:         DBG_VFS(("hfs_vget: vp = 0x%x\n", (u_int)*vpp));
                   1406:                }
                   1407: 
                   1408:     return (retval);
                   1409: 
                   1410: }
                   1411: 
                   1412: /*
                   1413:  * Flush out all the files in a filesystem.
                   1414:  */
                   1415: int
                   1416: hfs_flushfiles(struct mount *mp, int flags)
                   1417: {
                   1418:        int error;
                   1419: 
                   1420:        error = vflush(mp, NULLVP, SKIPSYSTEM | flags);
                   1421: 
                   1422:        return (error);
                   1423: }
                   1424: 
                   1425: short hfs_flushMDB(struct hfsmount *hfsmp, int waitfor)
                   1426: {
                   1427:        ExtendedVCB                     *vcb = HFSTOVCB(hfsmp);
                   1428:        FCB                                             *fcb;
                   1429:        HFSMasterDirectoryBlock *mdb;
                   1430:        struct buf                              *bp;
                   1431:        int                                             retval;
                   1432:        int                     size = kMDBSize;        /* 512 */
                   1433:        size_t                                  namelen;
                   1434: 
                   1435:        if (vcb->vcbSigWord != kHFSSigWord)
                   1436:                return EINVAL;
                   1437: 
                   1438:     DBG_ASSERT(hfsmp->hfs_devvp != NULL);
                   1439: 
                   1440:        retval = bread(hfsmp->hfs_devvp, IOBLKNOFORBLK(kMasterDirectoryBlock, size),
                   1441:                                        IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, size), NOCRED, &bp);
                   1442:        if (retval) {
                   1443:            DBG_VFS((" hfs_flushMDB bread return error! (%d)\n", retval));
                   1444:                if (bp) brelse(bp);
                   1445:                return retval;
                   1446:        }
                   1447: 
                   1448:     DBG_ASSERT(bp != NULL);
                   1449:     DBG_ASSERT(bp->b_data != NULL);
                   1450:     DBG_ASSERT(bp->b_bcount == size);
                   1451: 
                   1452:        mdb = (HFSMasterDirectoryBlock *)((char *)bp->b_data + IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, size));
                   1453: 
                   1454:        VCB_LOCK(vcb);
                   1455:        mdb->drCrDate   = UTCToLocal(vcb->vcbCrDate);
                   1456:        mdb->drLsMod    = UTCToLocal(vcb->vcbLsMod);
                   1457:        mdb->drAtrb             = vcb->vcbAtrb;
                   1458:        mdb->drNmFls    = vcb->vcbNmFls;
                   1459:        mdb->drAllocPtr = vcb->nextAllocation;
                   1460:        mdb->drClpSiz   = vcb->vcbClpSiz;
                   1461:        mdb->drNxtCNID  = vcb->vcbNxtCNID;
                   1462:        mdb->drFreeBks  = vcb->freeBlocks;
                   1463: 
                   1464:        /* XXX need to do a real UTF-8 conversion here... */
                   1465:        copystr(vcb->vcbVN, &mdb->drVN[1], sizeof(mdb->drVN)-1, &namelen);
                   1466:        mdb->drVN[0] = namelen-1;
                   1467:        mdb->drVN[namelen] = '\0';
                   1468:        
                   1469:        mdb->drVolBkUp  = UTCToLocal(vcb->vcbVolBkUp);
                   1470:        mdb->drVSeqNum  = vcb->vcbVSeqNum;
                   1471:        mdb->drWrCnt    = vcb->vcbWrCnt;
                   1472:        mdb->drNmRtDirs = vcb->vcbNmRtDirs;
                   1473:        mdb->drFilCnt   = vcb->vcbFilCnt;
                   1474:        mdb->drDirCnt   = vcb->vcbDirCnt;
                   1475:        
                   1476:        bcopy(vcb->vcbFndrInfo, mdb->drFndrInfo, sizeof(mdb->drFndrInfo));
                   1477: 
                   1478:        fcb = VTOFCB(vcb->extentsRefNum);
                   1479:        HFSPlusToHFSExtents(fcb->fcbExtents, mdb->drXTExtRec);
                   1480:        mdb->drXTFlSize = fcb->fcbPLen;
                   1481:        mdb->drXTClpSiz = fcb->fcbClmpSize;
                   1482:        
                   1483:        fcb = VTOFCB(vcb->catalogRefNum);
                   1484:        HFSPlusToHFSExtents(fcb->fcbExtents, mdb->drCTExtRec);
                   1485:        mdb->drCTFlSize = fcb->fcbPLen;
                   1486:        mdb->drCTClpSiz = fcb->fcbClmpSize;
                   1487:        VCB_UNLOCK(vcb);
                   1488: 
                   1489: 
                   1490:     if (waitfor != MNT_WAIT)
                   1491:                bawrite(bp);
                   1492:     else 
                   1493:                retval = bwrite(bp);
                   1494:  
                   1495:        MarkVCBClean( vcb );
                   1496: 
                   1497:        return (retval);
                   1498: }
                   1499: 
                   1500: 
                   1501: short hfs_flushvolumeheader(struct hfsmount *hfsmp, int waitfor)
                   1502: {
                   1503:     ExtendedVCB                        *vcb = HFSTOVCB(hfsmp);
                   1504:     FCB                                                *fcb;
                   1505:     HFSPlusVolumeHeader                *volumeHeader;
                   1506:     int                                                retval;
                   1507:     int                     size = sizeof(HFSPlusVolumeHeader);
                   1508:     struct buf                                 *bp;
                   1509: 
                   1510:        if (vcb->vcbSigWord != kHFSPlusSigWord)
                   1511:                return EINVAL;
                   1512: 
                   1513:        retval = bread(hfsmp->hfs_devvp, IOBLKNOFORBLK((vcb->hfsPlusIOPosOffset / 512) + kMasterDirectoryBlock, size),
                   1514:                                        IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, size), NOCRED, &bp);
                   1515:        if (retval) {
                   1516:            DBG_VFS((" hfs_flushvolumeheader bread return error! (%d)\n", retval));
                   1517:                if (bp) brelse(bp);
                   1518:                return retval;
                   1519:        }
                   1520: 
                   1521:     DBG_ASSERT(bp != NULL);
                   1522:     DBG_ASSERT(bp->b_data != NULL);
                   1523:     DBG_ASSERT(bp->b_bcount == size);
                   1524: 
                   1525:        volumeHeader = (HFSPlusVolumeHeader *)((char *)bp->b_data +
                   1526:                                        IOBYTEOFFSETFORBLK((vcb->hfsPlusIOPosOffset / 512) + kMasterDirectoryBlock, size));
                   1527: 
                   1528:        /*
                   1529:         * For embedded HFS+ volumes, update create date if neccessary
                   1530:         */
                   1531:        if (vcb->hfsPlusIOPosOffset != 0 && volumeHeader->createDate != UTCToLocal(vcb->vcbCrDate))
                   1532:          {
                   1533:                struct buf                              *bp2;
                   1534:                HFSMasterDirectoryBlock *mdb;
                   1535: 
                   1536:                retval = bread(hfsmp->hfs_devvp, IOBLKNOFORBLK(kMasterDirectoryBlock, kMDBSize),
                   1537:                                                IOBYTECCNTFORBLK(kMasterDirectoryBlock, kMDBSize, kMDBSize), NOCRED, &bp2);
                   1538:                if (retval != E_NONE) {
                   1539:                        if (bp2) brelse(bp2);
                   1540:                } else {
                   1541:                        mdb = (HFSMasterDirectoryBlock *)((char *)bp2->b_data + IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, kMDBSize));
                   1542:                        if ( mdb->drCrDate != UTCToLocal(vcb->vcbCrDate) )
                   1543:                          {
                   1544:                                mdb->drCrDate = UTCToLocal(vcb->vcbCrDate);             /* pick up the new create date */
                   1545:                                (void) bwrite(bp2);                                     /* write out the changes */
                   1546:                          }
                   1547:                        else
                   1548:                          {
                   1549:                                brelse(bp2);                                            /* just release it */
                   1550:                          }
                   1551:                  }     
                   1552:          }
                   1553: 
                   1554:        VCB_LOCK(vcb);
                   1555:        /* Note: only update the lower 16 bits worth of attributes */
                   1556:        volumeHeader->attributes                 =      (volumeHeader->attributes & 0xFFFF0000) + (UInt16) vcb->vcbAtrb;
                   1557:        volumeHeader->lastMountedVersion = kHFSPlusMountVersion;
                   1558:        volumeHeader->createDate = UTCToLocal(vcb->vcbCrDate);
                   1559:        volumeHeader->modifyDate = vcb->vcbLsMod;
                   1560:        volumeHeader->backupDate = vcb->vcbVolBkUp;
                   1561:        volumeHeader->checkedDate = vcb->checkedDate;
                   1562:        volumeHeader->fileCount                  =      vcb->vcbFilCnt;
                   1563:        volumeHeader->folderCount                =      vcb->vcbDirCnt;
                   1564:        volumeHeader->freeBlocks                 =      vcb->freeBlocks;
                   1565:        volumeHeader->nextAllocation     =      vcb->nextAllocation;
                   1566:        volumeHeader->rsrcClumpSize              =      vcb->vcbClpSiz;
                   1567:        volumeHeader->dataClumpSize              =      vcb->vcbClpSiz;
                   1568:        volumeHeader->nextCatalogID              =      vcb->vcbNxtCNID;
                   1569:        volumeHeader->writeCount                 =      vcb->vcbWrCnt;
                   1570:        volumeHeader->encodingsBitmap    =      vcb->encodingsBitmap;
                   1571: 
                   1572:        bcopy( vcb->vcbFndrInfo, volumeHeader->finderInfo, sizeof(volumeHeader->finderInfo) );
                   1573: 
                   1574:        VCB_UNLOCK(vcb);
                   1575: 
                   1576:        fcb = VTOFCB(vcb->extentsRefNum);
                   1577:        bcopy( fcb->fcbExtents, volumeHeader->extentsFile.extents, sizeof(HFSPlusExtentRecord) );
                   1578:        fcb->fcbFlags &= ~fcbModifiedMask;
                   1579:        volumeHeader->extentsFile.logicalSize = fcb->fcbEOF;
                   1580:        volumeHeader->extentsFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
                   1581:        volumeHeader->extentsFile.clumpSize = fcb->fcbClmpSize;
                   1582: 
                   1583:        fcb = VTOFCB(vcb->catalogRefNum);
                   1584:        bcopy( fcb->fcbExtents, volumeHeader->catalogFile.extents, sizeof(HFSPlusExtentRecord) );
                   1585:        fcb->fcbFlags &= ~fcbModifiedMask;
                   1586:        volumeHeader->catalogFile.logicalSize = fcb->fcbEOF;
                   1587:        volumeHeader->catalogFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
                   1588:        volumeHeader->catalogFile.clumpSize = fcb->fcbClmpSize;
                   1589: 
                   1590:        fcb = VTOFCB(vcb->allocationsRefNum);
                   1591:        bcopy( fcb->fcbExtents, volumeHeader->allocationFile.extents, sizeof(HFSPlusExtentRecord) );
                   1592:        fcb->fcbFlags &= ~fcbModifiedMask;
                   1593:        volumeHeader->allocationFile.logicalSize = fcb->fcbEOF;
                   1594:        volumeHeader->allocationFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
                   1595:        volumeHeader->allocationFile.clumpSize = fcb->fcbClmpSize;
                   1596: 
                   1597:     if (waitfor != MNT_WAIT)
                   1598:         bawrite(bp);
                   1599:     else 
                   1600:                retval = bwrite(bp);
                   1601:  
                   1602:        MarkVCBClean( vcb );
                   1603: 
                   1604:        return (retval);
                   1605: }
                   1606: 
                   1607: 
                   1608: /*
                   1609:  *      Moved here to avoid having to define prototypes
                   1610:  */
                   1611: 
                   1612: /*
                   1613:  * hfs vfs operations.
                   1614:  */
                   1615: struct vfsops hfs_vfsops = {
                   1616:     hfs_mount,
                   1617:     hfs_start,
                   1618:     hfs_unmount,
                   1619:     hfs_root,
                   1620:     hfs_quotactl,
                   1621:     hfs_statfs,
                   1622:     hfs_sync,
                   1623:     hfs_vget,
                   1624:     hfs_fhtovp,
                   1625:     hfs_vptofh,
                   1626:     hfs_init,
                   1627:     hfs_sysctl
                   1628: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.