1*bbecb9d1SAndroid Build Coastguard Worker /*
2*bbecb9d1SAndroid Build Coastguard Worker * Copyright © 2012 Collabora, Ltd.
3*bbecb9d1SAndroid Build Coastguard Worker *
4*bbecb9d1SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining
5*bbecb9d1SAndroid Build Coastguard Worker * a copy of this software and associated documentation files (the
6*bbecb9d1SAndroid Build Coastguard Worker * "Software"), to deal in the Software without restriction, including
7*bbecb9d1SAndroid Build Coastguard Worker * without limitation the rights to use, copy, modify, merge, publish,
8*bbecb9d1SAndroid Build Coastguard Worker * distribute, sublicense, and/or sell copies of the Software, and to
9*bbecb9d1SAndroid Build Coastguard Worker * permit persons to whom the Software is furnished to do so, subject to
10*bbecb9d1SAndroid Build Coastguard Worker * the following conditions:
11*bbecb9d1SAndroid Build Coastguard Worker *
12*bbecb9d1SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the
13*bbecb9d1SAndroid Build Coastguard Worker * next paragraph) shall be included in all copies or substantial
14*bbecb9d1SAndroid Build Coastguard Worker * portions of the Software.
15*bbecb9d1SAndroid Build Coastguard Worker *
16*bbecb9d1SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*bbecb9d1SAndroid Build Coastguard Worker * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*bbecb9d1SAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*bbecb9d1SAndroid Build Coastguard Worker * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20*bbecb9d1SAndroid Build Coastguard Worker * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21*bbecb9d1SAndroid Build Coastguard Worker * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22*bbecb9d1SAndroid Build Coastguard Worker * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*bbecb9d1SAndroid Build Coastguard Worker * SOFTWARE.
24*bbecb9d1SAndroid Build Coastguard Worker */
25*bbecb9d1SAndroid Build Coastguard Worker
26*bbecb9d1SAndroid Build Coastguard Worker /*
27*bbecb9d1SAndroid Build Coastguard Worker * Based on weston shared/os-compatibility.c
28*bbecb9d1SAndroid Build Coastguard Worker */
29*bbecb9d1SAndroid Build Coastguard Worker
30*bbecb9d1SAndroid Build Coastguard Worker #ifndef _WIN32
31*bbecb9d1SAndroid Build Coastguard Worker #include "anon_file.h"
32*bbecb9d1SAndroid Build Coastguard Worker
33*bbecb9d1SAndroid Build Coastguard Worker #include <unistd.h>
34*bbecb9d1SAndroid Build Coastguard Worker #include <fcntl.h>
35*bbecb9d1SAndroid Build Coastguard Worker #include <errno.h>
36*bbecb9d1SAndroid Build Coastguard Worker #include <stdlib.h>
37*bbecb9d1SAndroid Build Coastguard Worker
38*bbecb9d1SAndroid Build Coastguard Worker #if defined(HAVE_MEMFD_CREATE) || defined(__FreeBSD__) || defined(__OpenBSD__)
39*bbecb9d1SAndroid Build Coastguard Worker #include <sys/mman.h>
40*bbecb9d1SAndroid Build Coastguard Worker #elif defined(__ANDROID__)
41*bbecb9d1SAndroid Build Coastguard Worker #include <sys/syscall.h>
42*bbecb9d1SAndroid Build Coastguard Worker #include <linux/memfd.h>
43*bbecb9d1SAndroid Build Coastguard Worker #else
44*bbecb9d1SAndroid Build Coastguard Worker #include <stdio.h>
45*bbecb9d1SAndroid Build Coastguard Worker #endif
46*bbecb9d1SAndroid Build Coastguard Worker
47*bbecb9d1SAndroid Build Coastguard Worker #if !(defined(__FreeBSD__) || defined(HAVE_MEMFD_CREATE) || defined(HAVE_MKOSTEMP) || defined(__ANDROID__))
48*bbecb9d1SAndroid Build Coastguard Worker static int
set_cloexec_or_close(int fd)49*bbecb9d1SAndroid Build Coastguard Worker set_cloexec_or_close(int fd)
50*bbecb9d1SAndroid Build Coastguard Worker {
51*bbecb9d1SAndroid Build Coastguard Worker long flags;
52*bbecb9d1SAndroid Build Coastguard Worker
53*bbecb9d1SAndroid Build Coastguard Worker if (fd == -1)
54*bbecb9d1SAndroid Build Coastguard Worker return -1;
55*bbecb9d1SAndroid Build Coastguard Worker
56*bbecb9d1SAndroid Build Coastguard Worker flags = fcntl(fd, F_GETFD);
57*bbecb9d1SAndroid Build Coastguard Worker if (flags == -1)
58*bbecb9d1SAndroid Build Coastguard Worker goto err;
59*bbecb9d1SAndroid Build Coastguard Worker
60*bbecb9d1SAndroid Build Coastguard Worker if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
61*bbecb9d1SAndroid Build Coastguard Worker goto err;
62*bbecb9d1SAndroid Build Coastguard Worker
63*bbecb9d1SAndroid Build Coastguard Worker return fd;
64*bbecb9d1SAndroid Build Coastguard Worker
65*bbecb9d1SAndroid Build Coastguard Worker err:
66*bbecb9d1SAndroid Build Coastguard Worker close(fd);
67*bbecb9d1SAndroid Build Coastguard Worker return -1;
68*bbecb9d1SAndroid Build Coastguard Worker }
69*bbecb9d1SAndroid Build Coastguard Worker #endif
70*bbecb9d1SAndroid Build Coastguard Worker
71*bbecb9d1SAndroid Build Coastguard Worker #if !(defined(__FreeBSD__) || defined(HAVE_MEMFD_CREATE) || defined(__ANDROID__))
72*bbecb9d1SAndroid Build Coastguard Worker static int
create_tmpfile_cloexec(char * tmpname)73*bbecb9d1SAndroid Build Coastguard Worker create_tmpfile_cloexec(char *tmpname)
74*bbecb9d1SAndroid Build Coastguard Worker {
75*bbecb9d1SAndroid Build Coastguard Worker int fd;
76*bbecb9d1SAndroid Build Coastguard Worker
77*bbecb9d1SAndroid Build Coastguard Worker #ifdef HAVE_MKOSTEMP
78*bbecb9d1SAndroid Build Coastguard Worker fd = mkostemp(tmpname, O_CLOEXEC);
79*bbecb9d1SAndroid Build Coastguard Worker #else
80*bbecb9d1SAndroid Build Coastguard Worker fd = mkstemp(tmpname);
81*bbecb9d1SAndroid Build Coastguard Worker #endif
82*bbecb9d1SAndroid Build Coastguard Worker
83*bbecb9d1SAndroid Build Coastguard Worker if (fd < 0) {
84*bbecb9d1SAndroid Build Coastguard Worker return fd;
85*bbecb9d1SAndroid Build Coastguard Worker }
86*bbecb9d1SAndroid Build Coastguard Worker
87*bbecb9d1SAndroid Build Coastguard Worker #ifndef HAVE_MKOSTEMP
88*bbecb9d1SAndroid Build Coastguard Worker fd = set_cloexec_or_close(fd);
89*bbecb9d1SAndroid Build Coastguard Worker #endif
90*bbecb9d1SAndroid Build Coastguard Worker
91*bbecb9d1SAndroid Build Coastguard Worker unlink(tmpname);
92*bbecb9d1SAndroid Build Coastguard Worker return fd;
93*bbecb9d1SAndroid Build Coastguard Worker }
94*bbecb9d1SAndroid Build Coastguard Worker #endif
95*bbecb9d1SAndroid Build Coastguard Worker
96*bbecb9d1SAndroid Build Coastguard Worker /*
97*bbecb9d1SAndroid Build Coastguard Worker * Create a new, unique, anonymous file of the given size, and
98*bbecb9d1SAndroid Build Coastguard Worker * return the file descriptor for it. The file descriptor is set
99*bbecb9d1SAndroid Build Coastguard Worker * CLOEXEC. The file is immediately suitable for mmap()'ing
100*bbecb9d1SAndroid Build Coastguard Worker * the given size at offset zero.
101*bbecb9d1SAndroid Build Coastguard Worker *
102*bbecb9d1SAndroid Build Coastguard Worker * An optional name for debugging can be provided as the second argument.
103*bbecb9d1SAndroid Build Coastguard Worker *
104*bbecb9d1SAndroid Build Coastguard Worker * The file should not have a permanent backing store like a disk,
105*bbecb9d1SAndroid Build Coastguard Worker * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
106*bbecb9d1SAndroid Build Coastguard Worker *
107*bbecb9d1SAndroid Build Coastguard Worker * If memfd or SHM_ANON is supported, the filesystem is not touched at all.
108*bbecb9d1SAndroid Build Coastguard Worker * Otherwise, the file name is deleted from the file system.
109*bbecb9d1SAndroid Build Coastguard Worker *
110*bbecb9d1SAndroid Build Coastguard Worker * The file is suitable for buffer sharing between processes by
111*bbecb9d1SAndroid Build Coastguard Worker * transmitting the file descriptor over Unix sockets using the
112*bbecb9d1SAndroid Build Coastguard Worker * SCM_RIGHTS methods.
113*bbecb9d1SAndroid Build Coastguard Worker */
114*bbecb9d1SAndroid Build Coastguard Worker int
os_create_anonymous_file(off_t size,const char * debug_name)115*bbecb9d1SAndroid Build Coastguard Worker os_create_anonymous_file(off_t size, const char *debug_name)
116*bbecb9d1SAndroid Build Coastguard Worker {
117*bbecb9d1SAndroid Build Coastguard Worker int fd, ret;
118*bbecb9d1SAndroid Build Coastguard Worker #if defined(HAVE_MEMFD_CREATE)
119*bbecb9d1SAndroid Build Coastguard Worker if (!debug_name)
120*bbecb9d1SAndroid Build Coastguard Worker debug_name = "mesa-shared";
121*bbecb9d1SAndroid Build Coastguard Worker fd = memfd_create(debug_name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
122*bbecb9d1SAndroid Build Coastguard Worker #elif defined(__ANDROID__)
123*bbecb9d1SAndroid Build Coastguard Worker if (!debug_name)
124*bbecb9d1SAndroid Build Coastguard Worker debug_name = "mesa-shared";
125*bbecb9d1SAndroid Build Coastguard Worker fd = syscall(SYS_memfd_create, debug_name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
126*bbecb9d1SAndroid Build Coastguard Worker #elif defined(__FreeBSD__)
127*bbecb9d1SAndroid Build Coastguard Worker fd = shm_open(SHM_ANON, O_CREAT | O_RDWR | O_CLOEXEC, 0600);
128*bbecb9d1SAndroid Build Coastguard Worker #elif defined(__OpenBSD__)
129*bbecb9d1SAndroid Build Coastguard Worker char template[] = "/tmp/mesa-XXXXXXXXXX";
130*bbecb9d1SAndroid Build Coastguard Worker fd = shm_mkstemp(template);
131*bbecb9d1SAndroid Build Coastguard Worker if (fd != -1)
132*bbecb9d1SAndroid Build Coastguard Worker shm_unlink(template);
133*bbecb9d1SAndroid Build Coastguard Worker #else
134*bbecb9d1SAndroid Build Coastguard Worker const char *path;
135*bbecb9d1SAndroid Build Coastguard Worker char *name;
136*bbecb9d1SAndroid Build Coastguard Worker
137*bbecb9d1SAndroid Build Coastguard Worker path = getenv("XDG_RUNTIME_DIR");
138*bbecb9d1SAndroid Build Coastguard Worker if (!path) {
139*bbecb9d1SAndroid Build Coastguard Worker errno = ENOENT;
140*bbecb9d1SAndroid Build Coastguard Worker return -1;
141*bbecb9d1SAndroid Build Coastguard Worker }
142*bbecb9d1SAndroid Build Coastguard Worker
143*bbecb9d1SAndroid Build Coastguard Worker if (debug_name)
144*bbecb9d1SAndroid Build Coastguard Worker asprintf(&name, "%s/mesa-shared-%s-XXXXXX", path, debug_name);
145*bbecb9d1SAndroid Build Coastguard Worker else
146*bbecb9d1SAndroid Build Coastguard Worker asprintf(&name, "%s/mesa-shared-XXXXXX", path);
147*bbecb9d1SAndroid Build Coastguard Worker if (!name)
148*bbecb9d1SAndroid Build Coastguard Worker return -1;
149*bbecb9d1SAndroid Build Coastguard Worker
150*bbecb9d1SAndroid Build Coastguard Worker fd = create_tmpfile_cloexec(name);
151*bbecb9d1SAndroid Build Coastguard Worker
152*bbecb9d1SAndroid Build Coastguard Worker free(name);
153*bbecb9d1SAndroid Build Coastguard Worker #endif
154*bbecb9d1SAndroid Build Coastguard Worker
155*bbecb9d1SAndroid Build Coastguard Worker if (fd < 0)
156*bbecb9d1SAndroid Build Coastguard Worker return -1;
157*bbecb9d1SAndroid Build Coastguard Worker
158*bbecb9d1SAndroid Build Coastguard Worker ret = ftruncate(fd, size);
159*bbecb9d1SAndroid Build Coastguard Worker if (ret < 0) {
160*bbecb9d1SAndroid Build Coastguard Worker close(fd);
161*bbecb9d1SAndroid Build Coastguard Worker return -1;
162*bbecb9d1SAndroid Build Coastguard Worker }
163*bbecb9d1SAndroid Build Coastguard Worker
164*bbecb9d1SAndroid Build Coastguard Worker return fd;
165*bbecb9d1SAndroid Build Coastguard Worker }
166*bbecb9d1SAndroid Build Coastguard Worker #endif
167