source: trunk/kernel/syscalls/sys_mmap.c @ 5

Last change on this file since 5 was 1, checked in by alain, 8 years ago

First import

File size: 4.1 KB
Line 
1/*
2 * kern/sys_mmap.c - map files, memory or devices into process's
3 *                   virtual address space
4 *
5 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
6 * Copyright (c) 2011,2012 UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-kernel.
9 *
10 * ALMOS-kernel is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-kernel is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-kernel; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <errno.h>
25#include <thread.h>
26#include <vfs.h>
27#include <sys-vfs.h>
28#include <process.h>
29#include <vmm.h>
30
31///////////////////////////////////
32int sys_mmap( mmap_attr_t * mattr )
33{
34        error_t err;
35        uint_t count;
36        struct thread_s *this;
37        struct process_s *process;
38        struct vfs_file_s *file;
39        mmap_attr_t attr;
40        size_t isize;
41        int retval;
42 
43        this = current_thread;
44        process = this->process;
45        err  = EINVAL;
46        file = NULL;
47
48        if((err = cpu_copy_from_uspace(&attr, mattr, sizeof(mmap_attr_t))))
49        {
50                printk(INFO, "%s: failed, copying from uspace @%x\n",
51                       __FUNCTION__, 
52                       mattr);
53
54                this->info.errno = EFAULT;
55                return (int)VM_FAILED;
56        }
57
58        if((attr.flags  & VM_REG_HEAP)                     ||
59           ((attr.flags & VM_REG_PVSH) == VM_REG_PVSH)     || 
60           ((attr.flags & VM_REG_PVSH) == 0)               ||
61           (attr.length == 0)                              ||
62           (attr.offset & PMM_PAGE_MASK)                   || 
63           ((attr.addr != NULL) && (((uint_t)attr.addr & PMM_PAGE_MASK)          ||
64                                (NOT_IN_USPACE(attr.length + (uint_t)attr.addr)) ||
65                                (NOT_IN_USPACE((uint_t)attr.addr)) )))
66        {
67                printk(INFO, "%s: failed, we don't like flags (%x), length (%d), or addr (%x)\n",
68                       __FUNCTION__, 
69                       attr.flags, 
70                       attr.length, 
71                       attr.addr);
72     
73                this->info.errno = EINVAL;
74                return (int)VM_FAILED;
75        }
76   
77        if(attr.flags & VM_REG_ANON)
78        {
79                attr.offset = 0;
80                attr.addr   = (attr.flags & VM_REG_FIXED) ? attr.addr : NULL;
81        }
82        else
83        {     
84                /* FIXEME: possible concurent delete of file from another bugy thread closing it */
85                if((attr.fd >= CONFIG_TASK_FILE_MAX_NR) || (process_fd_lookup(process, attr.fd, &file)))
86                {
87                        printk(INFO, "%s: failed, bad file descriptor (%d)\n", 
88                               __FUNCTION__, 
89                               attr.fd);
90
91                        this->info.errno = EBADFD;
92                        return (int)VM_FAILED;
93                }
94     
95                //atomic_add(&file->f_count, 1);
96                vfs_file_up(file);//FIXME coalsce access to remote node info
97     
98                //FIXME: does we really to get the size...
99                isize = vfs_inode_size_get_remote(file->f_inode.ptr, file->f_inode.cid);
100                if((attr.offset + attr.length) > isize)
101                {
102                        printk(INFO, "%s: failed, offset (%d) + len (%d) >= file's size (%d)\n", 
103                               __FUNCTION__, 
104                               attr.offset, 
105                               attr.length, 
106                               isize);
107
108                        this->info.errno = ERANGE;
109                        goto SYS_MMAP_FILE_ERR;
110                }
111
112                if(((attr.prot & VM_REG_RD) && !(VFS_IS(file->f_flags, VFS_O_RDONLY)))   ||
113                   ((attr.prot & VM_REG_WR) && !(VFS_IS(file->f_flags, VFS_O_WRONLY)))   ||
114                   ((attr.prot & VM_REG_WR) && (VFS_IS(file->f_flags, VFS_O_APPEND))))//    ||
115                        //(!(attr.prot & VM_REG_RD) && (attr.flags & VM_REG_PRIVATE)))
116                {
117                        printk(INFO, "%s: failed, EACCES prot (%x), f_flags (%x)\n", 
118                               __FUNCTION__, 
119                               attr.prot, 
120                               file->f_flags);
121
122                        this->info.errno = EACCES;
123                        goto SYS_MMAP_FILE_ERR;
124                }
125        }
126
127        retval = (int) vmm_mmap(process,
128                                file,
129                                attr.addr,
130                                attr.length,
131                                attr.prot,
132                                attr.flags,
133                                attr.offset);
134   
135        if((retval != (int)VM_FAILED) || (attr.flags & VM_REG_ANON))
136                return retval;
137
138SYS_MMAP_FILE_ERR:
139        printk(INFO, "%s: Failed, Droping file count \n", 
140               __FUNCTION__);
141   
142        vfs_close( file , &count );
143
144        if(count == 1) process_fd_put( process , attr.fd );
145
146        return (int)VM_FAILED;
147}
Note: See TracBrowser for help on using the repository browser.