[BACK]Return to advfsops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / adosfs

Annotation of src/sys/adosfs/advfsops.c, Revision 1.56

1.56    ! mycroft     1: /*     $NetBSD: advfsops.c,v 1.55 2002/09/21 18:10:04 christos Exp $   */
1.4       cgd         2:
1.1       chopps      3: /*
                      4:  * Copyright (c) 1994 Christian E. Hopps
1.17      mhitch      5:  * Copyright (c) 1996 Matthias Scheler
1.1       chopps      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *      This product includes software developed by Christian E. Hopps.
                     19:  * 4. The name of the author may not be used to endorse or promote products
                     20:  *    derived from this software without specific prior written permission
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32:  */
1.50      lukem      33:
                     34: #include <sys/cdefs.h>
1.56    ! mycroft    35: __KERNEL_RCSID(0, "$NetBSD: advfsops.c,v 1.55 2002/09/21 18:10:04 christos Exp $");
1.29      jonathan   36:
1.46      mrg        37: #if defined(_KERNEL_OPT)
1.29      jonathan   38: #include "opt_compat_netbsd.h"
                     39: #endif
                     40:
1.1       chopps     41: #include <sys/param.h>
                     42: #include <sys/systm.h>
                     43: #include <sys/vnode.h>
                     44: #include <sys/mount.h>
1.2       chopps     45: #include <sys/proc.h>
1.1       chopps     46: #include <sys/time.h>
                     47: #include <sys/malloc.h>
1.31      thorpej    48: #include <sys/pool.h>
1.1       chopps     49: #include <sys/disklabel.h>
                     50: #include <miscfs/specfs/specdev.h> /* XXX */
                     51: #include <sys/fcntl.h>
                     52: #include <sys/namei.h>
                     53: #include <sys/ioctl.h>
                     54: #include <sys/queue.h>
                     55: #include <sys/buf.h>
1.54      gehenna    56: #include <sys/conf.h>
1.1       chopps     57: #include <adosfs/adosfs.h>
                     58:
1.16      christos   59: void adosfs_init __P((void));
1.47      chs        60: void adosfs_reinit __P((void));
1.42      jdolecek   61: void adosfs_done __P((void));
1.24      cgd        62: int adosfs_mount __P((struct mount *, const char *, void *, struct nameidata *,
1.16      christos   63:                      struct proc *));
                     64: int adosfs_start __P((struct mount *, int, struct proc *));
                     65: int adosfs_unmount __P((struct mount *, int, struct proc *));
                     66: int adosfs_root __P((struct mount *, struct vnode **));
                     67: int adosfs_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *));
                     68: int adosfs_statfs __P((struct mount *, struct statfs *, struct proc *));
                     69: int adosfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
                     70: int adosfs_vget __P((struct mount *, ino_t, struct vnode **));
1.35      wrstuden   71: int adosfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
                     72: int adosfs_checkexp __P((struct mount *, struct mbuf *, int *,
                     73:                       struct ucred **));
1.16      christos   74: int adosfs_vptofh __P((struct vnode *, struct fid *));
                     75:
                     76: int adosfs_mountfs __P((struct vnode *, struct mount *, struct proc *));
1.17      mhitch     77: int adosfs_loadbitmap __P((struct adosfsmount *));
1.28      fvdl       78: int adosfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
                     79:                        struct proc *));
                     80:
                     81: struct simplelock adosfs_hashlock;
1.16      christos   82:
1.31      thorpej    83: struct pool adosfs_node_pool;
                     84:
1.49      chs        85: struct genfs_ops adosfs_genfsops = {
                     86:        genfs_size,
                     87: };
1.52      matt       88:
                     89: int (**adosfs_vnodeop_p) __P((void *));
1.49      chs        90:
1.1       chopps     91: int
                     92: adosfs_mount(mp, path, data, ndp, p)
                     93:        struct mount *mp;
1.24      cgd        94:        const char *path;
                     95:        void *data;
