Annotation of kernel/bsd/kern/kern_mman.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:  * Copyright (c) 1988 University of Utah.
        !            27:  * Copyright (c) 1991, 1993
        !            28:  *     The Regents of the University of California.  All rights reserved.
        !            29:  *
        !            30:  * This code is derived from software contributed to Berkeley by
        !            31:  * the Systems Programming Group of the University of Utah Computer
        !            32:  * Science Department.
        !            33:  *
        !            34:  * Redistribution and use in source and binary forms, with or without
        !            35:  * modification, are permitted provided that the following conditions
        !            36:  * are met:
        !            37:  * 1. Redistributions of source code must retain the above copyright
        !            38:  *    notice, this list of conditions and the following disclaimer.
        !            39:  * 2. Redistributions in binary form must reproduce the above copyright
        !            40:  *    notice, this list of conditions and the following disclaimer in the
        !            41:  *    documentation and/or other materials provided with the distribution.
        !            42:  * 3. All advertising materials mentioning features or use of this software
        !            43:  *    must display the following acknowledgement:
        !            44:  *     This product includes software developed by the University of
        !            45:  *     California, Berkeley and its contributors.
        !            46:  * 4. Neither the name of the University nor the names of its contributors
        !            47:  *    may be used to endorse or promote products derived from this software
        !            48:  *    without specific prior written permission.
        !            49:  *
        !            50:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            51:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            52:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            53:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            54:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            55:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            56:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            57:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            58:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            59:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            60:  * SUCH DAMAGE.
        !            61:  *
        !            62:  * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
        !            63:  *
        !            64:  *     @(#)vm_mmap.c   8.10 (Berkeley) 2/19/95
        !            65:  */
        !            66: 
        !            67: /*
        !            68:  * Mapped file (mmap) interface to VM
        !            69:  */
        !            70: 
        !            71: #import <sys/param.h>
        !            72: #import <sys/systm.h>
        !            73: #import <sys/filedesc.h>
        !            74: #import <sys/proc.h>
        !            75: #import <sys/resourcevar.h>
        !            76: #import <sys/buf.h>
        !            77: #import <sys/vnode.h>
        !            78: #import <sys/acct.h>
        !            79: #import <sys/wait.h>
        !            80: #import <sys/file.h>
        !            81: #import <sys/vadvise.h>
        !            82: #import <sys/trace.h>
        !            83: #import <sys/mman.h>
        !            84: #import <sys/conf.h>
        !            85: #import <mach/kern_return.h>
        !            86: #import <kern/task.h>
        !            87: #import <mach/vm_param.h>
        !            88: #import <vm/vm_map.h>
        !            89: #import <vm/vm_pager.h>
        !            90: #import <vm/vnode_pager.h>
        !            91: #import <kern/mapfs.h>
        !            92: #import <miscfs/specfs/specdev.h>
        !            93: 
        !            94: struct sbrk_args {
        !            95:                int     incr;
        !            96: };
        !            97: 
        !            98: /* ARGSUSED */
        !            99: int
        !           100: sbrk(p, uap, retval)
        !           101:        struct proc *p;
        !           102:        struct sbrk_args *uap;
        !           103:        register_t *retval;
        !           104: {
        !           105:        /* Not yet implemented */
        !           106:        kprintf("sbrk(): not supported!\n");
        !           107:        return (EOPNOTSUPP);
        !           108: }
        !           109: 
        !           110: struct sstk_args {
        !           111:        int     incr;
        !           112: } *uap;
        !           113: 
        !           114: /* ARGSUSED */
        !           115: int
        !           116: sstk(p, uap, retval)
        !           117:        struct proc *p;
        !           118:        struct sstk_args *uap;
        !           119:        register_t *retval;
        !           120: {
        !           121:        /* Not yet implemented */
        !           122:        kprintf("sstk(): not supported!\n");
        !           123:        return (EOPNOTSUPP);
        !           124: }
        !           125: 
        !           126: #if COMPAT_43
        !           127: /* ARGSUSED */
        !           128: int
        !           129: ogetpagesize(p, uap, retval)
        !           130:        struct proc *p;
        !           131:        void *uap;
        !           132:        register_t *retval;
        !           133: {
        !           134: 
        !           135:        *retval = PAGE_SIZE;
        !           136:        return (0);
        !           137: }
        !           138: #endif /* COMPAT_43 */
        !           139: 
        !           140: struct osmmap_args {
        !           141:                caddr_t addr;
        !           142:                int     len;
        !           143:                int     prot;
        !           144:                int     share;
        !           145:                int     fd;
        !           146:                long    pos;
        !           147: };
        !           148: 
        !           149: osmmap(curp, uap, retval)
        !           150:        struct proc *curp;
        !           151:        register struct osmmap_args *uap;
        !           152:        register_t *retval;
        !           153: {
        !           154: struct mmap_args {
        !           155:                caddr_t addr;
        !           156:                size_t len;
        !           157:                int prot;
        !           158:                int flags;
        !           159:                int fd;
        !           160: #ifdef DOUBLE_ALIGN_PARAMS
        !           161:                long pad;
        !           162: #endif
        !           163:                off_t pos;
        !           164: } newargs;
        !           165: 
        !           166:        if ((uap->share ==  MAP_SHARED )|| (uap->share ==  MAP_PRIVATE )) {
        !           167:                newargs.addr = uap->addr;
        !           168:                newargs.len = (size_t)uap->len;
        !           169:                newargs.prot = uap->prot;
        !           170:                newargs.flags = uap->share;
        !           171:                newargs.fd = uap->fd;
        !           172:                newargs.pos = (off_t)uap->pos;
        !           173:                return(mmap(curp,&newargs, retval));
        !           174:        } else
        !           175:                return(EINVAL); 
        !           176: }
        !           177: 
        !           178: struct mmap_args {
        !           179:                caddr_t addr;
        !           180:                size_t len;
        !           181:                int prot;
        !           182:                int flags;
        !           183:                int fd;
        !           184: #ifdef DOUBLE_ALIGN_PARAMS
        !           185:                long pad;
        !           186: #endif
        !           187:                off_t pos;
        !           188: };
        !           189: 
        !           190: mmap(p, uap, retval)
        !           191:        struct proc *p;
        !           192:        struct mmap_args *uap;
        !           193:        register_t *retval;
        !           194: {
        !           195:        /*
        !           196:         *      Map in special device (must be SHARED) or file
        !           197:         */
        !           198:        struct file *fp;
        !           199:        register struct vnode *vp;
        !           200:        int             flags;
        !           201:        int             prot;
        !           202:        int             err=0;
        !           203:        vm_map_t        user_map;
        !           204:        kern_return_t   result;
        !           205:        vm_offset_t     user_addr;
        !           206:        vm_size_t       user_size;
        !           207:        vm_offset_t     file_pos;
        !           208:        boolean_t       find_space;
        !           209:        extern vm_object_t      vm_object_special();
        !           210: 
        !           211:        user_addr = (vm_offset_t)uap->addr;
        !           212:        user_size = (vm_size_t) uap->len;
        !           213: 
        !           214:        prot = (uap->prot & VM_PROT_ALL);
        !           215:        flags = uap->flags;
        !           216: 
        !           217:        /*
        !           218:         * The vm code does not have prototypes & compileser doesn't do the'
        !           219:         * the right thing when you cast 64bit value and pass it in function 
        !           220:         * call. So here it is.
        !           221:         */
        !           222:        file_pos = (vm_offset_t)uap->pos;
        !           223: 
        !           224:        /* Anonymous mapping not supported, for now. */
        !           225:        if (((flags & MAP_FIXED) && !page_aligned(user_addr)) ||
        !           226:                                (user_size < 0) || (flags & MAP_ANON)) {
        !           227:                return(EINVAL);
        !           228:        }
        !           229: 
        !           230:        err = fdgetf(p, uap->fd, &fp);
        !           231:        if (err)
        !           232:                return(err);
        !           233: 
        !           234:        if (fp->f_type != DTYPE_VNODE)
        !           235:                return(EBADF);
        !           236:        vp = (struct vnode *)fp->f_data;
        !           237: 
        !           238:        /*
        !           239:         *      We bend a little - round the start and end addresses
        !           240:         *      to the nearest page boundary.
        !           241:         */
        !           242:        user_addr = trunc_page(user_addr);
        !           243:        user_size = round_page(user_size);
        !           244: 
        !           245:        /*
        !           246:         *      File can be COPIED at an arbitrary offset.
        !           247:         *      File can only be SHARED if the offset is at a
        !           248:         *      page boundary.
        !           249:         */
        !           250: 
        !           251:        if ((flags & MAP_SHARED) && ((vm_offset_t)file_pos & page_mask)) {
        !           252:                return(EINVAL);
        !           253:        }
        !           254: 
        !           255:        /*
        !           256:         *      File must be writable if memory will be.
        !           257:         */
        !           258:        if ((prot & PROT_WRITE) && (fp->f_flag&FWRITE) == 0) {
        !           259:                if ((flags & MAP_PRIVATE) == 0) {
        !           260:                /*  #2211802 */
        !           261:                /* If private map, its okay to have write access 
        !           262:                   as allocated space is both read and write
        !           263:                 */
        !           264:                        return(EACCES);
        !           265:                }
        !           266:        }
        !           267:        if ((prot & PROT_READ) && (fp->f_flag&FREAD) == 0) {
        !           268:                return(EACCES);
        !           269:        }
        !           270:        /*
        !           271:         * Bug# 2203998 ->  zero sized length is a valid arg
        !           272:         *      in 4.4; for ex, copy of zero sized file
        !           273:         *      will call mmap with length 0
        !           274:         */
        !           275:        if (user_size == 0) 
        !           276:                return(0);
        !           277: 
        !           278:        /*
        !           279:         *      memory must exist and be writable (even if we're
        !           280:         *      just reading)
        !           281:         */
        !           282: 
        !           283:        user_map = current_task()->map;
        !           284: 
        !           285: #if 0
        !           286:        if (!vm_map_check_protection(user_map, user_addr,
        !           287:                                (vm_offset_t)(user_addr + user_size),
        !           288:                                VM_PROT_READ|VM_PROT_WRITE)) {
        !           289:                return(EINVAL);
        !           290:        }
        !           291: #endif
        !           292:        if (flags & MAP_FIXED) {
        !           293:                find_space = FALSE;
        !           294:        } else {
        !           295:                find_space = TRUE;
        !           296:        }
        !           297: 
        !           298:        if (vp->v_type == VCHR || vp->v_type == VSTR) {
        !           299:                return(EOPNOTSUPP);
        !           300:        }
        !           301:        else {
        !           302:                /*
        !           303:                 *      Map in a file.  May be PRIVATE (copy-on-write)
        !           304:                 *      or SHARED (changes go back to file)
        !           305:                 */
        !           306:                vm_pager_t      pager;
        !           307:                vm_map_t        copy_map;
        !           308:                vm_offset_t     off;
        !           309:                struct vm_info  *vmp;
        !           310: 
        !           311:                /*
        !           312:                 *      Only allow regular files for the moment.
        !           313:                 */
        !           314:                if (vp->v_type != VREG) {
        !           315:                        return(EBADF);
        !           316:                }
        !           317:                
        !           318:                pager = vnode_pager_setup(vp, FALSE, TRUE);
        !           319:                
        !           320:                /*
        !           321:                 *  Set credentials:
        !           322:                 *      FIXME: if we're writing the file we need a way to
        !           323:                 *      ensure that someone doesn't replace our R/W creds
        !           324:                 *      with ones that only work for read.
        !           325:                 */
        !           326:                vmp = vp->v_vm_info;
        !           327:                if (vmp->cred == NULL) {                        
        !           328:                        crhold(p->p_ucred);
        !           329:                        vmp->cred = p->p_ucred;
        !           330:                }
        !           331:                /* Find space if not MAP_FIXED; otherwise validate */
        !           332:                /* This also fixes 2215605 */
        !           333:                result = vm_map_find(user_map, NULL, (vm_offset_t) 0,
        !           334:                                        &user_addr, user_size, find_space);
        !           335:                if (result != KERN_SUCCESS) {
        !           336:                        goto out;
        !           337:                }
        !           338:                if (flags & MAP_SHARED) {
        !           339:                        /*
        !           340:                         *      Map it directly, allowing modifications
        !           341:                         *      to go out to the inode.
        !           342:                         */
        !           343:                        (void) vm_deallocate(user_map, user_addr, user_size);
        !           344:                        result = vm_allocate_with_pager(user_map,
        !           345:                                        &user_addr, user_size, find_space,
        !           346:                                        pager,
        !           347:                                        (vm_offset_t)file_pos);
        !           348:                        if (result != KERN_SUCCESS) {
        !           349:                                goto out;
        !           350:                        }
        !           351:                }
        !           352:                else {
        !           353: #if 0
        !           354:                        /* Moved to cover both shared and private cases */
        !           355:                        result = vm_map_find(user_map, NULL, (vm_offset_t) 0,
        !           356:                                        &user_addr, user_size, find_space);
        !           357:                        if (result != KERN_SUCCESS) {
        !           358:                                goto out;
        !           359:                        }
        !           360: #endif /* 0 */
        !           361:                        /*
        !           362:                         *      Copy-on-write of file.  Map into private
        !           363:                         *      map, then copy into our address space.
        !           364:                         */
        !           365:                        copy_map = vm_map_create(pmap_create(user_size),
        !           366:                                        0, user_size, TRUE);
        !           367:                        off = 0;
        !           368:                        result = vm_allocate_with_pager(copy_map,
        !           369:                                        &off, user_size, find_space,
        !           370:                                        pager,
        !           371:                                        (vm_offset_t)file_pos);
        !           372:                        if (result != KERN_SUCCESS) {
        !           373:                                vm_map_deallocate(copy_map);
        !           374:                                goto out;
        !           375:                        }
        !           376:                        result = vm_map_copy(user_map, copy_map,
        !           377:                                        user_addr, user_size,
        !           378:                                        0, FALSE, FALSE);
        !           379:                        if (result != KERN_SUCCESS) {
        !           380:                                vm_map_deallocate(copy_map);
        !           381:                                goto out;
        !           382:                        }
        !           383:                        vm_map_deallocate(copy_map);
        !           384:                }
        !           385:        }
        !           386: 
        !           387:        /*
        !           388:         *      Our memory defaults to read-write.  If it shouldn't
        !           389:         *      be readable, protect it.
        !           390:         */
        !           391:        if ((prot & PROT_WRITE) == 0) {
        !           392:                result = vm_protect(user_map, user_addr, user_size,
        !           393:                                        FALSE, VM_PROT_READ);
        !           394:                if (result != KERN_SUCCESS) {
        !           395:                        (void) vm_deallocate(user_map, user_addr, user_size);
        !           396:                        goto out;
        !           397:                }
        !           398:        }
        !           399: 
        !           400:        /*
        !           401:         *      Shared memory is also shared with children
        !           402:         */
        !           403:        /*
        !           404:         *      HACK HACK HACK
        !           405:         *      Since this memory CAN'T be made copy-on-write, and since
        !           406:         *      its users fork, we must change its inheritance to SHARED.
        !           407:         *      HACK HACK HACK
        !           408:         */
        !           409:        if (flags & MAP_SHARED) {
        !           410:                result = vm_inherit(user_map, user_addr, user_size,
        !           411:                                VM_INHERIT_SHARE);
        !           412:                if (result != KERN_SUCCESS) {
        !           413:                        (void) vm_deallocate(user_map, user_addr, user_size);
        !           414:                        goto out;
        !           415:                }
        !           416:        }
        !           417: 
        !           418:        *fdflags(p, uap->fd) |= UF_MAPPED;
        !           419: 
        !           420:        if (result == KERN_SUCCESS)
        !           421:                *retval = (register_t)user_addr;
        !           422:        /* FALL THROUGH */
        !           423: out: 
        !           424:        switch (result) {
        !           425:        case KERN_SUCCESS:
        !           426:                return (0);
        !           427:        case KERN_INVALID_ADDRESS:
        !           428:        case KERN_NO_SPACE:
        !           429:                return (ENOMEM);
        !           430:        case KERN_PROTECTION_FAILURE:
        !           431:                return (EACCES);
        !           432:        default:
        !           433:                return (EINVAL);
        !           434:        }
        !           435: }
        !           436: 
        !           437: struct msync_args {
        !           438:                caddr_t addr;
        !           439:                int len;
        !           440: };
        !           441: int
        !           442: msync(p, uap, retval)
        !           443:        struct proc *p;
        !           444:        struct msync_args *uap;
        !           445:        register_t *retval;
        !           446: {
        !           447:        /* Not yet implemented */
        !           448:        return (EOPNOTSUPP);
        !           449: }
        !           450: 
        !           451: 
        !           452: mremap()
        !           453: {
        !           454:        /* Not yet implemented */
        !           455:        return (EOPNOTSUPP);
        !           456: }
        !           457: 
        !           458: struct munmap_args {
        !           459:                caddr_t addr;
        !           460:                int     len;
        !           461: };
        !           462: munmap(p, uap, retval)
        !           463:        struct proc *p;
        !           464:        struct munmap_args *uap;
        !           465:        register_t *retval;
        !           466: 
        !           467: {
        !           468:        vm_offset_t     user_addr;
        !           469:        vm_size_t       user_size;
        !           470:        kern_return_t   result;
        !           471: 
        !           472:        user_addr = (vm_offset_t) uap->addr;
        !           473:        user_size = (vm_size_t) uap->len;
        !           474: 
        !           475:        /*
        !           476:         * user size is allocated to page boundary and size from
        !           477:         * the user land is not necessarily in multiple of page size
        !           478:         */
        !           479:        user_size = round_page(user_size);
        !           480:        if ((user_addr & page_mask) ||
        !           481:            (user_size & page_mask)) {
        !           482:                return(EINVAL);
        !           483:        }
        !           484:        result = vm_deallocate(current_task()->map, user_addr, user_size);
        !           485:        if (result != KERN_SUCCESS) {
        !           486:                return(EINVAL);
        !           487:        }
        !           488:        return(0);
        !           489: }
        !           490: 
        !           491: void
        !           492: munmapfd(p, fd)
        !           493:        struct proc *p;
        !           494:        int fd;
        !           495: {
        !           496:        /*
        !           497:         * XXX should vm_deallocate any regions mapped to this file
        !           498:         */
        !           499:        *fdflags(p, fd) &= ~UF_MAPPED;
        !           500: }
        !           501: 
        !           502: struct mprotect_args {
        !           503:                caddr_t addr;
        !           504:                int len;
        !           505:                int prot;
        !           506: };
        !           507: int
        !           508: mprotect(p, uap, retval)
        !           509:        struct proc *p;
        !           510:        struct mprotect_args *uap;
        !           511:        register_t *retval;
        !           512: {
        !           513:        vm_size_t size;
        !           514:        register vm_prot_t prot;
        !           515:        caddr_t addr;
        !           516:        int len;
        !           517:        vm_map_t        user_map;
        !           518: 
        !           519:        addr = uap->addr;
        !           520:        len = uap->len;
        !           521:        prot = (vm_prot_t)(uap->prot & VM_PROT_ALL);
        !           522: 
        !           523:        if (((unsigned long)addr & page_mask) || len < 0)
        !           524:                return(EINVAL);
        !           525:        size = (vm_size_t)len;
        !           526: 
        !           527:        user_map = current_task()->map;
        !           528:        switch (vm_map_protect(user_map, addr, addr+size, prot,
        !           529:            FALSE)) {
        !           530:        case KERN_SUCCESS:
        !           531:                return (0);
        !           532:        case KERN_PROTECTION_FAILURE:
        !           533:                return (EACCES);
        !           534:        }
        !           535:        return (EINVAL);
        !           536: }
        !           537: 
        !           538: struct madvise_args {
        !           539:                caddr_t addr;
        !           540:                int len;
        !           541:                int behav;
        !           542: };
        !           543: /* ARGSUSED */
        !           544: int
        !           545: madvise(p, uap, retval)
        !           546:        struct proc *p;
        !           547:        struct madvise_args *uap;
        !           548:        register_t *retval;
        !           549: {
        !           550:        /* Not yet implemented */
        !           551:        return (EOPNOTSUPP);
        !           552: }
        !           553: 
        !           554: struct mincore_args {
        !           555:                caddr_t addr;
        !           556:                int len;
        !           557:                char * vec;
        !           558: };
        !           559: /* ARGSUSED */
        !           560: int
        !           561: mincore(p, uap, retval)
        !           562:        struct proc *p;
        !           563:        struct mincore_args *uap;
        !           564:        register_t *retval;
        !           565: {
        !           566:        /* Not yet implemented */
        !           567:        return (EOPNOTSUPP);
        !           568: }
        !           569: 
        !           570: struct mlock_args {
        !           571:                caddr_t addr;
        !           572:                size_t len;
        !           573: };
        !           574: int
        !           575: mlock(p, uap, retval)
        !           576:        struct proc *p;
        !           577:        struct mlock_args *uap;
        !           578:        register_t *retval;
        !           579: {
        !           580:        /* Not yet implemented */
        !           581:        return (EOPNOTSUPP);
        !           582: }
        !           583: 
        !           584: struct munlock_args {
        !           585:                caddr_t addr;
        !           586:                size_t len;
        !           587: };
        !           588: int
        !           589: munlock(p, uap, retval)
        !           590:        struct proc *p;
        !           591:        struct munlock_args *uap;
        !           592:        register_t *retval;
        !           593: {
        !           594:        /* Not yet implemented */
        !           595:        return (EOPNOTSUPP);
        !           596: }
        !           597: 
        !           598: int
        !           599: map_fd(fd, offset, va, findspace, size)
        !           600:        int             fd;
        !           601:        vm_offset_t     offset;
        !           602:        vm_offset_t     *va;
        !           603:        boolean_t       findspace;
        !           604:        vm_size_t       size;
        !           605: {
        !           606:        struct file     *fp;
        !           607:        register struct vnode *vp;
        !           608:        vm_map_t        user_map;
        !           609:        kern_return_t   result;
        !           610:        vm_offset_t     user_addr;
        !           611:        vm_size_t       user_size;
        !           612:        vm_pager_t      pager;
        !           613:        vm_map_t        copy_map;
        !           614:        vm_offset_t     off;
        !           615: 
        !           616:        user_map = current_task()->map;
        !           617: 
        !           618:        /*
        !           619:         *      Find the inode; verify that it's a regular file.
        !           620:         */
        !           621:        if (getvnode(current_proc(), fd, &fp))
        !           622:                return (KERN_INVALID_ARGUMENT);
        !           623: 
        !           624:        vp = (struct vnode *)fp->f_data;
        !           625:        if (vp->v_type != VREG)
        !           626:                return(KERN_INVALID_ARGUMENT);
        !           627: 
        !           628:        user_size = round_page(size);
        !           629: 
        !           630:        if (findspace) {
        !           631:                /*
        !           632:                 *      Allocate dummy memory.
        !           633:                 */
        !           634:                result = vm_allocate(user_map, &user_addr, size, TRUE);
        !           635:                if (result != KERN_SUCCESS)
        !           636:                        return(result);
        !           637:                if (copyout(&user_addr, va, sizeof(vm_offset_t))) {
        !           638:                        (void) vm_deallocate(user_map, user_addr, size);
        !           639:                        return(KERN_INVALID_ADDRESS);
        !           640:                }
        !           641:        }
        !           642:        else {
        !           643:                /*
        !           644:                 *      Get user's address, and verify that it's
        !           645:                 *      page-aligned and writable.
        !           646:                 */
        !           647: 
        !           648:                if (copyin(va, &user_addr, sizeof(vm_offset_t)))
        !           649:                        return(KERN_INVALID_ADDRESS);
        !           650:                if ((trunc_page(user_addr) != user_addr))
        !           651:                        return(KERN_INVALID_ARGUMENT);
        !           652:                if (!vm_map_check_protection(user_map, user_addr,
        !           653:                                (vm_offset_t)(user_addr + user_size),
        !           654:                                VM_PROT_READ|VM_PROT_WRITE))
        !           655:                        return(KERN_INVALID_ARGUMENT);
        !           656:        }
        !           657: 
        !           658:        /*
        !           659:         * Allow user to map in a zero length file.
        !           660:         */
        !           661:        if (size == 0)
        !           662:                return KERN_SUCCESS;
        !           663: 
        !           664:        /*
        !           665:         *      Map in the file.
        !           666:         */
        !           667: 
        !           668:        pager = vnode_pager_setup(vp, FALSE, TRUE);
        !           669: 
        !           670:        /*
        !           671:         *      Map into private map, then copy into our address space.
        !           672:         */
        !           673:        copy_map = vm_map_create(pmap_create(user_size), 0, user_size, TRUE);
        !           674:        off = 0;
        !           675:        result = vm_allocate_with_pager(copy_map, &off, user_size, FALSE,
        !           676:                                        pager,
        !           677:                                        offset);
        !           678:        if (result == KERN_SUCCESS)
        !           679:                result = vm_map_copy(user_map, copy_map, user_addr, user_size,
        !           680:                                        0, FALSE, FALSE);
        !           681: 
        !           682:        if ((result != KERN_SUCCESS) && findspace)
        !           683:                (void) vm_deallocate(user_map, user_addr, user_size);
        !           684: 
        !           685:        vm_map_deallocate(copy_map);
        !           686: 
        !           687:        /*
        !           688:         * Set credentials.
        !           689:         */
        !           690:        if (vp->v_vm_info->cred == NULL) {
        !           691:                crhold(current_proc()->p_ucred);
        !           692:                vp->v_vm_info->cred = current_proc()->p_ucred;
        !           693:        }
        !           694: 
        !           695:        return(result);
        !           696: }
        !           697: 
        !           698: 
        !           699: /* BEGIN DEFUNCT */
        !           700: struct obreak_args {
        !           701:        char *nsiz;
        !           702: };
        !           703: obreak(p, uap, retval)
        !           704:        struct proc *p;
        !           705:        struct obreak_args *uap;
        !           706:        register_t *retval;
        !           707: {
        !           708:        /* Not implemented, obsolete */
        !           709:        return (ENOMEM);
        !           710: }
        !           711: 
        !           712: int    both;
        !           713: 
        !           714: ovadvise()
        !           715: {
        !           716: 
        !           717: #ifdef lint
        !           718:        both = 0;
        !           719: #endif
        !           720: }
        !           721: /* END DEFUNCT */

unix.superglobalmegacorp.com

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