1 // Copyright © 2017 Rémi Thebault 2 module wayland.util.shm_helper; 3 4 import std.exception : enforce; 5 import core.sys.posix.stdlib : mkstemp; 6 import core.sys.posix.unistd; 7 import core.sys.posix.fcntl; 8 import core.stdc.config : c_long; 9 10 // createMmapableFile inspired from weston source code. 11 12 /// Create a file of the given size suitable for mmap. 13 /// The file is created under XDG_RUNTIME_DIR and should therfore not be 14 /// backed stored on disk. The shared memory object will be freed by the kernel 15 /// when it is closed and no more mapping is alive. 16 int createMmapableFile(size_t size) 17 { 18 import std.process : environment; 19 enum tmplt = "/wld-d-XXXXXX"; 20 string base = environment.get("XDG_RUNTIME_DIR", "/tmp"); 21 auto path = new char[base.length + tmplt.length + 1]; 22 path[0 .. base.length] = base; 23 path[base.length .. base.length+tmplt.length] = tmplt; 24 path[base.length+tmplt.length] = '\0'; 25 26 immutable fd = createTmpfileCloexec(path.ptr); 27 enforce(fd > 0, "Could not open file for mmap at "~path[0 .. $-1]); 28 29 scope(failure) close(fd); 30 31 import std.format : format; 32 enforce( 33 ftruncate(fd, size) >= 0, 34 format("Could not set mmap file %s to %s bytes", path[0 .. $-1], size) 35 ); 36 37 return fd; 38 } 39 40 private: 41 42 int 43 setCloexecOrClose(int fd) 44 { 45 assert(fd != -1); 46 scope(failure) close(fd); 47 48 auto flags = fcntl(fd, F_GETFD); 49 enforce(flags != -1); 50 enforce(fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1); 51 52 return fd; 53 } 54 55 int 56 createTmpfileCloexec(char* tmpname) 57 { 58 try 59 { 60 auto fd = mkstemp(tmpname); 61 if (fd >= 0) 62 { 63 fd = setCloexecOrClose(fd); 64 unlink(tmpname); 65 } 66 return fd; 67 } 68 catch(Exception ex) 69 { 70 return -1; 71 } 72 }