1.1       chopps     96:        struct nameidata *ndp;
                     97:        struct proc *p;
                     98: {
1.9       mycroft    99:        struct vnode *devvp;
1.1       chopps    100:        struct adosfs_args args;
1.9       mycroft   101:        struct adosfsmount *amp;
1.12      mycroft   102:        size_t size;
1.1       chopps    103:        int error;
1.9       mycroft   104:        mode_t accessmode;
1.1       chopps    105:
1.55      christos  106:        if (mp->mnt_flag & MNT_GETARGS) {
                    107:                amp = VFSTOADOSFS(mp);
                    108:                if (amp == NULL)
                    109:                        return EIO;
                    110:                args.uid = amp->uid;
                    111:                args.gid = amp->gid;
                    112:                args.mask = amp->mask;
                    113:                args.fspec = NULL;
1.56    ! mycroft   114:                vfs_showexport(mp, &args.export, &amp->export);
1.55      christos  115:                return copyout(&args, data, sizeof(args));
                    116:        }
1.16      christos  117:        error = copyin(data, (caddr_t)&args, sizeof(struct adosfs_args));
                    118:        if (error)
1.1       chopps    119:                return(error);
                    120:
1.9       mycroft   121:        if ((mp->mnt_flag & MNT_RDONLY) == 0)
                    122:                return (EROFS);
                    123:        /*
1.14      chopps    124:         * If updating, check whether changing from read-only to
                    125:         * read/write; if there is no device name, that's all we do.
                    126:         */
                    127:        if (mp->mnt_flag & MNT_UPDATE) {
                    128:                amp = VFSTOADOSFS(mp);
                    129:                if (args.fspec == 0)
                    130:                        return (vfs_export(mp, &amp->export, &args.export));
                    131:        }
                    132:        /*
1.9       mycroft   133:         * Not an update, or updating the name: look up the name
                    134:         * and verify that it refers to a sensible block device.
1.1       chopps    135:         */
1.2       chopps    136:        NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
1.16      christos  137:        if ((error = namei(ndp)) != 0)
1.2       chopps    138:                return (error);
1.9       mycroft   139:        devvp = ndp->ni_vp;
1.2       chopps    140:
1.9       mycroft   141:        if (devvp->v_type != VBLK) {
                    142:                vrele(devvp);
1.2       chopps    143:                return (ENOTBLK);
1.1       chopps    144:        }
1.54      gehenna   145:        if (bdevsw_lookup(devvp->v_rdev) == NULL) {
1.9       mycroft   146:                vrele(devvp);
1.2       chopps    147:                return (ENXIO);
1.1       chopps    148:        }
1.9       mycroft   149:        /*
                    150:         * If mount by non-root, then verify that user has necessary
                    151:         * permissions on the device.
                    152:         */
                    153:        if (p->p_ucred->cr_uid != 0) {
                    154:                accessmode = VREAD;
                    155:                if ((mp->mnt_flag & MNT_RDONLY) == 0)
                    156:                        accessmode |= VWRITE;
1.28      fvdl      157:                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.16      christos  158:                error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
                    159:                if (error) {
1.9       mycroft   160:                        vput(devvp);
                    161:                        return (error);
                    162:                }
1.28      fvdl      163:                VOP_UNLOCK(devvp, 0);
1.9       mycroft   164:        }
1.14      chopps    165: /* MNT_UPDATE? */
1.16      christos  166:        if ((error = adosfs_mountfs(devvp, mp, p)) != 0) {
1.9       mycroft   167:                vrele(devvp);
                    168:                return (error);
                    169:        }
                    170:        amp = VFSTOADOSFS(mp);
                    171:        amp->uid = args.uid;
                    172:        amp->gid = args.gid;
                    173:        amp->mask = args.mask;
                    174:        (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
1.30      perry     175:        memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
1.9       mycroft   176:        (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
                    177:            &size);
1.30      perry     178:        memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
1.9       mycroft   179:        return (0);
1.1       chopps    180: }
                    181:
                    182: int
1.9       mycroft   183: adosfs_mountfs(devvp, mp, p)
                    184:        struct vnode *devvp;
1.1       chopps    185:        struct mount *mp;
                    186:        struct proc *p;
                    187: {
                    188:        struct disklabel dl;
                    189:        struct partition *parp;
1.10      mycroft   190:        struct adosfsmount *amp;
1.17      mhitch    191:        struct buf *bp;
1.2       chopps    192:        struct vnode *rvp;
1.11      cgd       193:        int error, part, i;
1.1       chopps    194:
1.9       mycroft   195:        part = DISKPART(devvp->v_rdev);
1.2       chopps    196:        amp = NULL;
1.9       mycroft   197:
1.1       chopps    198:        /*
1.9       mycroft   199:         * Disallow multiple mounts of the same device.
                    200:         * Disallow mounting of a device that is currently in use
                    201:         * (except for root, which might share swap device for miniroot).
                    202:         * Flush out any old buffers remaining from a previous use.
1.1       chopps    203:         */
1.16      christos  204:        if ((error = vfs_mountedon(devvp)) != 0)
1.2       chopps    205:                return (error);
1.9       mycroft   206:        if (vcount(devvp) > 1 && devvp != rootvp)
1.2       chopps    207:                return (EBUSY);
1.16      christos  208:        if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
1.2       chopps    209:                return (error);
1.1       chopps    210:
                    211:        /*
1.2       chopps    212:         * open blkdev and read root block
1.1       chopps    213:         */
1.16      christos  214:        if ((error = VOP_OPEN(devvp, FREAD, NOCRED, p)) != 0)
1.2       chopps    215:                return (error);
1.16      christos  216:        error = VOP_IOCTL(devvp, DIOCGDINFO,(caddr_t)&dl, FREAD, NOCRED, p);
                    217:        if (error)
1.1       chopps    218:                goto fail;
                    219:
                    220:        parp = &dl.d_partitions[part];
1.10      mycroft   221:        amp = malloc(sizeof(struct adosfsmount), M_ADOSFSMNT, M_WAITOK);
1.30      perry     222:        memset((char *)amp, 0, (u_long)sizeof(struct adosfsmount));
1.1       chopps    223:        amp->mp = mp;
1.17      mhitch    224:        if (dl.d_type == DTYPE_FLOPPY) {
                    225:                amp->bsize = dl.d_secsize;
                    226:                amp->secsperblk = 1;
                    227:        }
                    228:        else {
                    229:                amp->bsize = parp->p_fsize * parp->p_frag;
                    230:                amp->secsperblk = parp->p_frag;
                    231:        }
1.43      jdolecek  232:
                    233:        /* invalid fs ? */
                    234:        if (amp->secsperblk == 0) {
                    235:                error = EINVAL;
                    236:                goto fail;
                    237:        }
1.17      mhitch    238:
                    239:        bp = NULL;
                    240:        if ((error = bread(devvp, (daddr_t)BBOFF,
1.32      bouyer    241:                           amp->bsize, NOCRED, &bp)) != 0) {
                    242:                brelse(bp);
1.17      mhitch    243:                goto fail;
1.32      bouyer    244:        }
1.17      mhitch    245:        amp->dostype = adoswordn(bp, 0);
                    246:        brelse(bp);
                    247:
1.43      jdolecek  248:        /* basic sanity checks */
1.17      mhitch    249:        if (amp->dostype < 0x444f5300 || amp->dostype > 0x444f5305) {
                    250:                error = EINVAL;
                    251:                goto fail;
                    252:        }
1.43      jdolecek  253:
                    254:        amp->rootb = (parp->p_size / amp->secsperblk - 1 + parp->p_cpg) >> 1;
                    255:        amp->numblks = parp->p_size / amp->secsperblk - parp->p_cpg;
1.17      mhitch    256:
1.1       chopps    257:        amp->nwords = amp->bsize >> 2;
1.17      mhitch    258:        amp->dbsize = amp->bsize - (IS_FFS(amp) ? 0 : OFS_DATA_OFFSET);
1.9       mycroft   259:        amp->devvp = devvp;
1.1       chopps    260:
1.53      soren     261:        mp->mnt_data = amp;
1.9       mycroft   262:         mp->mnt_stat.f_fsid.val[0] = (long)devvp->v_rdev;
1.1       chopps    263:         mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_ADOSFS);
1.45      chs       264:        mp->mnt_fs_bshift = ffs(amp->bsize) - 1;
                    265:        mp->mnt_dev_bshift = DEV_BSHIFT;        /* XXX */
1.9       mycroft   266:        mp->mnt_flag |= MNT_LOCAL;
1.1       chopps    267:
                    268:        /*
                    269:         * init anode table.
                    270:         */
                    271:        for (i = 0; i < ANODEHASHSZ; i++)
                    272:                LIST_INIT(&amp->anodetab[i]);
                    273:
                    274:        /*
                    275:         * get the root anode, if not a valid fs this will fail.
                    276:         */
1.16      christos  277:        if ((error = VFS_ROOT(mp, &rvp)) != 0)
1.1       chopps    278:                goto fail;
1.17      mhitch    279:        /* allocate and load bitmap, set free space */
                    280:        amp->bitmap = malloc(((amp->numblks + 31) / 32) * sizeof(*amp->bitmap),
                    281:            M_ADOSFSBITMAP, M_WAITOK);
                    282:        if (amp->bitmap)
                    283:                adosfs_loadbitmap(amp);
                    284:        if (mp->mnt_flag & MNT_RDONLY && amp->bitmap) {
                    285:                /*
                    286:                 * Don't need the bitmap any more if it's read-only.
                    287:                 */
                    288:                free(amp->bitmap, M_ADOSFSBITMAP);
                    289:                amp->bitmap = NULL;
                    290:        }
1.2       chopps    291:        vput(rvp);
                    292:
1.1       chopps    293:        return(0);
1.9       mycroft   294:
1.1       chopps    295: fail:
1.38      wrstuden  296:        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.9       mycroft   297:        (void) VOP_CLOSE(devvp, FREAD, NOCRED, p);
1.38      wrstuden  298:        VOP_UNLOCK(devvp, 0);
1.17      mhitch    299:        if (amp && amp->bitmap)
                    300:                free(amp->bitmap, M_ADOSFSBITMAP);
1.2       chopps    301:        if (amp)
                    302:                free(amp, M_ADOSFSMNT);
1.9       mycroft   303:        return (error);
1.1       chopps    304: }
                    305:
                    306: int
                    307: adosfs_start(mp, flags, p)
                    308:        struct mount *mp;
                    309:        int flags;
                    310:        struct proc *p;
                    311: {
1.9       mycroft   312:
                    313:        return (0);
1.1       chopps    314: }
                    315:
                    316: int
