17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2012 Collabora, Ltd. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining 57ec681f3Smrg * a copy of this software and associated documentation files (the 67ec681f3Smrg * "Software"), to deal in the Software without restriction, including 77ec681f3Smrg * without limitation the rights to use, copy, modify, merge, publish, 87ec681f3Smrg * distribute, sublicense, and/or sell copies of the Software, and to 97ec681f3Smrg * permit persons to whom the Software is furnished to do so, subject to 107ec681f3Smrg * the following conditions: 117ec681f3Smrg * 127ec681f3Smrg * The above copyright notice and this permission notice (including the 137ec681f3Smrg * next paragraph) shall be included in all copies or substantial 147ec681f3Smrg * portions of the Software. 157ec681f3Smrg * 167ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 177ec681f3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 187ec681f3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 197ec681f3Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 207ec681f3Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 217ec681f3Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 227ec681f3Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 237ec681f3Smrg * SOFTWARE. 247ec681f3Smrg */ 257ec681f3Smrg 267ec681f3Smrg/* 277ec681f3Smrg * Based on weston shared/os-compatibility.c 287ec681f3Smrg */ 297ec681f3Smrg 307ec681f3Smrg#ifndef _WIN32 317ec681f3Smrg#include "anon_file.h" 327ec681f3Smrg 337ec681f3Smrg#include <unistd.h> 347ec681f3Smrg#include <fcntl.h> 357ec681f3Smrg#include <errno.h> 367ec681f3Smrg#include <stdlib.h> 377ec681f3Smrg 387ec681f3Smrg#if defined(HAVE_MEMFD_CREATE) || defined(__FreeBSD__) || defined(__OpenBSD__) 397ec681f3Smrg#include <sys/mman.h> 407ec681f3Smrg#elif defined(ANDROID) 417ec681f3Smrg#include <sys/syscall.h> 427ec681f3Smrg#include <linux/memfd.h> 437ec681f3Smrg#else 447ec681f3Smrg#include <stdio.h> 457ec681f3Smrg#endif 467ec681f3Smrg 477ec681f3Smrg#if !(defined(__FreeBSD__) || defined(HAVE_MEMFD_CREATE) || defined(HAVE_MKOSTEMP) || defined(ANDROID)) 487ec681f3Smrgstatic int 497ec681f3Smrgset_cloexec_or_close(int fd) 507ec681f3Smrg{ 517ec681f3Smrg long flags; 527ec681f3Smrg 537ec681f3Smrg if (fd == -1) 547ec681f3Smrg return -1; 557ec681f3Smrg 567ec681f3Smrg flags = fcntl(fd, F_GETFD); 577ec681f3Smrg if (flags == -1) 587ec681f3Smrg goto err; 597ec681f3Smrg 607ec681f3Smrg if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) 617ec681f3Smrg goto err; 627ec681f3Smrg 637ec681f3Smrg return fd; 647ec681f3Smrg 657ec681f3Smrgerr: 667ec681f3Smrg close(fd); 677ec681f3Smrg return -1; 687ec681f3Smrg} 697ec681f3Smrg#endif 707ec681f3Smrg 717ec681f3Smrg#if !(defined(__FreeBSD__) || defined(HAVE_MEMFD_CREATE) || defined(ANDROID)) 727ec681f3Smrgstatic int 737ec681f3Smrgcreate_tmpfile_cloexec(char *tmpname) 747ec681f3Smrg{ 757ec681f3Smrg int fd; 767ec681f3Smrg 777ec681f3Smrg#ifdef HAVE_MKOSTEMP 787ec681f3Smrg fd = mkostemp(tmpname, O_CLOEXEC); 797ec681f3Smrg#else 807ec681f3Smrg fd = mkstemp(tmpname); 817ec681f3Smrg#endif 827ec681f3Smrg 837ec681f3Smrg if (fd < 0) { 847ec681f3Smrg return fd; 857ec681f3Smrg } 867ec681f3Smrg 877ec681f3Smrg#ifndef HAVE_MKOSTEMP 887ec681f3Smrg fd = set_cloexec_or_close(fd); 897ec681f3Smrg#endif 907ec681f3Smrg 917ec681f3Smrg unlink(tmpname); 927ec681f3Smrg return fd; 937ec681f3Smrg} 947ec681f3Smrg#endif 957ec681f3Smrg 967ec681f3Smrg/* 977ec681f3Smrg * Create a new, unique, anonymous file of the given size, and 987ec681f3Smrg * return the file descriptor for it. The file descriptor is set 997ec681f3Smrg * CLOEXEC. The file is immediately suitable for mmap()'ing 1007ec681f3Smrg * the given size at offset zero. 1017ec681f3Smrg * 1027ec681f3Smrg * An optional name for debugging can be provided as the second argument. 1037ec681f3Smrg * 1047ec681f3Smrg * The file should not have a permanent backing store like a disk, 1057ec681f3Smrg * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. 1067ec681f3Smrg * 1077ec681f3Smrg * If memfd or SHM_ANON is supported, the filesystem is not touched at all. 1087ec681f3Smrg * Otherwise, the file name is deleted from the file system. 1097ec681f3Smrg * 1107ec681f3Smrg * The file is suitable for buffer sharing between processes by 1117ec681f3Smrg * transmitting the file descriptor over Unix sockets using the 1127ec681f3Smrg * SCM_RIGHTS methods. 1137ec681f3Smrg */ 1147ec681f3Smrgint 1157ec681f3Smrgos_create_anonymous_file(off_t size, const char *debug_name) 1167ec681f3Smrg{ 1177ec681f3Smrg int fd, ret; 1187ec681f3Smrg#if defined(HAVE_MEMFD_CREATE) 1197ec681f3Smrg if (!debug_name) 1207ec681f3Smrg debug_name = "mesa-shared"; 1217ec681f3Smrg fd = memfd_create(debug_name, MFD_CLOEXEC | MFD_ALLOW_SEALING); 1227ec681f3Smrg#elif defined(ANDROID) 1237ec681f3Smrg if (!debug_name) 1247ec681f3Smrg debug_name = "mesa-shared"; 1257ec681f3Smrg fd = syscall(SYS_memfd_create, debug_name, MFD_CLOEXEC | MFD_ALLOW_SEALING); 1267ec681f3Smrg#elif defined(__FreeBSD__) 1277ec681f3Smrg fd = shm_open(SHM_ANON, O_CREAT | O_RDWR | O_CLOEXEC, 0600); 1287ec681f3Smrg#elif defined(__OpenBSD__) 1297ec681f3Smrg char template[] = "/tmp/mesa-XXXXXXXXXX"; 1307ec681f3Smrg fd = shm_mkstemp(template); 1317ec681f3Smrg if (fd != -1) 1327ec681f3Smrg shm_unlink(template); 1337ec681f3Smrg#else 1347ec681f3Smrg const char *path; 1357ec681f3Smrg char *name; 1367ec681f3Smrg 1377ec681f3Smrg path = getenv("XDG_RUNTIME_DIR"); 1387ec681f3Smrg if (!path) { 1397ec681f3Smrg errno = ENOENT; 1407ec681f3Smrg return -1; 1417ec681f3Smrg } 1427ec681f3Smrg 1437ec681f3Smrg if (debug_name) 1447ec681f3Smrg asprintf(&name, "%s/mesa-shared-%s-XXXXXX", path, debug_name); 1457ec681f3Smrg else 1467ec681f3Smrg asprintf(&name, "%s/mesa-shared-XXXXXX", path); 1477ec681f3Smrg if (!name) 1487ec681f3Smrg return -1; 1497ec681f3Smrg 1507ec681f3Smrg fd = create_tmpfile_cloexec(name); 1517ec681f3Smrg 1527ec681f3Smrg free(name); 1537ec681f3Smrg#endif 1547ec681f3Smrg 1557ec681f3Smrg if (fd < 0) 1567ec681f3Smrg return -1; 1577ec681f3Smrg 1587ec681f3Smrg ret = ftruncate(fd, size); 1597ec681f3Smrg if (ret < 0) { 1607ec681f3Smrg close(fd); 1617ec681f3Smrg return -1; 1627ec681f3Smrg } 1637ec681f3Smrg 1647ec681f3Smrg return fd; 1657ec681f3Smrg} 1667ec681f3Smrg#endif 167