]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/mach/hurd/mmap.c
Break some lines before not after operators.
[thirdparty/glibc.git] / sysdeps / mach / hurd / mmap.c
CommitLineData
04277e02 1/* Copyright (C) 1994-2019 Free Software Foundation, Inc.
478b92f0 2 This file is part of the GNU C Library.
28f540f4 3
478b92f0 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
28f540f4 8
478b92f0
UD
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
28f540f4
RM
17
18#include <sys/types.h>
19#include <sys/mman.h>
20#include <errno.h>
21#include <hurd.h>
22#include <hurd/fd.h>
23
24/* Map addresses starting near ADDR and extending for LEN bytes. from
25 OFFSET into the file FD describes according to PROT and FLAGS. If ADDR
26 is nonzero, it is the desired mapping address. If the MAP_FIXED bit is
27 set in FLAGS, the mapping will be at ADDR exactly (which must be
28 page-aligned); otherwise the system chooses a convenient nearby address.
f17a4233 29 The return value is the actual mapping address chosen or (void *) -1
28f540f4
RM
30 for errors (in which case `errno' is set). A successful `mmap' call
31 deallocates any previous mapping for the affected region. */
32
f17a4233
JM
33void *
34__mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
28f540f4
RM
35{
36 error_t err;
37 vm_prot_t vmprot;
38 memory_object_t memobj;
39 vm_address_t mapaddr;
65bf5fa3 40
57a491d1
RM
41 mapaddr = (vm_address_t) addr;
42
fbf86dda 43 /* ADDR and OFFSET must be page-aligned. */
51a3985d 44 if ((mapaddr & (__vm_page_size - 1)) || (offset & (__vm_page_size - 1)))
f17a4233 45 return (void *) (long int) __hurd_fail (EINVAL);
fbf86dda 46
57a491d1
RM
47 if ((flags & (MAP_TYPE|MAP_INHERIT)) == MAP_ANON
48 && prot == (PROT_READ|PROT_WRITE)) /* cf VM_PROT_DEFAULT */
49 {
50 /* vm_allocate has (a little) less overhead in the kernel too. */
868df0f9 51 err = __vm_allocate (__mach_task_self (), &mapaddr, len, mapaddr == 0);
57a491d1 52
0ea698ae 53 if (err == KERN_NO_SPACE)
57a491d1 54 {
0ea698ae
ST
55 if (flags & MAP_FIXED)
56 {
57 /* XXX this is not atomic as it is in unix! */
58 /* The region is already allocated; deallocate it first. */
59 err = __vm_deallocate (__mach_task_self (), mapaddr, len);
60 if (!err)
61 err = __vm_allocate (__mach_task_self (), &mapaddr, len, 0);
62 }
868df0f9 63 else if (mapaddr != 0)
0ea698ae 64 err = __vm_allocate (__mach_task_self (), &mapaddr, len, 1);
57a491d1
RM
65 }
66
f17a4233 67 return err ? (void *) (long int) __hurd_fail (err) : (void *) mapaddr;
57a491d1
RM
68 }
69
28f540f4
RM
70 vmprot = VM_PROT_NONE;
71 if (prot & PROT_READ)
72 vmprot |= VM_PROT_READ;
73 if (prot & PROT_WRITE)
74 vmprot |= VM_PROT_WRITE;
75 if (prot & PROT_EXEC)
76 vmprot |= VM_PROT_EXECUTE;
77
78 switch (flags & MAP_TYPE)
79 {
80 default:
f17a4233 81 return (void *) (long int) __hurd_fail (EINVAL);
28f540f4
RM
82
83 case MAP_ANON:
84 memobj = MACH_PORT_NULL;
85 break;
86
87 case MAP_FILE:
7752137a 88 case 0: /* Allow, e.g., just MAP_SHARED. */
28f540f4
RM
89 {
90 mach_port_t robj, wobj;
91 if (err = HURD_DPORT_USE (fd, __io_map (port, &robj, &wobj)))
edc7ae46
RM
92 {
93 if (err == MIG_BAD_ID || err == EOPNOTSUPP || err == ENOSYS)
94 err = ENODEV; /* File descriptor doesn't support mmap. */
f17a4233 95 return (void *) (long int) __hurd_dfail (fd, err);
edc7ae46 96 }
28f540f4
RM
97 switch (prot & (PROT_READ|PROT_WRITE))
98 {
e86c5b64
ST
99 /* Although it apparently doesn't make sense to map a file with
100 protection set to PROT_NONE, it is actually sometimes done.
101 In particular, that's how localedef reserves some space for
102 the locale archive file, the rationale being that some
103 implementations take into account whether the mapping is
104 anonymous or not when selecting addresses. */
105 case PROT_NONE:
28f540f4
RM
106 case PROT_READ:
107 memobj = robj;
1a3a58fd
RM
108 if (wobj != MACH_PORT_NULL)
109 __mach_port_deallocate (__mach_task_self (), wobj);
28f540f4
RM
110 break;
111 case PROT_WRITE:
112 memobj = wobj;
1a3a58fd
RM
113 if (robj != MACH_PORT_NULL)
114 __mach_port_deallocate (__mach_task_self (), robj);
28f540f4
RM
115 break;
116 case PROT_READ|PROT_WRITE:
28f540f4 117 if (robj == wobj)
1a3a58fd
RM
118 {
119 memobj = wobj;
120 /* Remove extra reference. */
121 __mach_port_deallocate (__mach_task_self (), memobj);
122 }
123 else if (wobj == MACH_PORT_NULL && /* Not writable by mapping. */
907a1bac 124 !(flags & MAP_SHARED))
1a3a58fd
RM
125 /* The file can only be mapped for reading. Since we are
126 making a private mapping, we will never try to write the
127 object anyway, so we don't care. */
128 memobj = robj;
28f540f4
RM
129 else
130 {
131 __mach_port_deallocate (__mach_task_self (), wobj);
f17a4233 132 return (void *) (long int) __hurd_fail (EACCES);
28f540f4
RM
133 }
134 break;
e86c5b64
ST
135 default:
136 __builtin_unreachable ();
28f540f4
RM
137 }
138 break;
139 /* XXX handle MAP_NOEXTEND */
140 }
141 }
142
65bf5fa3
RM
143 /* XXX handle MAP_INHERIT */
144
28f540f4
RM
145 err = __vm_map (__mach_task_self (),
146 &mapaddr, (vm_size_t) len, (vm_address_t) 0,
868df0f9 147 mapaddr == 0,
28f540f4 148 memobj, (vm_offset_t) offset,
65bf5fa3 149 ! (flags & MAP_SHARED),
28f540f4 150 vmprot, VM_PROT_ALL,
65bf5fa3
RM
151 (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY);
152
0ea698ae 153 if (err == KERN_NO_SPACE)
787e4db9 154 {
0ea698ae
ST
155 if (flags & MAP_FIXED)
156 {
157 /* XXX this is not atomic as it is in unix! */
158 /* The region is already allocated; deallocate it first. */
159 err = __vm_deallocate (__mach_task_self (), mapaddr, len);
160 if (! err)
161 err = __vm_map (__mach_task_self (),
162 &mapaddr, (vm_size_t) len, (vm_address_t) 0,
163 0, memobj, (vm_offset_t) offset,
164 ! (flags & MAP_SHARED),
165 vmprot, VM_PROT_ALL,
166 (flags & MAP_SHARED) ? VM_INHERIT_SHARE
167 : VM_INHERIT_COPY);
168 }
868df0f9 169 else if (mapaddr != 0)
787e4db9
RM
170 err = __vm_map (__mach_task_self (),
171 &mapaddr, (vm_size_t) len, (vm_address_t) 0,
0ea698ae 172 1, memobj, (vm_offset_t) offset,
f36f8dcf 173 ! (flags & MAP_SHARED),
787e4db9 174 vmprot, VM_PROT_ALL,
f36f8dcf
RM
175 (flags & MAP_SHARED) ? VM_INHERIT_SHARE
176 : VM_INHERIT_COPY);
787e4db9 177 }
28f540f4
RM
178
179 if (memobj != MACH_PORT_NULL)
180 __mach_port_deallocate (__mach_task_self (), memobj);
181
65bf5fa3 182 if (err)
f17a4233 183 return (void *) (long int) __hurd_fail (err);
65bf5fa3 184
f17a4233 185 return (void *) mapaddr;
28f540f4 186}
6408bdde 187
a166531f 188libc_hidden_def (__mmap)
6408bdde 189weak_alias (__mmap, mmap)