1.9       mycroft   317: adosfs_unmount(mp, mntflags, p)
1.1       chopps    318:        struct mount *mp;
1.9       mycroft   319:        int mntflags;
1.1       chopps    320:        struct proc *p;
                    321: {
1.10      mycroft   322:        struct adosfsmount *amp;
1.9       mycroft   323:        int error, flags;
1.1       chopps    324:
1.9       mycroft   325:        flags = 0;
                    326:        if (mntflags & MNT_FORCE)
                    327:                flags |= FORCECLOSE;
1.16      christos  328:        if ((error = vflush(mp, NULLVP, flags)) != 0)
1.9       mycroft   329:                return (error);
1.1       chopps    330:        amp = VFSTOADOSFS(mp);
1.39      enami     331:        if (amp->devvp->v_type != VBAD)
1.41      tron      332:                amp->devvp->v_specmountpoint = NULL;
1.37      wrstuden  333:        vn_lock(amp->devvp, LK_EXCLUSIVE | LK_RETRY);
1.9       mycroft   334:        error = VOP_CLOSE(amp->devvp, FREAD, NOCRED, p);
1.37      wrstuden  335:        vput(amp->devvp);
1.17      mhitch    336:        if (amp->bitmap)
                    337:                free(amp->bitmap, M_ADOSFSBITMAP);
1.1       chopps    338:        free(amp, M_ADOSFSMNT);
1.53      soren     339:        mp->mnt_data = NULL;
1.2       chopps    340:        mp->mnt_flag &= ~MNT_LOCAL;
                    341:        return (error);
1.1       chopps    342: }
                    343:
                    344: int
                    345: adosfs_root(mp, vpp)
                    346:        struct mount *mp;
                    347:        struct vnode **vpp;
                    348: {
1.2       chopps    349:        struct vnode *nvp;
                    350:        int error;
1.1       chopps    351:
1.16      christos  352:        if ((error = VFS_VGET(mp, (ino_t)VFSTOADOSFS(mp)->rootb, &nvp)) != 0)
1.2       chopps    353:                return (error);
1.17      mhitch    354:        /* XXX verify it's a root block? */
1.2       chopps    355:        *vpp = nvp;
                    356:        return (0);
1.1       chopps    357: }
                    358:
                    359: int
                    360: adosfs_statfs(mp, sbp, p)
                    361:        struct mount *mp;
                    362:        struct statfs *sbp;
                    363:        struct proc *p;
                    364: {
1.10      mycroft   365:        struct adosfsmount *amp;
1.9       mycroft   366:
1.1       chopps    367:        amp = VFSTOADOSFS(mp);
1.28      fvdl      368: #ifdef COMPAT_09
                    369:        sbp->f_type = 16;
                    370: #else
1.1       chopps    371:        sbp->f_type = 0;
1.28      fvdl      372: #endif
1.1       chopps    373:        sbp->f_bsize = amp->bsize;
1.17      mhitch    374:        sbp->f_iosize = amp->dbsize;
                    375:        sbp->f_blocks = amp->numblks;
                    376:        sbp->f_bfree = amp->freeblks;
                    377:        sbp->f_bavail = amp->freeblks;
1.1       chopps    378:        sbp->f_files = 0;               /* who knows */
                    379:        sbp->f_ffree = 0;               /* " " */
                    380:        if (sbp != &mp->mnt_stat) {
1.30      perry     381:                memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN);
                    382:                memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN);
