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