headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / libroot / posix / sys / mman.cpp
blob2f1122b83c1c12040fbf4c3d03dc7a33d21f19b7
1 /*
2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <sys/mman.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <string.h>
13 #include <OS.h>
15 #include <errno_private.h>
16 #include <syscall_utils.h>
17 #include <syscalls.h>
18 #include <vm_defs.h>
21 static const char* kSharedMemoryDir = "/var/shared_memory/";
24 static bool
25 append_string(char*& path, size_t& bytesLeft, const char* toAppend, size_t size)
27 if (bytesLeft <= size)
28 return false;
30 memcpy(path, toAppend, size);
31 path += size;
32 path[0] = '\0';
33 bytesLeft -= size;
35 return true;
39 static bool
40 append_string(char*& path, size_t& bytesLeft, const char* toAppend)
42 return append_string(path, bytesLeft, toAppend, strlen(toAppend));
46 static status_t
47 shm_name_to_path(const char* name, char* path, size_t pathSize)
49 if (name == NULL)
50 return B_BAD_VALUE;
52 // skip leading slashes
53 while (*name == '/')
54 name++;
56 if (*name == '\0')
57 return B_BAD_VALUE;
59 // create the path; replace occurrences of '/' by "%s" and '%' by "%%"
60 if (!append_string(path, pathSize, kSharedMemoryDir))
61 return ENAMETOOLONG;
63 while (const char* found = strpbrk(name, "%/")) {
64 // append section that doesn't need escaping
65 if (found != name) {
66 if (!append_string(path, pathSize, name, found - name))
67 return ENAMETOOLONG;
70 // append escaped char
71 const char* append = (*found == '%' ? "%%" : "%s");
72 if (!append_string(path, pathSize, append, 2))
73 return ENAMETOOLONG;
74 name = found + 1;
77 // append remaining string
78 if (!append_string(path, pathSize, name))
79 return ENAMETOOLONG;
81 return B_OK;
85 // #pragma mark -
88 void*
89 mmap(void* address, size_t length, int protection, int flags, int fd,
90 off_t offset)
92 // offset and length must be page-aligned
93 if (length == 0 || offset % B_PAGE_SIZE != 0) {
94 __set_errno(B_BAD_VALUE);
95 return MAP_FAILED;
98 // check anonymous mapping
99 if ((flags & MAP_ANONYMOUS) != 0) {
100 fd = -1;
101 } else if (fd < 0) {
102 __set_errno(EBADF);
103 return MAP_FAILED;
106 // either MAP_SHARED or MAP_PRIVATE must be specified
107 if (((flags & MAP_SHARED) != 0) == ((flags & MAP_PRIVATE) != 0)) {
108 __set_errno(B_BAD_VALUE);
109 return MAP_FAILED;
112 // translate mapping, address specification, and protection
113 int mapping = (flags & MAP_SHARED) != 0
114 ? REGION_NO_PRIVATE_MAP : REGION_PRIVATE_MAP;
116 uint32 addressSpec;
117 if ((flags & MAP_FIXED) != 0)
118 addressSpec = B_EXACT_ADDRESS;
119 else if (address != NULL)
120 addressSpec = B_BASE_ADDRESS;
121 else
122 addressSpec = B_RANDOMIZED_ANY_ADDRESS;
124 uint32 areaProtection = 0;
125 if ((protection & PROT_READ) != 0)
126 areaProtection |= B_READ_AREA;
127 if ((protection & PROT_WRITE) != 0)
128 areaProtection |= B_WRITE_AREA;
129 if ((protection & PROT_EXEC) != 0)
130 areaProtection |= B_EXECUTE_AREA;
132 // ask the kernel to map
133 area_id area = _kern_map_file("mmap area", &address, addressSpec,
134 length, areaProtection, mapping, true, fd, offset);
135 if (area < 0) {
136 __set_errno(area);
137 return MAP_FAILED;
140 return address;
145 munmap(void* address, size_t length)
147 RETURN_AND_SET_ERRNO(_kern_unmap_memory(address, length));
152 mprotect(void* address, size_t length, int protection)
154 RETURN_AND_SET_ERRNO(_kern_set_memory_protection(address, length,
155 protection));
160 msync(void* address, size_t length, int flags)
162 RETURN_AND_SET_ERRNO_TEST_CANCEL(_kern_sync_memory(address, length, flags));
167 posix_madvise(void* address, size_t length, int advice)
169 RETURN_AND_SET_ERRNO(_kern_memory_advice(address, length, advice));
174 shm_open(const char* name, int openMode, mode_t permissions)
176 char path[PATH_MAX];
177 status_t error = shm_name_to_path(name, path, sizeof(path));
178 if (error != B_OK)
179 RETURN_AND_SET_ERRNO(error);
181 return open(path, openMode | FD_CLOEXEC, permissions);
186 shm_unlink(const char* name)
188 char path[PATH_MAX];
189 status_t error = shm_name_to_path(name, path, sizeof(path));
190 if (error != B_OK)
191 RETURN_AND_SET_ERRNO(error);
193 return unlink(path);