1.1       chopps    383:        }
                    384:        strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
1.9       mycroft   385:        return (0);
1.1       chopps    386: }
                    387:
1.2       chopps    388: /*
                    389:  * lookup an anode, check mount's hash table if not found, create
                    390:  * return locked and referenced al la vget(vp, 1);
                    391:  */
1.1       chopps    392: int
1.2       chopps    393: adosfs_vget(mp, an, vpp)
1.1       chopps    394:        struct mount *mp;
1.2       chopps    395:        ino_t an;
                    396:        struct vnode **vpp;
1.1       chopps    397: {
1.10      mycroft   398:        struct adosfsmount *amp;
1.2       chopps    399:        struct vnode *vp;
                    400:        struct anode *ap;
                    401:        struct buf *bp;
                    402:        char *nam, *tmp;
1.17      mhitch    403:        int namlen, error;
1.2       chopps    404:
                    405:        error = 0;
                    406:        amp = VFSTOADOSFS(mp);
                    407:        bp = NULL;
                    408:
                    409:        /*
                    410:         * check hash table. we are done if found
                    411:         */
1.16      christos  412:        if ((*vpp = adosfs_ahashget(mp, an)) != NULL)
1.2       chopps    413:                return (0);
                    414:
1.16      christos  415:        error = getnewvnode(VT_ADOSFS, mp, adosfs_vnodeop_p, &vp);
                    416:        if (error)
1.2       chopps    417:                return (error);
                    418:
                    419:        /*
                    420:         * setup, insert in hash, and lock before io.
                    421:         */
1.31      thorpej   422:        vp->v_data = ap = pool_get(&adosfs_node_pool, PR_WAITOK);
1.30      perry     423:        memset(ap, 0, sizeof(struct anode));
1.2       chopps    424:        ap->vp = vp;
                    425:        ap->amp = amp;
                    426:        ap->block = an;
                    427:        ap->nwords = amp->nwords;
                    428:        adosfs_ainshash(amp, ap);
                    429:
1.36      is        430:        if ((error = bread(amp->devvp, an * amp->bsize / DEV_BSIZE,
1.17      mhitch    431:                           amp->bsize, NOCRED, &bp)) != 0) {
1.32      bouyer    432:                brelse(bp);
1.2       chopps    433:                vput(vp);
                    434:                return (error);
                    435:        }
                    436:
                    437:        /*
                    438:         * get type and fill rest in based on that.
                    439:         */
                    440:        switch (ap->type = adosfs_getblktype(amp, bp)) {
                    441:        case AROOT:
                    442:                vp->v_type = VDIR;
                    443:                vp->v_flag |= VROOT;
                    444:                ap->mtimev.days = adoswordn(bp, ap->nwords - 10);
                    445:                ap->mtimev.mins = adoswordn(bp, ap->nwords - 9);
                    446:                ap->mtimev.ticks = adoswordn(bp, ap->nwords - 8);
                    447:                ap->created.days = adoswordn(bp, ap->nwords - 7);
                    448:                ap->created.mins = adoswordn(bp, ap->nwords - 6);
                    449:                ap->created.ticks = adoswordn(bp, ap->nwords - 5);
                    450:                break;
                    451:        case ALDIR:
                    452:        case ADIR:
                    453:                vp->v_type = VDIR;
                    454:                break;
                    455:        case ALFILE:
                    456:        case AFILE:
                    457:                vp->v_type = VREG;
                    458:                ap->fsize = adoswordn(bp, ap->nwords - 47);
                    459:                break;
                    460:        case ASLINK:            /* XXX soft link */
                    461:                vp->v_type = VLNK;
                    462:                /*
                    463:                 * convert from BCPL string and
                    464:                 * from: "part:dir/file" to: "/part/dir/file"
                    465:                 */
                    466:                nam = bp->b_data + (6 * sizeof(long));
1.17      mhitch    467:                namlen = strlen(nam);
1.2       chopps    468:                tmp = nam;
1.17      mhitch    469:                while (*tmp && *tmp != ':')
1.2       chopps    470:                        tmp++;
                    471:                if (*tmp == 0) {
                    472:                        ap->slinkto = malloc(namlen + 1, M_ANODE, M_WAITOK);
1.30      perry     473:                        memcpy(ap->slinkto, nam, namlen);
1.2       chopps    474:                } else if (*nam == ':') {
                    475:                        ap->slinkto = malloc(namlen + 1, M_ANODE, M_WAITOK);
1.30      perry     476:                        memcpy(ap->slinkto, nam, namlen);
1.2       chopps    477:                        ap->slinkto[0] = '/';
                    478:                } else {
                    479:                        ap->slinkto = malloc(namlen + 2, M_ANODE, M_WAITOK);
                    480:                        ap->slinkto[0] = '/';
1.30      perry     481:                        memcpy(&ap->slinkto[1], nam, namlen);
1.2       chopps    482:                        ap->slinkto[tmp - nam + 1] = '/';
                    483:                        namlen++;
                    484:                }
                    485:                ap->slinkto[namlen] = 0;
1.19      mhitch    486:                ap->fsize = namlen;
1.2       chopps    487:                break;
                    488:        default:
                    489:                brelse(bp);
                    490:                vput(vp);
                    491:                return (EINVAL);
                    492:        }
1.17      mhitch    493:
                    494:        /*
                    495:         * Get appropriate data from this block;  hard link needs
                    496:         * to get other data from the "real" block.
                    497:         */
                    498:
                    499:        /*
                    500:         * copy in name (from original block)
                    501:         */
1.20      thorpej   502:        nam = bp->b_data + (ap->nwords - 20) * sizeof(u_int32_t);
1.17      mhitch    503:        namlen = *(u_char *)nam++;
                    504:        if (namlen > 30) {
                    505: #ifdef DIAGNOSTIC
1.23      christos  506:                printf("adosfs: aget: name length too long blk %d\n", an);
1.17      mhitch    507: #endif
                    508:                brelse(bp);
                    509:                vput(vp);
                    510:                return (EINVAL);
                    511:        }
1.30      perry     512:        memcpy(ap->name, nam, namlen);
1.17      mhitch    513:        ap->name[namlen] = 0;
                    514:
1.2       chopps    515:        /*
                    516:         * if dir alloc hash table and copy it in
                    517:         */
                    518:        if (vp->v_type == VDIR) {
                    519:                int i;
                    520:
                    521:                ap->tab = malloc(ANODETABSZ(ap) * 2, M_ANODE, M_WAITOK);
                    522:                ap->ntabent = ANODETABENT(ap);
                    523:                ap->tabi = (int *)&ap->tab[ap->ntabent];
1.30      perry     524:                memset(ap->tabi, 0, ANODETABSZ(ap));
1.2       chopps    525:                for (i = 0; i < ap->ntabent; i++)
                    526:                        ap->tab[i] = adoswordn(bp, i + 6);
                    527:        }
                    528:
                    529:        /*
                    530:         * misc.
                    531:         */
                    532:        ap->pblock = adoswordn(bp, ap->nwords - 3);
                    533:        ap->hashf = adoswordn(bp, ap->nwords - 4);
                    534:        ap->linknext = adoswordn(bp, ap->nwords - 10);
                    535:        ap->linkto = adoswordn(bp, ap->nwords - 11);
1.5       chopps    536:
                    537:        /*
                    538:         * setup last indirect block cache.
                    539:         */
                    540:        ap->lastlindblk = 0;
1.17      mhitch    541:        if (ap->type == AFILE)  {
1.5       chopps    542:                ap->lastindblk = ap->block;
1.17      mhitch    543:                if (adoswordn(bp, ap->nwords - 10))
                    544:                        ap->linkto = ap->block;
                    545:        } else if (ap->type == ALFILE) {
1.5       chopps    546:                ap->lastindblk = ap->linkto;
1.17      mhitch    547:                brelse(bp);
                    548:                bp = NULL;
1.36      is        549:                error = bread(amp->devvp, ap->linkto * amp->bsize / DEV_BSIZE,
1.17      mhitch    550:                    amp->bsize, NOCRED, &bp);
1.32      bouyer    551:                if (error) {
                    552:                        brelse(bp);
                    553:                        vput(vp);
                    554:                        return (error);
                    555:                }
1.17      mhitch    556:                ap->fsize = adoswordn(bp, ap->nwords - 47);
                    557:                /*
                    558:                 * Should ap->block be set to the real file header block?
                    559:                 */
                    560:                ap->block = ap->linkto;
                    561:        }
1.5       chopps    562:
1.8       chopps    563:        if (ap->type == AROOT) {
1.17      mhitch    564:                ap->adprot = 15;
1.8       chopps    565:                ap->uid = amp->uid;
                    566:                ap->gid = amp->gid;
                    567:        } else {
1.17      mhitch    568:                ap->adprot = adoswordn(bp, ap->nwords - 48) ^ 15;
1.25      kleink    569:                /*
                    570:                 * ADOS directories do not have a `x' protection bit as
                    571:                 * it is known in VFS; this functionality is fulfilled
                    572:                 * by the ADOS `r' bit.
                    573:                 *
                    574:                 * To retain the ADOS behaviour, fake execute permissions
                    575:                 * in that case.
                    576:                 */
1.26      kleink    577:                if ((ap->type == ADIR || ap->type == ALDIR) &&
                    578:                    (ap->adprot & 0x00000008) == 0)
                    579:                        ap->adprot &= ~0x00000002;
1.25      kleink    580:
1.8       chopps    581:                /*
                    582:                 * Get uid/gid from extensions in file header
                    583:                 * (really need to know if this is a muFS partition)
                    584:                 */
                    585:                ap->uid = (adoswordn(bp, ap->nwords - 49) >> 16) & 0xffff;
                    586:                ap->gid = adoswordn(bp, ap->nwords - 49) & 0xffff;
                    587:                if (ap->uid || ap->gid) {
                    588:                        if (ap->uid == 0xffff)
                    589:                                ap->uid = 0;
                    590:                        if (ap->gid == 0xffff)
                    591:                                ap->gid = 0;
                    592:                        ap->adprot |= 0x40000000;       /* Kludge */
                    593:                }
                    594:                else {
                    595:                        /*
                    596:                         * uid & gid extension don't exist,
                    597:                         * so use the mount-point uid/gid
                    598:                         */
                    599:                        ap->uid = amp->uid;
                    600:                        ap->gid = amp->gid;
                    601:                }
                    602:        }
1.2       chopps    603:        ap->mtime.days = adoswordn(bp, ap->nwords - 23);
                    604:        ap->mtime.mins = adoswordn(bp, ap->nwords - 22);
                    605:        ap->mtime.ticks = adoswordn(bp, ap->nwords - 21);
                    606:
1.49      chs       607:        genfs_node_init(vp, &adosfs_genfsops);
1.48      chs       608:        *vpp = vp;
                    609:        brelse(bp);
                    610:        vp->v_size = ap->fsize;
1.17      mhitch    611:        return (0);
                    612: }
                    613:
                    614: /*
                    615:  * Load the bitmap into memory, and count the number of available
                    616:  * blocks.
                    617:  * The bitmap will be released if the filesystem is read-only;  it's
                    618:  * only needed to find the free space.
                    619:  */
                    620: int
                    621: adosfs_loadbitmap(amp)
                    622:        struct adosfsmount *amp;
                    623: {
                    624:        struct buf *bp, *mapbp;
                    625:        u_long bn;
                    626:        int blkix, endix, mapix;
                    627:        int bmsize;
                    628:        int error;
                    629:
                    630:        bp = mapbp = NULL;
                    631:        bn = amp->rootb;
1.36      is        632:        if ((error = bread(amp->devvp, bn * amp->bsize / DEV_BSIZE, amp->bsize,
1.32      bouyer    633:            NOCRED, &bp)) != 0) {
                    634:                brelse(bp);
1.17      mhitch    635:                return (error);
1.32      bouyer    636:        }
1.17      mhitch    637:        blkix = amp->nwords - 49;
                    638:        endix = amp->nwords - 24;
                    639:        mapix = 0;
                    640:        bmsize = (amp->numblks + 31) / 32;
                    641:        while (mapix < bmsize) {
                    642:                int n;
                    643:                u_long bits;
                    644:
                    645:                if (adoswordn(bp, blkix) == 0)
                    646:                        break;
                    647:                if (mapbp != NULL)
                    648:                        brelse(mapbp);
                    649:                if ((error = bread(amp->devvp,
1.36      is        650:                    adoswordn(bp, blkix) * amp->bsize / DEV_BSIZE, amp->bsize,
1.17      mhitch    651:                     NOCRED, &mapbp)) != 0)
                    652:                        break;
                    653:                if (adoscksum(mapbp, amp->nwords)) {
1.2       chopps    654: #ifdef DIAGNOSTIC
1.23      christos  655:                        printf("adosfs: loadbitmap - cksum of blk %d failed\n",
1.21      christos  656:                            adoswordn(bp, blkix));
1.1       chopps    657: #endif
1.17      mhitch    658:                        /* XXX Force read-only?  Set free space 0? */
                    659:                        break;
                    660:                }
                    661:                n = 1;
                    662:                while (n < amp->nwords && mapix < bmsize) {
                    663:                        amp->bitmap[mapix++] = bits = adoswordn(mapbp, n);
                    664:                        ++n;
                    665:                        if (mapix == bmsize && amp->numblks & 31)
                    666:                                bits &= ~(0xffffffff << (amp->numblks & 31));
                    667:                        while (bits) {
                    668:                                if (bits & 1)
                    669:                                        ++amp->freeblks;
                    670:                                bits >>= 1;
                    671:                        }
                    672:                }
                    673:                ++blkix;
                    674:                if (mapix < bmsize && blkix == endix) {
                    675:                        bn = adoswordn(bp, blkix);
                    676:                        brelse(bp);
1.36      is        677:                        if ((error = bread(amp->devvp, bn * amp->bsize / DEV_BSIZE,
1.17      mhitch    678:                            amp->bsize, NOCRED, &bp)) != 0)
                    679:                                break;
                    680:                        /*
                    681:                         * Why is there no checksum on these blocks?
                    682:                         */
                    683:                        blkix = 0;
                    684:                        endix = amp->nwords - 1;
                    685:                }
                    686:        }
                    687:        if (bp)
1.2       chopps    688:                brelse(bp);
1.17      mhitch    689:        if (mapbp)
                    690:                brelse(mapbp);
                    691:        return (error);
1.1       chopps    692: }
                    693:
