1 /// Linux platform specific functions
2 module mecca.platform.os.linux;
3 
4 // Licensed under the Boost license. Full copyright information in the AUTHORS file
5 
6 import mecca.log: notrace;
7 
8 version(linux):
9 version(X86_64):
10 
11 public import mecca.platform.os.linux.ucontext;
12 public import mecca.platform.os.linux.time;
13 
14 enum Syscall: int {
15     NR_read = 0,
16     NR_write = 1,
17     NR_open = 2,
18     NR_close = 3,
19     NR_stat = 4,
20     NR_fstat = 5,
21     NR_lstat = 6,
22     NR_poll = 7,
23     NR_lseek = 8,
24     NR_mmap = 9,
25     NR_mprotect = 10,
26     NR_munmap = 11,
27     NR_brk = 12,
28     NR_rt_sigaction = 13,
29     NR_rt_sigprocmask = 14,
30     NR_rt_sigreturn = 15,
31     NR_ioctl = 16,
32     NR_pread64 = 17,
33     NR_pwrite64 = 18,
34     NR_readv = 19,
35     NR_writev = 20,
36     NR_access = 21,
37     NR_pipe = 22,
38     NR_select = 23,
39     NR_sched_yield = 24,
40     NR_mremap = 25,
41     NR_msync = 26,
42     NR_mincore = 27,
43     NR_madvise = 28,
44     NR_shmget = 29,
45     NR_shmat = 30,
46     NR_shmctl = 31,
47     NR_dup = 32,
48     NR_dup2 = 33,
49     NR_pause = 34,
50     NR_nanosleep = 35,
51     NR_getitimer = 36,
52     NR_alarm = 37,
53     NR_setitimer = 38,
54     NR_getpid = 39,
55     NR_sendfile = 40,
56     NR_socket = 41,
57     NR_connect = 42,
58     NR_accept = 43,
59     NR_sendto = 44,
60     NR_recvfrom = 45,
61     NR_sendmsg = 46,
62     NR_recvmsg = 47,
63     NR_shutdown = 48,
64     NR_bind = 49,
65     NR_listen = 50,
66     NR_getsockname = 51,
67     NR_getpeername = 52,
68     NR_socketpair = 53,
69     NR_setsockopt = 54,
70     NR_getsockopt = 55,
71     NR_clone = 56,
72     NR_fork = 57,
73     NR_vfork = 58,
74     NR_execve = 59,
75     NR_exit = 60,
76     NR_wait4 = 61,
77     NR_kill = 62,
78     NR_uname = 63,
79     NR_semget = 64,
80     NR_semop = 65,
81     NR_semctl = 66,
82     NR_shmdt = 67,
83     NR_msgget = 68,
84     NR_msgsnd = 69,
85     NR_msgrcv = 70,
86     NR_msgctl = 71,
87     NR_fcntl = 72,
88     NR_flock = 73,
89     NR_fsync = 74,
90     NR_fdatasync = 75,
91     NR_truncate = 76,
92     NR_ftruncate = 77,
93     NR_getdents = 78,
94     NR_getcwd = 79,
95     NR_chdir = 80,
96     NR_fchdir = 81,
97     NR_rename = 82,
98     NR_mkdir = 83,
99     NR_rmdir = 84,
100     NR_creat = 85,
101     NR_link = 86,
102     NR_unlink = 87,
103     NR_symlink = 88,
104     NR_readlink = 89,
105     NR_chmod = 90,
106     NR_fchmod = 91,
107     NR_chown = 92,
108     NR_fchown = 93,
109     NR_lchown = 94,
110     NR_umask = 95,
111     NR_gettimeofday = 96,
112     NR_getrlimit = 97,
113     NR_getrusage = 98,
114     NR_sysinfo = 99,
115     NR_times = 100,
116     NR_ptrace = 101,
117     NR_getuid = 102,
118     NR_syslog = 103,
119     NR_getgid = 104,
120     NR_setuid = 105,
121     NR_setgid = 106,
122     NR_geteuid = 107,
123     NR_getegid = 108,
124     NR_setpgid = 109,
125     NR_getppid = 110,
126     NR_getpgrp = 111,
127     NR_setsid = 112,
128     NR_setreuid = 113,
129     NR_setregid = 114,
130     NR_getgroups = 115,
131     NR_setgroups = 116,
132     NR_setresuid = 117,
133     NR_getresuid = 118,
134     NR_setresgid = 119,
135     NR_getresgid = 120,
136     NR_getpgid = 121,
137     NR_setfsuid = 122,
138     NR_setfsgid = 123,
139     NR_getsid = 124,
140     NR_capget = 125,
141     NR_capset = 126,
142     NR_rt_sigpending = 127,
143     NR_rt_sigtimedwait = 128,
144     NR_rt_sigqueueinfo = 129,
145     NR_rt_sigsuspend = 130,
146     NR_sigaltstack = 131,
147     NR_utime = 132,
148     NR_mknod = 133,
149     NR_uselib = 134,
150     NR_personality = 135,
151     NR_ustat = 136,
152     NR_statfs = 137,
153     NR_fstatfs = 138,
154     NR_sysfs = 139,
155     NR_getpriority = 140,
156     NR_setpriority = 141,
157     NR_sched_setparam = 142,
158     NR_sched_getparam = 143,
159     NR_sched_setscheduler = 144,
160     NR_sched_getscheduler = 145,
161     NR_sched_get_priority_max = 146,
162     NR_sched_get_priority_min = 147,
163     NR_sched_rr_get_interval = 148,
164     NR_mlock = 149,
165     NR_munlock = 150,
166     NR_mlockall = 151,
167     NR_munlockall = 152,
168     NR_vhangup = 153,
169     NR_modify_ldt = 154,
170     NR_pivot_root = 155,
171     NR__sysctl = 156,
172     NR_prctl = 157,
173     NR_arch_prctl = 158,
174     NR_adjtimex = 159,
175     NR_setrlimit = 160,
176     NR_chroot = 161,
177     NR_sync = 162,
178     NR_acct = 163,
179     NR_settimeofday = 164,
180     NR_mount = 165,
181     NR_umount2 = 166,
182     NR_swapon = 167,
183     NR_swapoff = 168,
184     NR_reboot = 169,
185     NR_sethostname = 170,
186     NR_setdomainname = 171,
187     NR_iopl = 172,
188     NR_ioperm = 173,
189     NR_create_module = 174,
190     NR_init_module = 175,
191     NR_delete_module = 176,
192     NR_get_kernel_syms = 177,
193     NR_query_module = 178,
194     NR_quotactl = 179,
195     NR_nfsservctl = 180,
196     NR_getpmsg = 181,
197     NR_putpmsg = 182,
198     NR_afs_syscall = 183,
199     NR_tuxcall = 184,
200     NR_security = 185,
201     NR_gettid = 186,
202     NR_readahead = 187,
203     NR_setxattr = 188,
204     NR_lsetxattr = 189,
205     NR_fsetxattr = 190,
206     NR_getxattr = 191,
207     NR_lgetxattr = 192,
208     NR_fgetxattr = 193,
209     NR_listxattr = 194,
210     NR_llistxattr = 195,
211     NR_flistxattr = 196,
212     NR_removexattr = 197,
213     NR_lremovexattr = 198,
214     NR_fremovexattr = 199,
215     NR_tkill = 200,
216     NR_time = 201,
217     NR_futex = 202,
218     NR_sched_setaffinity = 203,
219     NR_sched_getaffinity = 204,
220     NR_set_thread_area = 205,
221     NR_io_setup = 206,
222     NR_io_destroy = 207,
223     NR_io_getevents = 208,
224     NR_io_submit = 209,
225     NR_io_cancel = 210,
226     NR_get_thread_area = 211,
227     NR_lookup_dcookie = 212,
228     NR_epoll_create = 213,
229     NR_epoll_ctl_old = 214,
230     NR_epoll_wait_old = 215,
231     NR_remap_file_pages = 216,
232     NR_getdents64 = 217,
233     NR_set_tid_address = 218,
234     NR_restart_syscall = 219,
235     NR_semtimedop = 220,
236     NR_fadvise64 = 221,
237     NR_timer_create = 222,
238     NR_timer_settime = 223,
239     NR_timer_gettime = 224,
240     NR_timer_getoverrun = 225,
241     NR_timer_delete = 226,
242     NR_clock_settime = 227,
243     NR_clock_gettime = 228,
244     NR_clock_getres = 229,
245     NR_clock_nanosleep = 230,
246     NR_exit_group = 231,
247     NR_epoll_wait = 232,
248     NR_epoll_ctl = 233,
249     NR_tgkill = 234,
250     NR_utimes = 235,
251     NR_vserver = 236,
252     NR_mbind = 237,
253     NR_set_mempolicy = 238,
254     NR_get_mempolicy = 239,
255     NR_mq_open = 240,
256     NR_mq_unlink = 241,
257     NR_mq_timedsend = 242,
258     NR_mq_timedreceive = 243,
259     NR_mq_notify = 244,
260     NR_mq_getsetattr = 245,
261     NR_kexec_load = 246,
262     NR_waitid = 247,
263     NR_add_key = 248,
264     NR_request_key = 249,
265     NR_keyctl = 250,
266     NR_ioprio_set = 251,
267     NR_ioprio_get = 252,
268     NR_inotify_init = 253,
269     NR_inotify_add_watch = 254,
270     NR_inotify_rm_watch = 255,
271     NR_migrate_pages = 256,
272     NR_openat = 257,
273     NR_mkdirat = 258,
274     NR_mknodat = 259,
275     NR_fchownat = 260,
276     NR_futimesat = 261,
277     NR_newfstatat = 262,
278     NR_unlinkat = 263,
279     NR_renameat = 264,
280     NR_linkat = 265,
281     NR_symlinkat = 266,
282     NR_readlinkat = 267,
283     NR_fchmodat = 268,
284     NR_faccessat = 269,
285     NR_pselect6 = 270,
286     NR_ppoll = 271,
287     NR_unshare = 272,
288     NR_set_robust_list = 273,
289     NR_get_robust_list = 274,
290     NR_splice = 275,
291     NR_tee = 276,
292     NR_sync_file_range = 277,
293     NR_vmsplice = 278,
294     NR_move_pages = 279,
295     NR_utimensat = 280,
296     NR_epoll_pwait = 281,
297     NR_signalfd = 282,
298     NR_timerfd_create = 283,
299     NR_eventfd = 284,
300     NR_fallocate = 285,
301     NR_timerfd_settime = 286,
302     NR_timerfd_gettime = 287,
303     NR_accept4 = 288,
304     NR_signalfd4 = 289,
305     NR_eventfd2 = 290,
306     NR_epoll_create1 = 291,
307     NR_dup3 = 292,
308     NR_pipe2 = 293,
309     NR_inotify_init1 = 294,
310     NR_preadv = 295,
311     NR_pwritev = 296,
312     NR_rt_tgsigqueueinfo = 297,
313     NR_perf_event_open = 298,
314     NR_recvmmsg = 299,
315     NR_fanotify_init = 300,
316     NR_fanotify_mark = 301,
317     NR_prlimit64 = 302,
318     NR_name_to_handle_at = 303,
319     NR_open_by_handle_at = 304,
320     NR_clock_adjtime = 305,
321     NR_syncfs = 306,
322     NR_sendmmsg = 307,
323     NR_setns = 308,
324     NR_getcpu = 309,
325     NR_process_vm_readv = 310,
326     NR_process_vm_writev = 311,
327     NR_kcmp = 312,
328     NR_finit_module = 313,
329     NR_sched_setattr = 314,
330     NR_sched_getattr = 315,
331     NR_renameat2 = 316,
332     NR_seccomp = 317,
333 }
334 
335 extern(C) nothrow @system @nogc {
336     long syscall(int number, ...) nothrow;
337 
338     @notrace
339     int syscall_int(ARGS...)(int number, auto ref ARGS args) nothrow {
340         return cast(int)syscall(number, args);
341     }
342 
343     @notrace
344     int gettid() nothrow @trusted {
345         return syscall_int(Syscall.NR_gettid);
346     }
347 
348     @notrace
349     int tgkill(int tgid, int tid, int sig) nothrow @trusted {
350         return syscall_int(Syscall.NR_tgkill, tgid, tid, sig);
351     }
352 }
353 
354 unittest {
355     import core.thread: thread_isMainThread;
356     import core.sys.posix.unistd: getpid;
357     assert (thread_isMainThread());
358     assert (gettid() == getpid());
359 }
360 
361 enum OSSignal: uint {
362     SIGNONE        = 0,       /// Invalid signal
363     SIGHUP         = 1,       /// Hangup (POSIX).
364     SIGINT         = 2,       /// Interrupt (ANSI).
365     SIGQUIT        = 3,       /// Quit (POSIX).
366     SIGILL         = 4,       /// Illegal instruction (ANSI).
367     SIGTRAP        = 5,       /// Trace trap (POSIX).
368     SIGABRT        = 6,       /// Abort (ANSI).
369     SIGBUS         = 7,       /// BUS error (4.2 BSD).
370     SIGFPE         = 8,       /// Floating-point exception (ANSI).
371     SIGKILL        = 9,       /// Kill, unblockable (POSIX).
372     SIGUSR1        = 10,      /// User-defined signal 1 (POSIX).
373     SIGSEGV        = 11,      /// Segmentation violation (ANSI).
374     SIGUSR2        = 12,      /// User-defined signal 2 (POSIX).
375     SIGPIPE        = 13,      /// Broken pipe (POSIX).
376     SIGALRM        = 14,      /// Alarm clock (POSIX).
377     SIGTERM        = 15,      /// Termination (ANSI).
378     SIGSTKFLT      = 16,      /// Stack fault.
379     SIGCHLD        = 17,      /// Child status has changed (POSIX).
380     SIGCONT        = 18,      /// Continue (POSIX).
381     SIGSTOP        = 19,      /// Stop, unblockable (POSIX).
382     SIGTSTP        = 20,      /// Keyboard stop (POSIX).
383     SIGTTIN        = 21,      /// Background read from tty (POSIX).
384     SIGTTOU        = 22,      /// Background write to tty (POSIX).
385     SIGURG         = 23,      /// Urgent condition on socket (4.2 BSD).
386     SIGXCPU        = 24,      /// CPU limit exceeded (4.2 BSD).
387     SIGXFSZ        = 25,      /// File size limit exceeded (4.2 BSD).
388     SIGVTALRM      = 26,      /// Virtual alarm clock (4.2 BSD).
389     SIGPROF        = 27,      /// Profiling alarm clock (4.2 BSD).
390     SIGWINCH       = 28,      /// Window size change (4.3 BSD, Sun).
391     SIGIO          = 29,      /// I/O now possible (4.2 BSD).
392     SIGPOLL        = SIGIO,   /// ditto
393     SIGPWR         = 30,      /// Power failure restart (System V).
394     SIGSYS         = 31,      /// Bad system call.
395 }
396 
397 /* _NSIG: Biggest signal number + 1 (including real-time signals).  */
398 enum NUM_SIGS = 65;
399 
400 public import core.sys.posix.signal: SIGRTMIN, SIGRTMAX;
401 
402 unittest {
403     assert (SIGRTMIN > OSSignal.SIGSYS);
404     assert (SIGRTMAX < NUM_SIGS);
405 }
406 
407 
408 extern(C) nothrow /*@nogc*/ {
409     public alias CloneFunction = extern(C) int function(void*) nothrow /*@nogc*/;
410     public int clone(CloneFunction fn, void* child_stack, int flags, void* args);
411     public int unshare(int flags);
412     public int chroot(const char* dirname);
413     public enum {
414         CSIGNAL                 = 0x000000ff,     // signal mask to be sent at exit
415         CLONE_VM                = 0x00000100,     // set if VM shared between processes
416         CLONE_FS                = 0x00000200,     // set if fs info shared between processes
417         CLONE_FILES             = 0x00000400,     // set if open files shared between processes
418         CLONE_SIGHAND           = 0x00000800,     // set if signal handlers and blocked signals shared
419         CLONE_PTRACE            = 0x00002000,     // set if we want to let tracing continue on the child too
420         CLONE_VFORK             = 0x00004000,     // set if the parent wants the child to wake it up on mm_release
421         CLONE_PARENT            = 0x00008000,     // set if we want to have the same parent as the cloner
422         CLONE_THREAD            = 0x00010000,     // Same thread group?
423         CLONE_NEWNS             = 0x00020000,     // New namespace group?
424         CLONE_SYSVSEM           = 0x00040000,     // share system V SEM_UNDO semantics
425         CLONE_SETTLS            = 0x00080000,     // create a new TLS for the child
426         CLONE_PARENT_SETTID     = 0x00100000,     // set the TID in the parent
427         CLONE_CHILD_CLEARTID    = 0x00200000,     // clear the TID in the child
428         CLONE_DETACHED          = 0x00400000,     // Unused, ignored
429         CLONE_UNTRACED          = 0x00800000,     // set if the tracing process can't force CLONE_PTRACE on this clone
430         CLONE_CHILD_SETTID      = 0x01000000,     // set the TID in the child
431         CLONE_NEWUTS            = 0x04000000,     // New utsname group?
432         CLONE_NEWIPC            = 0x08000000,     // New ipcs
433         CLONE_NEWUSER           = 0x10000000,     // New user namespace
434         CLONE_NEWPID            = 0x20000000,     // New pid namespace
435         CLONE_NEWNET            = 0x40000000,     // New network namespace
436         CLONE_IO                = 0x80000000,     // Clone io context
437     }
438 
439     public int mount(in char* __special_file, in char* __dir, in char* __fstype, ulong __rwflag, in void* __data);
440     public int umount(in char* target);
441     public int umount2(in char* target, int flags);
442     public enum MountOptions {
443         MS_RDONLY = 1,                // Mount read-only.
444         MS_NOSUID = 2,                // Ignore suid and sgid bits.
445         MS_NODEV = 4,                 // Disallow access to device special files.
446         MS_NOEXEC = 8,                // Disallow program execution.
447         MS_SYNCHRONOUS = 16,          // Writes are synced at once.
448         MS_REMOUNT = 32,              // Alter flags of a mounted FS.
449         MS_MANDLOCK = 64,             // Allow mandatory locks on an FS.
450         MS_DIRSYNC = 128,             // Directory modifications are synchronous.
451         MS_NOATIME = 1024,            // Do not update access times.
452         MS_NODIRATIME = 2048,         // Do not update directory access times.
453         MS_BIND = 4096,               // Bind directory at different place.
454         MS_MOVE = 8192,
455         MS_REC = 16384,
456         MS_SILENT = 32768,
457         MS_POSIXACL = 1 << 16,        // VFS does not apply the umask.
458         MS_UNBINDABLE = 1 << 17,      // Change to unbindable.
459         MS_PRIVATE = 1 << 18,         // Change to private.
460         MS_SLAVE = 1 << 19,           // Change to slave.
461         MS_SHARED = 1 << 20,          // Change to shared.
462         MS_RELATIME = 1 << 21,        // Update atime relative to mtime/ctime.
463         MS_KERNMOUNT = 1 << 22,       // This is a kern_mount call.
464         MS_I_VERSION =  1 << 23,      // Update inode I_version field.
465         MS_STRICTATIME = 1 << 24,     // Always perform atime updates.
466         MS_ACTIVE = 1 << 30,
467         MS_NOUSER = 1 << 31
468     }
469     public enum {
470         MNT_FORCE = 1,                /* Force unmounting.  */
471         MNT_DETACH = 2,               /* Just detach from the tree.  */
472         MNT_EXPIRE = 4,               /* Mark for expiry.  */
473         UMOUNT_NOFOLLOW = 8           /* Don't follow symlink on umount.  */
474     };
475 }
476 
477 /** Intercept a library of a system call
478  *
479  * To use: define a function (typically, with `extern(C)` linkage) that performs the alternative implementation of
480  * the library call. Then expand the template mixin here, giving it your function as a template argument.
481  *
482  * The template mixin will define a function called `next_` $(I yourfunction)
483  *
484  * Example:
485  * ---
486  * extern(C) int socket(int domain, int type, int protocol) {
487  *     import std.stdio;
488  *     int ret = next_socket(domain, type, protocol);
489  *
490  *     writefln("socket(%s, %s, %s) = %s", domain, type, protocol, ret);
491  *
492  *     return ret;
493  * }
494  *
495  * mixin InterceptCall!socket;
496  * ---
497  */
498 mixin template InterceptCall(alias F) {
499 private:
500     import core.sys.posix.dlfcn: dlsym;
501     import core.sys.linux.dlfcn: RTLD_NEXT;
502     import std..string: format;
503     import mecca.lib.reflection:  funcAttrToString;
504 
505     mixin(q{
506             typeof(F)* next_%1$s = &stub_%1$s;
507 
508             extern(%2$s) ReturnType!F stub_%1$s(Parameters!F args) %3$s {
509                 if( next_%1$s is &stub_%1$s ) {
510                     next_%1$s = cast(typeof(F)*)dlsym(RTLD_NEXT, "%1$s");
511                 }
512 
513                 return next_%1$s(args);
514             }
515         }.format(mangledName!F, functionLinkage!F, funcAttrToString(functionAttributes!F)));
516 }
517 
518 enum SyscallTracePoint {
519     PRE_SYSCALL,
520     POST_SYSCALL,
521 }
522 
523 mixin template hookSyscall(alias F, Syscall nr, alias traceFunc, SyscallTracePoint tracePoint=SyscallTracePoint.PRE_SYSCALL, string file = __FILE_FULL_PATH__, size_t line = __LINE__, string _module_ = __MODULE__) {
524     import std.traits: Parameters, ReturnType;
525     import mecca.platform.linux: syscall;
526     enum name = __traits(identifier, F);
527     mixin("extern(C) pragma(mangle, \"" ~ name ~ "\") @system ReturnType!F " ~ name ~ "(Parameters!F args) {
528             static if (tracePoint == SyscallTracePoint.PRE_SYSCALL) {
529                 traceFunc(args);
530             }
531             auto res = cast(ReturnType!F)syscall(nr, args);
532             static if (tracePoint == SyscallTracePoint.POST_SYSCALL) {
533                 traceFunc(res, args);
534             }
535             return res;
536         }"
537     );
538     import std.traits: fullyQualifiedName;
539     enum hookFunctionScope = fullyQualifiedName!(__traits(parent, name));
540     static assert(_module_ == hookFunctionScope,
541         "syscall hook should be mixed into the global scope of a module in order for the linker to find it (instantiated on " ~ file ~ "(" ~ line.to!string ~ ")");
542 }
543 
544 /+version (unittest) {
545     __gshared bool hitPreFunc = false;
546 
547     static import core.sys.posix.unistd;
548     mixin hookSyscall!(core.sys.posix.unistd.close, Syscall.NR_close, (int fd){hitPreFunc = true;});
549 
550     unittest {
551         import std.stdio;
552         auto f = File("/tmp/test", "w");
553         f.close();
554         assert (hitPreFunc);
555     }
556 }+/
557 
558 public import core.sys.linux.sys.mman : MAP_POPULATE, MREMAP_MAYMOVE;
559 import core.sys.posix.sys.types : pid_t;
560 import std.traits : ReturnType;
561 
562 package(mecca):
563 
564 /**
565  * Represents the ID of a thread.
566  *
567  * This type is platform dependent.
568  */
569 alias ThreadId = ReturnType!gettid;
570 
571 /**
572  * Represents the ID of a thread.
573  *
574  * This type is platform dependent.
575  */
576 ThreadId currentThreadId() nothrow @system @nogc
577 {
578     return gettid();
579 }
580 
581 __gshared static immutable BLOCKED_SIGNALS = [
582     OSSignal.SIGHUP, OSSignal.SIGINT, OSSignal.SIGQUIT,
583     //OSSignal.SIGILL, OSSignal.SIGTRAP, OSSignal.SIGABRT,
584     //OSSignal.SIGBUS, OSSignal.SIGFPE, OSSignal.SIGKILL,
585     //OSSignal.SIGUSR1, OSSignal.SIGSEGV, OSSignal.SIGUSR2,
586     OSSignal.SIGPIPE, OSSignal.SIGALRM, OSSignal.SIGTERM,
587     //OSSignal.SIGSTKFLT, OSSignal.SIGCONT, OSSignal.SIGSTOP,
588     OSSignal.SIGCHLD, OSSignal.SIGTSTP, OSSignal.SIGTTIN,
589     OSSignal.SIGTTOU, OSSignal.SIGURG, OSSignal.SIGXCPU,
590     OSSignal.SIGXFSZ, OSSignal.SIGVTALRM, OSSignal.SIGPROF,
591     OSSignal.SIGWINCH, OSSignal.SIGIO, OSSignal.SIGPWR,
592     //OSSignal.SIGSYS,
593 ];
594 
595 static if( __traits(compiles, O_CLOEXEC) ) {
596     enum O_CLOEXEC = core.sys.posix.fcntl.O_CLOEXEC;
597 } else {
598     enum O_CLOEXEC = 0x80000;
599 }
600 
601 import fcntl = core.sys.posix.fcntl;
602 static if( __traits(compiles, fcntl.F_DUPFD_CLOEXEC) ) {
603     enum F_DUPFD_CLOEXEC = fcntl.F_DUPFD_CLOEXEC;
604 } else {
605     version(linux) {
606         enum F_DUPFD_CLOEXEC = 1030;
607     }
608 }
609 
610 public import core.stdc.errno : EREMOTEIO;
611 public import core.sys.posix.sys.time : ITIMER_REAL;
612 
613 import mecca.platform.os : MmapArguments;
614 
615 // A wrapper that is compatible with the signature used for Darwin
616 void* mremap(Args...)(MmapArguments, void* oldAddress,
617     size_t oldSize, size_t newSize, int flags, Args args)
618 {
619     import core.sys.linux.sys.mman: mremap;
620     return mremap(oldAddress, oldSize, newSize, flags, args);
621 }