compositor: Use stdint for specifing integer storage
[src/agl-compositor.git] / shared / os-compatibility.c
1 /*
2  * Copyright © 2012 Collabora, Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <sys/epoll.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <libweston/zalloc.h>
35
36 #ifdef HAVE_MEMFD_CREATE
37 #include <sys/mman.h>
38 #endif
39
40 #include "os-compatibility.h"
41
42 #define READONLY_SEALS (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)
43
44 int
45 os_fd_set_cloexec(int fd)
46 {
47         long flags;
48
49         if (fd == -1)
50                 return -1;
51
52         flags = fcntl(fd, F_GETFD);
53         if (flags == -1)
54                 return -1;
55
56         if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
57                 return -1;
58
59         return 0;
60 }
61
62 static int
63 set_cloexec_or_close(int fd)
64 {
65         if (os_fd_set_cloexec(fd) != 0) {
66                 close(fd);
67                 return -1;
68         }
69         return fd;
70 }
71
72 int
73 os_socketpair_cloexec(int domain, int type, int protocol, int *sv)
74 {
75         int ret;
76
77 #ifdef SOCK_CLOEXEC
78         ret = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv);
79         if (ret == 0 || errno != EINVAL)
80                 return ret;
81 #endif
82
83         ret = socketpair(domain, type, protocol, sv);
84         if (ret < 0)
85                 return ret;
86
87         sv[0] = set_cloexec_or_close(sv[0]);
88         sv[1] = set_cloexec_or_close(sv[1]);
89
90         if (sv[0] != -1 && sv[1] != -1)
91                 return 0;
92
93         close(sv[0]);
94         close(sv[1]);
95         return -1;
96 }
97
98 int
99 os_epoll_create_cloexec(void)
100 {
101         int fd;
102
103 #ifdef EPOLL_CLOEXEC
104         fd = epoll_create1(EPOLL_CLOEXEC);
105         if (fd >= 0)
106                 return fd;
107         if (errno != EINVAL)
108                 return -1;
109 #endif
110
111         fd = epoll_create(1);
112         return set_cloexec_or_close(fd);
113 }
114
115 static int
116 create_tmpfile_cloexec(char *tmpname)
117 {
118         int fd;
119
120 #ifdef HAVE_MKOSTEMP
121         fd = mkostemp(tmpname, O_CLOEXEC);
122         if (fd >= 0)
123                 unlink(tmpname);
124 #else
125         fd = mkstemp(tmpname);
126         if (fd >= 0) {
127                 fd = set_cloexec_or_close(fd);
128                 unlink(tmpname);
129         }
130 #endif
131
132         return fd;
133 }
134
135 /*
136  * Create a new, unique, anonymous file of the given size, and
137  * return the file descriptor for it. The file descriptor is set
138  * CLOEXEC. The file is immediately suitable for mmap()'ing
139  * the given size at offset zero.
140  *
141  * The file should not have a permanent backing store like a disk,
142  * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
143  *
144  * The file name is deleted from the file system.
145  *
146  * The file is suitable for buffer sharing between processes by
147  * transmitting the file descriptor over Unix sockets using the
148  * SCM_RIGHTS methods.
149  *
150  * If the C library implements posix_fallocate(), it is used to
151  * guarantee that disk space is available for the file at the
152  * given size. If disk space is insufficient, errno is set to ENOSPC.
153  * If posix_fallocate() is not supported, program may receive
154  * SIGBUS on accessing mmap()'ed file contents instead.
155  *
156  * If the C library implements memfd_create(), it is used to create the
157  * file purely in memory, without any backing file name on the file
158  * system, and then sealing off the possibility of shrinking it.  This
159  * can then be checked before accessing mmap()'ed file contents, to
160  * make sure SIGBUS can't happen.  It also avoids requiring
161  * XDG_RUNTIME_DIR.
162  */
163 int
164 os_create_anonymous_file(off_t size)
165 {
166         static const char template[] = "/weston-shared-XXXXXX";
167         const char *path;
168         char *name;
169         int fd;
170         int ret;
171
172 #ifdef HAVE_MEMFD_CREATE
173         fd = memfd_create("weston-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);
174         if (fd >= 0) {
175                 /* We can add this seal before calling posix_fallocate(), as
176                  * the file is currently zero-sized anyway.
177                  *
178                  * There is also no need to check for the return value, we
179                  * couldn't do anything with it anyway.
180                  */
181                 fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK);
182         } else
183 #endif
184         {
185                 path = getenv("XDG_RUNTIME_DIR");
186                 if (!path) {
187                         errno = ENOENT;
188                         return -1;
189                 }
190
191                 name = malloc(strlen(path) + sizeof(template));
192                 if (!name)
193                         return -1;
194
195                 strcpy(name, path);
196                 strcat(name, template);
197
198                 fd = create_tmpfile_cloexec(name);
199
200                 free(name);
201
202                 if (fd < 0)
203                         return -1;
204         }
205
206 #ifdef HAVE_POSIX_FALLOCATE
207         do {
208                 ret = posix_fallocate(fd, 0, size);
209         } while (ret == EINTR);
210         if (ret != 0) {
211                 close(fd);
212                 errno = ret;
213                 return -1;
214         }
215 #else
216         do {
217                 ret = ftruncate(fd, size);
218         } while (ret < 0 && errno == EINTR);
219         if (ret < 0) {
220                 close(fd);
221                 return -1;
222         }
223 #endif
224
225         return fd;
226 }
227
228 #ifndef HAVE_STRCHRNUL
229 char *
230 strchrnul(const char *s, int c)
231 {
232         while (*s && *s != c)
233                 s++;
234         return (char *)s;
235 }
236 #endif
237
238 struct ro_anonymous_file {
239         int fd;
240         size_t size;
241 };
242
243 /** Create a new anonymous read-only file of the given size and the given data
244  *
245  * \param size The size of \p data.
246  * \param data The data of the file with the size \p size.
247  * \return A new \c ro_anonymous_file, or NULL on failure.
248  *
249  * The intended use-case is for sending mid-sized data from the compositor
250  * to clients.
251  * If the function fails errno is set.
252  */
253 struct ro_anonymous_file *
254 os_ro_anonymous_file_create(size_t size,
255                             const char *data)
256 {
257         struct ro_anonymous_file *file;
258         void *map;
259
260         file = zalloc(sizeof *file);
261         if (!file) {
262                 errno = ENOMEM;
263                 return NULL;
264         }
265
266         file->size = size;
267         file->fd = os_create_anonymous_file(size);
268         if (file->fd == -1)
269                 goto err_free;
270
271         map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, file->fd, 0);
272         if (map == MAP_FAILED)
273                 goto err_close;
274
275         memcpy(map, data, size);
276
277         munmap(map, size);
278
279 #ifdef HAVE_MEMFD_CREATE
280         /* try to put seals on the file to make it read-only so that we can
281          * return the fd later directly when support_shared is not set.
282          * os_ro_anonymous_file_get_fd can handle the fd even if it is not
283          * sealed read-only and will instead create a new anonymous file on
284          * each invocation.
285          */
286         fcntl(file->fd, F_ADD_SEALS, READONLY_SEALS);
287 #endif
288
289         return file;
290
291 err_close:
292         close(file->fd);
293 err_free:
294         free(file);
295         return NULL;
296 }
297
298 /** Destroy an anonymous read-only file
299  *
300  * \param file The file to destroy.
301  */
302 void
303 os_ro_anonymous_file_destroy(struct ro_anonymous_file *file)
304 {
305         close(file->fd);
306         free(file);
307 }
308
309 /** Get the size of an anonymous read-only file
310  *
311  * \param file The file to get the size of.
312  * \return The size of the file.
313  */
314 size_t
315 os_ro_anonymous_file_size(struct ro_anonymous_file *file)
316 {
317         return file->size;
318 }
319
320 /** Returns a file descriptor for the given file, ready to be send to a client.
321  *
322  * \param file The file for which to get a file descriptor.
323  * \param mapmode Describes the ways in which the returned file descriptor can
324  * be used with mmap.
325  * \return A file descriptor for the given file that can be send to a client
326  * or -1 on failure.
327  *
328  * The returned file descriptor must not be shared between multiple clients.
329  * When \p mapmode is RO_ANONYMOUS_FILE_MAPMODE_PRIVATE the file descriptor is
330  * only guaranteed to be mmapable with \c MAP_PRIVATE, when \p mapmode is
331  * RO_ANONYMOUS_FILE_MAPMODE_SHARED the file descriptor can be mmaped with
332  * either MAP_PRIVATE or MAP_SHARED.
333  * When you're done with the fd you must call \c os_ro_anonymous_file_put_fd
334  * instead of calling \c close.
335  * If the function fails errno is set.
336  */
337 int
338 os_ro_anonymous_file_get_fd(struct ro_anonymous_file *file,
339                             enum ro_anonymous_file_mapmode mapmode)
340 {
341         void *src, *dst;
342         int seals, fd;
343
344         seals = fcntl(file->fd, F_GET_SEALS);
345
346         /* file was sealed for read-only and we don't have to support MAP_SHARED
347          * so we can simply pass the memfd fd
348          */
349         if (seals != -1 && mapmode == RO_ANONYMOUS_FILE_MAPMODE_PRIVATE &&
350             (seals & READONLY_SEALS) == READONLY_SEALS)
351                 return file->fd;
352
353         /* for all other cases we create a new anonymous file that can be mapped
354          * with MAP_SHARED and copy the contents to it and return that instead
355          */
356         fd = os_create_anonymous_file(file->size);
357         if (fd == -1)
358                 return fd;
359
360         src = mmap(NULL, file->size, PROT_READ, MAP_PRIVATE, file->fd, 0);
361         if (src == MAP_FAILED) {
362                 close(fd);
363                 return -1;
364         }
365
366         dst = mmap(NULL, file->size, PROT_WRITE, MAP_SHARED, fd, 0);
367         if (dst == MAP_FAILED) {
368                 close(fd);
369                 munmap(src, file->size);
370                 return -1;
371         }
372
373         memcpy(dst, src, file->size);
374         munmap(src, file->size);
375         munmap(dst, file->size);
376
377         return fd;
378 }
379
380 /** Release a file descriptor returned by \c os_ro_anonymous_file_get_fd
381  *
382  * \param fd A file descriptor returned by \c os_ro_anonymous_file_get_fd.
383  * \return 0 on success, or -1 on failure.
384  *
385  * This function must be called for every file descriptor created with
386  * \c os_ro_anonymous_file_get_fd to not leake any resources.
387  * If the function fails errno is set.
388  */
389 int
390 os_ro_anonymous_file_put_fd(int fd)
391 {
392         int seals = fcntl(fd, F_GET_SEALS);
393         if (seals == -1 && errno != EINVAL)
394                 return -1;
395
396         /* If the fd cannot be sealed seals is -1 at this point
397          * or the file can be sealed but has not been sealed for writing.
398          * In both cases we created a new anonymous file that we have to
399          * close.
400          */
401         if (seals == -1 || !(seals & F_SEAL_WRITE))
402                 close(fd);
403
404         return 0;
405 }
406
407 int
408 os_fd_clear_cloexec(int fd)
409 {
410         int flags;
411
412         flags = fcntl(fd, F_GETFD);
413         if (flags == -1)
414                 return -1;
415
416         if (fcntl(fd, F_SETFD, flags & ~(int)FD_CLOEXEC) == -1)
417                 return -1;
418
419         return 0;
420 }