1.14      chopps    694:
                    695: /*
                    696:  * File handle to vnode
                    697:  *
                    698:  * Have to be really careful about stale file handles:
                    699:  * - check that the inode number is in range
                    700:  * - call iget() to get the locked inode
                    701:  * - check for an unallocated inode (i_mode == 0)
                    702:  * - check that the generation number matches
                    703:  */
                    704:
                    705: struct ifid {
                    706:        ushort  ifid_len;
                    707:        ushort  ifid_pad;
                    708:        int     ifid_ino;
                    709:        long    ifid_start;
                    710: };
                    711:
1.1       chopps    712: int
1.35      wrstuden  713: adosfs_fhtovp(mp, fhp, vpp)
1.1       chopps    714:        struct mount *mp;
                    715:        struct fid *fhp;
                    716:        struct vnode **vpp;
                    717: {
1.14      chopps    718:        struct ifid *ifhp = (struct ifid *)fhp;
1.16      christos  719: #if 0
1.14      chopps    720:        struct anode *ap;
1.16      christos  721: #endif
1.14      chopps    722:        struct vnode *nvp;
                    723:        int error;
                    724:
1.1       chopps    725: #ifdef ADOSFS_DIAGNOSTIC
1.23      christos  726:        printf("adfhtovp(%x, %x, %x)\n", mp, fhp, vpp);
1.1       chopps    727: #endif
1.14      chopps    728:
1.16      christos  729:        if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
1.14      chopps    730:                *vpp = NULLVP;
                    731:                return (error);
                    732:        }
                    733: #if 0
                    734:        ap = VTOA(nvp);
                    735:        if (ap->inode.iso_mode == 0) {
                    736:                vput(nvp);
                    737:                *vpp = NULLVP;
                    738:                return (ESTALE);
                    739:        }
                    740: #endif
                    741:        *vpp = nvp;
