Annotation of XNU/bsd/hfs/hfs_vfsops.c, revision 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.