1.35      wrstuden  742:        return(0);
                    743: }
                    744:
                    745: int
                    746: adosfs_checkexp(mp, nam, exflagsp, credanonp)
                    747:        struct mount *mp;
                    748:        struct mbuf *nam;
                    749:        int *exflagsp;
                    750:        struct ucred **credanonp;
                    751: {
                    752:        struct adosfsmount *amp = VFSTOADOSFS(mp);
                    753: #if 0
                    754:        struct anode *ap;
                    755: #endif
                    756:        struct netcred *np;
                    757:
                    758: #ifdef ADOSFS_DIAGNOSTIC
                    759:        printf("adcheckexp(%x, %x, %x)\n", mp, nam, exflagsp);
                    760: #endif
                    761:
                    762:        /*
                    763:         * Get the export permission structure for this <mp, client> tuple.
                    764:         */
                    765:        np = vfs_export_lookup(mp, &amp->export, nam);
                    766:        if (np == NULL)
                    767:                return (EACCES);
                    768:
1.14      chopps    769:        *exflagsp = np->netc_exflags;
                    770:        *credanonp = &np->netc_anon;
1.1       chopps    771:        return(0);
                    772: }
                    773:
                    774: int
                    775: adosfs_vptofh(vp, fhp)
                    776:        struct vnode *vp;
                    777:        struct fid *fhp;
                    778: {
1.14      chopps    779:        struct anode *ap = VTOA(vp);
                    780:        struct ifid *ifhp;
                    781:
                    782:        ifhp = (struct ifid *)fhp;
                    783:        ifhp->ifid_len = sizeof(struct ifid);
                    784:
                    785:        ifhp->ifid_ino = ap->block;
                    786:        ifhp->ifid_start = ap->block;
                    787:
1.1       chopps    788: #ifdef ADOSFS_DIAGNOSTIC
1.23      christos  789:        printf("advptofh(%x, %x)\n", vp, fhp);
1.1       chopps    790: #endif
                    791:        return(0);
                    792: }
                    793:
                    794: int
1.2       chopps    795: adosfs_quotactl(mp, cmds, uid, arg, p)
                    796:        struct mount *mp;
                    797:        int cmds;
                    798:        uid_t uid;
                    799:        caddr_t arg;
                    800:        struct proc *p;
                    801: {
                    802:        return(EOPNOTSUPP);
                    803: }
                    804:
                    805: int
1.16      christos  806: adosfs_sync(mp, waitfor, uc, p)
1.2       chopps    807:        struct mount *mp;
                    808:        int waitfor;
1.16      christos  809:        struct ucred *uc;
                    810:        struct proc *p;
1.1       chopps    811: {
                    812: #ifdef ADOSFS_DIAGNOSTIC
1.23      christos  813:        printf("ad_sync(%x, %x)\n", mp, waitfor);
1.1       chopps    814: #endif
                    815:        return(0);
                    816: }
                    817:
1.16      christos  818: void
1.2       chopps    819: adosfs_init()
                    820: {
1.28      fvdl      821:        simple_lock_init(&adosfs_hashlock);
1.31      thorpej   822:
                    823:        pool_init(&adosfs_node_pool, sizeof(struct anode), 0, 0, 0,
1.51      thorpej   824:            "adosndpl", &pool_allocator_nointr);
1.28      fvdl      825: }
                    826:
1.42      jdolecek  827: void
                    828: adosfs_done()
                    829: {
                    830:        pool_destroy(&adosfs_node_pool);
                    831: }
                    832:
1.28      fvdl      833: int
                    834: adosfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
                    835:        int *name;
                    836:        u_int namelen;
                    837:        void *oldp;
                    838:        size_t *oldlenp;
                    839:        void *newp;
                    840:        size_t newlen;
                    841:        struct proc *p;
                    842: {
                    843:        return (EOPNOTSUPP);
1.2       chopps    844: }
                    845:
1.1       chopps    846: /*
                    847:  * vfs generic function call table
                    848:  */
1.27      thorpej   849:
1.44      jdolecek  850: extern const struct vnodeopv_desc adosfs_vnodeop_opv_desc;
1.27      thorpej   851:
1.44      jdolecek  852: const struct vnodeopv_desc *adosfs_vnodeopv_descs[] = {
1.27      thorpej   853:        &adosfs_vnodeop_opv_desc,
                    854:        NULL,
                    855: };
                    856:
1.1       chopps    857: struct vfsops adosfs_vfsops = {
                    858:        MOUNT_ADOSFS,
                    859:        adosfs_mount,
                    860:        adosfs_start,
                    861:        adosfs_unmount,
                    862:        adosfs_root,
                    863:        adosfs_quotactl,
                    864:        adosfs_statfs,
                    865:        adosfs_sync,
1.2       chopps    866:        adosfs_vget,
1.1       chopps    867:        adosfs_fhtovp,
                    868:        adosfs_vptofh,
                    869:        adosfs_init,
1.47      chs       870:        NULL,
1.42      jdolecek  871:        adosfs_done,
1.28      fvdl      872:        adosfs_sysctl,
1.27      thorpej   873:        NULL,                           /* vfs_mountroot */
1.35      wrstuden  874:        adosfs_checkexp,
1.27      thorpej   875:        adosfs_vnodeopv_descs,
                    876: };

CVSweb <webmaster@jp.NetBSD.org>