diff --git a/pkgs/unix_api/constants.yaml b/pkgs/unix_api/constants.yaml index 924f9990..3fba4a1d 100644 --- a/pkgs/unix_api/constants.yaml +++ b/pkgs/unix_api/constants.yaml @@ -1,3 +1,25 @@ +"": + - MAP_ANONYMOUS + - MAP_FIXED + - MAP_PRIVATE + - MAP_SHARED + - MCL_CURRENT + - MCL_FUTURE + - MS_ASYNC + - MS_INVALIDATE + - MS_SYNC + - POSIX_MADV_DONTNEED + - POSIX_MADV_NORMAL + - POSIX_MADV_RANDOM + - POSIX_MADV_SEQUENTIAL + - POSIX_MADV_WILLNEED + - POSIX_TYPED_MEM_ALLOCATE + - POSIX_TYPED_MEM_ALLOCATE_CONTIG + - POSIX_TYPED_MEM_MAP_ALLOCATABLE + - PROT_EXEC + - PROT_NONE + - PROT_READ + - PROT_WRITE "": - AT_SYMLINK_NOFOLLOW - AT_RESOLVE_BENEATH @@ -34,9 +56,11 @@ - UF_HIDDEN "": - EACCES + - EBADF - EDOM - EEXIST - EINTR + - EINVAL - EMFILE - ENOENT - ENOSPC diff --git a/pkgs/unix_api/functions.yaml b/pkgs/unix_api/functions.yaml index 9e5df211..640f007b 100644 --- a/pkgs/unix_api/functions.yaml +++ b/pkgs/unix_api/functions.yaml @@ -22,6 +22,30 @@ - prototype: "char *strerror(int)" comment: "Formats an error code as a string." url: "https://pubs.opengroup.org/onlinepubs/9699919799/functions/strerror.html" +"": + - prototype: "int mlock(const void *, size_t)" + comment: "Locks a range of process address space." + url: "https://pubs.opengroup.org/onlinepubs/9699919799/functions/mlock.html" + error_value: "-1" + - prototype: "int mlockall(int)" + comment: "Locks the processes address space." + url: "https://pubs.opengroup.org/onlinepubs/9699919799/functions/mlockall.html" + - prototype: "void *mmap(void *, size_t, int, int, int, off_t)" + comment: "Maps pages of memory." + url: "https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html" + error_value: "MAP_FAILED" + - prototype: "int mprotect(void *, size_t, int)" + comment: "Sets the protection of mapped memory." + url: "https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html" + error_value: "-1" + - prototype: "int munlock(const void *, size_t)" + comment: Unlocks a range of process address space." + url: "https://pubs.opengroup.org/onlinepubs/9699919799/functions/munlock.html" + error_value: "-1" + - prototype: "int munmap(void *, size_t)" + comment: "Unmaps pages of memory." + url: "https://pubs.opengroup.org/onlinepubs/9699919799/functions/munmap.html" + error_value: "-1" "": - prototype: "int chmod(const char *, mode_t)" comment: "Changes the mode of a file." diff --git a/pkgs/unix_api/handwritten-constants-ffigen.yaml b/pkgs/unix_api/handwritten-constants-ffigen.yaml new file mode 100644 index 00000000..4ec26612 --- /dev/null +++ b/pkgs/unix_api/handwritten-constants-ffigen.yaml @@ -0,0 +1,18 @@ +# Run with `dart run ffigen --config constants-ffigen.yaml`. +name: NativeAddBindings +description: | + Bindings for `handwritten_constants.h`. + + Regenerate bindings with `dart run tool/generate.dart`. +output: 'lib/src/handwritten_constant_bindings.g.dart' +headers: + entry-points: + - 'src/handwritten_constants.h' + + include-directives: + - 'src/handwritten_constants.h' +comments: + style: any + length: full +ffi-native: + asset-id: package:unix_api/libc_shim diff --git a/pkgs/unix_api/hook/build.dart b/pkgs/unix_api/hook/build.dart index a308e515..a1d79d07 100644 --- a/pkgs/unix_api/hook/build.dart +++ b/pkgs/unix_api/hook/build.dart @@ -17,7 +17,12 @@ void main(List args) async { libraries: [ if ([OS.linux].contains(input.config.code.targetOS)) 'crypt', ], - sources: ['src/libc_shim.c', 'src/constants.g.c', 'src/functions.g.c'], + sources: [ + 'src/libc_shim.c', + 'src/constants.g.c', + 'src/functions.g.c', + 'src/handwritten_constants.c', + ], flags: ['-Weverything'], ).run( input: input, diff --git a/pkgs/unix_api/lib/src/constant_bindings.g.dart b/pkgs/unix_api/lib/src/constant_bindings.g.dart index dfdb828a..bbf36df9 100644 --- a/pkgs/unix_api/lib/src/constant_bindings.g.dart +++ b/pkgs/unix_api/lib/src/constant_bindings.g.dart @@ -34,6 +34,9 @@ external int get_DT_UNKNOWN(); @ffi.Native(symbol: 'libc_shim_get_EACCES') external int get_EACCES(); +@ffi.Native(symbol: 'libc_shim_get_EBADF') +external int get_EBADF(); + @ffi.Native(symbol: 'libc_shim_get_EDOM') external int get_EDOM(); @@ -43,6 +46,9 @@ external int get_EEXIST(); @ffi.Native(symbol: 'libc_shim_get_EINTR') external int get_EINTR(); +@ffi.Native(symbol: 'libc_shim_get_EINVAL') +external int get_EINVAL(); + @ffi.Native(symbol: 'libc_shim_get_EMFILE') external int get_EMFILE(); @@ -97,6 +103,75 @@ external int get_PATH_MAX(); @ffi.Native(symbol: 'libc_shim_get_L_ctermid') external int get_L_ctermid(); +@ffi.Native(symbol: 'libc_shim_get_MAP_ANONYMOUS') +external int get_MAP_ANONYMOUS(); + +@ffi.Native(symbol: 'libc_shim_get_MAP_FIXED') +external int get_MAP_FIXED(); + +@ffi.Native(symbol: 'libc_shim_get_MAP_PRIVATE') +external int get_MAP_PRIVATE(); + +@ffi.Native(symbol: 'libc_shim_get_MAP_SHARED') +external int get_MAP_SHARED(); + +@ffi.Native(symbol: 'libc_shim_get_MCL_CURRENT') +external int get_MCL_CURRENT(); + +@ffi.Native(symbol: 'libc_shim_get_MCL_FUTURE') +external int get_MCL_FUTURE(); + +@ffi.Native(symbol: 'libc_shim_get_MS_ASYNC') +external int get_MS_ASYNC(); + +@ffi.Native(symbol: 'libc_shim_get_MS_INVALIDATE') +external int get_MS_INVALIDATE(); + +@ffi.Native(symbol: 'libc_shim_get_MS_SYNC') +external int get_MS_SYNC(); + +@ffi.Native(symbol: 'libc_shim_get_POSIX_MADV_DONTNEED') +external int get_POSIX_MADV_DONTNEED(); + +@ffi.Native(symbol: 'libc_shim_get_POSIX_MADV_NORMAL') +external int get_POSIX_MADV_NORMAL(); + +@ffi.Native(symbol: 'libc_shim_get_POSIX_MADV_RANDOM') +external int get_POSIX_MADV_RANDOM(); + +@ffi.Native(symbol: 'libc_shim_get_POSIX_MADV_SEQUENTIAL') +external int get_POSIX_MADV_SEQUENTIAL(); + +@ffi.Native(symbol: 'libc_shim_get_POSIX_MADV_WILLNEED') +external int get_POSIX_MADV_WILLNEED(); + +@ffi.Native( + symbol: 'libc_shim_get_POSIX_TYPED_MEM_ALLOCATE', +) +external int get_POSIX_TYPED_MEM_ALLOCATE(); + +@ffi.Native( + symbol: 'libc_shim_get_POSIX_TYPED_MEM_ALLOCATE_CONTIG', +) +external int get_POSIX_TYPED_MEM_ALLOCATE_CONTIG(); + +@ffi.Native( + symbol: 'libc_shim_get_POSIX_TYPED_MEM_MAP_ALLOCATABLE', +) +external int get_POSIX_TYPED_MEM_MAP_ALLOCATABLE(); + +@ffi.Native(symbol: 'libc_shim_get_PROT_EXEC') +external int get_PROT_EXEC(); + +@ffi.Native(symbol: 'libc_shim_get_PROT_NONE') +external int get_PROT_NONE(); + +@ffi.Native(symbol: 'libc_shim_get_PROT_READ') +external int get_PROT_READ(); + +@ffi.Native(symbol: 'libc_shim_get_PROT_WRITE') +external int get_PROT_WRITE(); + @ffi.Native(symbol: 'libc_shim_get_AT_SYMLINK_NOFOLLOW') external int get_AT_SYMLINK_NOFOLLOW(); diff --git a/pkgs/unix_api/lib/src/constants.g.dart b/pkgs/unix_api/lib/src/constants.g.dart index f552008d..9268df81 100644 --- a/pkgs/unix_api/lib/src/constants.g.dart +++ b/pkgs/unix_api/lib/src/constants.g.dart @@ -86,6 +86,15 @@ int get EACCES { } } +int get EBADF { + final v = get_EBADF(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('EBADF'); + } else { + return v; + } +} + int get EDOM { final v = get_EDOM(); if (v == libc_shim_UNDEFINED) { @@ -113,6 +122,15 @@ int get EINTR { } } +int get EINVAL { + final v = get_EINVAL(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('EINVAL'); + } else { + return v; + } +} + int get EMFILE { final v = get_EMFILE(); if (v == libc_shim_UNDEFINED) { @@ -275,6 +293,195 @@ int get L_ctermid { } } +int get MAP_ANONYMOUS { + final v = get_MAP_ANONYMOUS(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('MAP_ANONYMOUS'); + } else { + return v; + } +} + +int get MAP_FIXED { + final v = get_MAP_FIXED(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('MAP_FIXED'); + } else { + return v; + } +} + +int get MAP_PRIVATE { + final v = get_MAP_PRIVATE(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('MAP_PRIVATE'); + } else { + return v; + } +} + +int get MAP_SHARED { + final v = get_MAP_SHARED(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('MAP_SHARED'); + } else { + return v; + } +} + +int get MCL_CURRENT { + final v = get_MCL_CURRENT(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('MCL_CURRENT'); + } else { + return v; + } +} + +int get MCL_FUTURE { + final v = get_MCL_FUTURE(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('MCL_FUTURE'); + } else { + return v; + } +} + +int get MS_ASYNC { + final v = get_MS_ASYNC(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('MS_ASYNC'); + } else { + return v; + } +} + +int get MS_INVALIDATE { + final v = get_MS_INVALIDATE(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('MS_INVALIDATE'); + } else { + return v; + } +} + +int get MS_SYNC { + final v = get_MS_SYNC(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('MS_SYNC'); + } else { + return v; + } +} + +int get POSIX_MADV_DONTNEED { + final v = get_POSIX_MADV_DONTNEED(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('POSIX_MADV_DONTNEED'); + } else { + return v; + } +} + +int get POSIX_MADV_NORMAL { + final v = get_POSIX_MADV_NORMAL(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('POSIX_MADV_NORMAL'); + } else { + return v; + } +} + +int get POSIX_MADV_RANDOM { + final v = get_POSIX_MADV_RANDOM(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('POSIX_MADV_RANDOM'); + } else { + return v; + } +} + +int get POSIX_MADV_SEQUENTIAL { + final v = get_POSIX_MADV_SEQUENTIAL(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('POSIX_MADV_SEQUENTIAL'); + } else { + return v; + } +} + +int get POSIX_MADV_WILLNEED { + final v = get_POSIX_MADV_WILLNEED(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('POSIX_MADV_WILLNEED'); + } else { + return v; + } +} + +int get POSIX_TYPED_MEM_ALLOCATE { + final v = get_POSIX_TYPED_MEM_ALLOCATE(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('POSIX_TYPED_MEM_ALLOCATE'); + } else { + return v; + } +} + +int get POSIX_TYPED_MEM_ALLOCATE_CONTIG { + final v = get_POSIX_TYPED_MEM_ALLOCATE_CONTIG(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('POSIX_TYPED_MEM_ALLOCATE_CONTIG'); + } else { + return v; + } +} + +int get POSIX_TYPED_MEM_MAP_ALLOCATABLE { + final v = get_POSIX_TYPED_MEM_MAP_ALLOCATABLE(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('POSIX_TYPED_MEM_MAP_ALLOCATABLE'); + } else { + return v; + } +} + +int get PROT_EXEC { + final v = get_PROT_EXEC(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('PROT_EXEC'); + } else { + return v; + } +} + +int get PROT_NONE { + final v = get_PROT_NONE(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('PROT_NONE'); + } else { + return v; + } +} + +int get PROT_READ { + final v = get_PROT_READ(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('PROT_READ'); + } else { + return v; + } +} + +int get PROT_WRITE { + final v = get_PROT_WRITE(); + if (v == libc_shim_UNDEFINED) { + throw UnsupportedError('PROT_WRITE'); + } else { + return v; + } +} + int get AT_SYMLINK_NOFOLLOW { final v = get_AT_SYMLINK_NOFOLLOW(); if (v == libc_shim_UNDEFINED) { diff --git a/pkgs/unix_api/lib/src/function_bindings.g.dart b/pkgs/unix_api/lib/src/function_bindings.g.dart index dc28162f..51a43c22 100644 --- a/pkgs/unix_api/lib/src/function_bindings.g.dart +++ b/pkgs/unix_api/lib/src/function_bindings.g.dart @@ -16,6 +16,9 @@ external int libc_shim_valid_mode_t(int arg0); @ffi.Native() external int libc_shim_valid_size_t(int arg0); +@ffi.Native() +external int libc_shim_valid_off_t(int arg0); + @ffi.Native< ffi.Int Function( ffi.Pointer, @@ -83,6 +86,84 @@ external ffi.Pointer libc_shim_strerror( ffi.Pointer arg1, ); +@ffi.Native< + ffi.Int Function( + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) +>() +external int libc_shim_mlock( + ffi.Pointer arg0, + int arg1, + ffi.Pointer arg2, +); + +@ffi.Native)>() +external int libc_shim_mlockall(int arg0, ffi.Pointer arg1); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.UnsignedLong, + ffi.Int, + ffi.Int, + ffi.Int, + ffi.Long, + ffi.Pointer, + ) +>() +external ffi.Pointer libc_shim_mmap( + ffi.Pointer arg0, + int arg1, + int arg2, + int arg3, + int arg4, + int arg5, + ffi.Pointer arg6, +); + +@ffi.Native< + ffi.Int Function( + ffi.Pointer, + ffi.UnsignedLong, + ffi.Int, + ffi.Pointer, + ) +>() +external int libc_shim_mprotect( + ffi.Pointer arg0, + int arg1, + int arg2, + ffi.Pointer arg3, +); + +@ffi.Native< + ffi.Int Function( + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) +>() +external int libc_shim_munlock( + ffi.Pointer arg0, + int arg1, + ffi.Pointer arg2, +); + +@ffi.Native< + ffi.Int Function( + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) +>() +external int libc_shim_munmap( + ffi.Pointer arg0, + int arg1, + ffi.Pointer arg2, +); + @ffi.Native< ffi.Int Function(ffi.Pointer, ffi.Long, ffi.Pointer) >() diff --git a/pkgs/unix_api/lib/src/functions.g.dart b/pkgs/unix_api/lib/src/functions.g.dart index 4f6384cf..cf0edeb4 100644 --- a/pkgs/unix_api/lib/src/functions.g.dart +++ b/pkgs/unix_api/lib/src/functions.g.dart @@ -41,6 +41,47 @@ ffi.Pointer mkdtemp(ffi.Pointer arg0) => /// See the [POSIX specification for `strerror`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/strerror.html). ffi.Pointer strerror(int arg0) => libc_shim_strerror(arg0, errnoPtr); +/// Locks a range of process address space. +/// +/// See the [POSIX specification for `mlock`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mlock.html). +int mlock(ffi.Pointer arg0, int arg1) => + libc_shim_mlock(arg0, arg1, errnoPtr); + +/// Locks the processes address space. +/// +/// See the [POSIX specification for `mlockall`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mlockall.html). +int mlockall(int arg0) => libc_shim_mlockall(arg0, errnoPtr); + +/// Maps pages of memory. +/// +/// See the [POSIX specification for `mmap`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html). +ffi.Pointer mmap( + ffi.Pointer arg0, + int arg1, + int arg2, + int arg3, + int arg4, + int arg5, +) => libc_shim_mmap(arg0, arg1, arg2, arg3, arg4, arg5, errnoPtr); + +/// Sets the protection of mapped memory. +/// +/// See the [POSIX specification for `mprotect`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html). +int mprotect(ffi.Pointer arg0, int arg1, int arg2) => + libc_shim_mprotect(arg0, arg1, arg2, errnoPtr); + +/// Unlocks a range of process address space." +/// +/// See the [POSIX specification for `munlock`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/munlock.html). +int munlock(ffi.Pointer arg0, int arg1) => + libc_shim_munlock(arg0, arg1, errnoPtr); + +/// Unmaps pages of memory. +/// +/// See the [POSIX specification for `munmap`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/munmap.html). +int munmap(ffi.Pointer arg0, int arg1) => + libc_shim_munmap(arg0, arg1, errnoPtr); + /// Changes the mode of a file. /// /// See the [POSIX specification for `chmod`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/chmod.html). diff --git a/pkgs/unix_api/lib/src/handwritten_constant_bindings.g.dart b/pkgs/unix_api/lib/src/handwritten_constant_bindings.g.dart new file mode 100644 index 00000000..fd4ef44c --- /dev/null +++ b/pkgs/unix_api/lib/src/handwritten_constant_bindings.g.dart @@ -0,0 +1,14 @@ +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +// ignore_for_file: type=lint +@ffi.DefaultAsset('package:unix_api/libc_shim') +library; + +import 'dart:ffi' as ffi; + +/// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +/// for details. All rights reserved. Use of this source code is governed by a +/// BSD-style license that can be found in the LICENSE file. +@ffi.Native Function()>() +external ffi.Pointer libc_shim_get_MAP_FAILED(); diff --git a/pkgs/unix_api/lib/src/handwritten_constants.dart b/pkgs/unix_api/lib/src/handwritten_constants.dart new file mode 100644 index 00000000..e3a7366e --- /dev/null +++ b/pkgs/unix_api/lib/src/handwritten_constants.dart @@ -0,0 +1,7 @@ +import 'dart:ffi' as ffi; + +import 'package:unix_api/src/handwritten_constant_bindings.g.dart'; + +ffi.Pointer get MAP_FAILED { + return libc_shim_get_MAP_FAILED(); +} diff --git a/pkgs/unix_api/lib/unix_api.dart b/pkgs/unix_api/lib/unix_api.dart index b5578808..a68c8c98 100644 --- a/pkgs/unix_api/lib/unix_api.dart +++ b/pkgs/unix_api/lib/unix_api.dart @@ -9,6 +9,7 @@ import 'src/errno.dart'; export 'src/bespoke.dart'; export 'src/constants.g.dart'; export 'src/functions.g.dart'; +export 'src/handwritten_constants.dart'; /// The code that indicates the reason for a failed function call. /// diff --git a/pkgs/unix_api/src/constants.g.c b/pkgs/unix_api/src/constants.g.c index 1930e276..fa45bb1c 100644 --- a/pkgs/unix_api/src/constants.g.c +++ b/pkgs/unix_api/src/constants.g.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include int64_t libc_shim_get_DT_BLK(void) { @@ -75,6 +76,13 @@ int64_t libc_shim_get_EACCES(void) { #endif return libc_shim_UNDEFINED; } +int64_t libc_shim_get_EBADF(void) { +#ifdef EBADF + assert(EBADF != libc_shim_UNDEFINED); + return EBADF; +#endif + return libc_shim_UNDEFINED; +} int64_t libc_shim_get_EDOM(void) { #ifdef EDOM assert(EDOM != libc_shim_UNDEFINED); @@ -96,6 +104,13 @@ int64_t libc_shim_get_EINTR(void) { #endif return libc_shim_UNDEFINED; } +int64_t libc_shim_get_EINVAL(void) { +#ifdef EINVAL + assert(EINVAL != libc_shim_UNDEFINED); + return EINVAL; +#endif + return libc_shim_UNDEFINED; +} int64_t libc_shim_get_EMFILE(void) { #ifdef EMFILE assert(EMFILE != libc_shim_UNDEFINED); @@ -222,6 +237,153 @@ int64_t libc_shim_get_L_ctermid(void) { #endif return libc_shim_UNDEFINED; } +int64_t libc_shim_get_MAP_ANONYMOUS(void) { +#ifdef MAP_ANONYMOUS + assert(MAP_ANONYMOUS != libc_shim_UNDEFINED); + return MAP_ANONYMOUS; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_MAP_FIXED(void) { +#ifdef MAP_FIXED + assert(MAP_FIXED != libc_shim_UNDEFINED); + return MAP_FIXED; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_MAP_PRIVATE(void) { +#ifdef MAP_PRIVATE + assert(MAP_PRIVATE != libc_shim_UNDEFINED); + return MAP_PRIVATE; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_MAP_SHARED(void) { +#ifdef MAP_SHARED + assert(MAP_SHARED != libc_shim_UNDEFINED); + return MAP_SHARED; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_MCL_CURRENT(void) { +#ifdef MCL_CURRENT + assert(MCL_CURRENT != libc_shim_UNDEFINED); + return MCL_CURRENT; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_MCL_FUTURE(void) { +#ifdef MCL_FUTURE + assert(MCL_FUTURE != libc_shim_UNDEFINED); + return MCL_FUTURE; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_MS_ASYNC(void) { +#ifdef MS_ASYNC + assert(MS_ASYNC != libc_shim_UNDEFINED); + return MS_ASYNC; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_MS_INVALIDATE(void) { +#ifdef MS_INVALIDATE + assert(MS_INVALIDATE != libc_shim_UNDEFINED); + return MS_INVALIDATE; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_MS_SYNC(void) { +#ifdef MS_SYNC + assert(MS_SYNC != libc_shim_UNDEFINED); + return MS_SYNC; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_POSIX_MADV_DONTNEED(void) { +#ifdef POSIX_MADV_DONTNEED + assert(POSIX_MADV_DONTNEED != libc_shim_UNDEFINED); + return POSIX_MADV_DONTNEED; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_POSIX_MADV_NORMAL(void) { +#ifdef POSIX_MADV_NORMAL + assert(POSIX_MADV_NORMAL != libc_shim_UNDEFINED); + return POSIX_MADV_NORMAL; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_POSIX_MADV_RANDOM(void) { +#ifdef POSIX_MADV_RANDOM + assert(POSIX_MADV_RANDOM != libc_shim_UNDEFINED); + return POSIX_MADV_RANDOM; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_POSIX_MADV_SEQUENTIAL(void) { +#ifdef POSIX_MADV_SEQUENTIAL + assert(POSIX_MADV_SEQUENTIAL != libc_shim_UNDEFINED); + return POSIX_MADV_SEQUENTIAL; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_POSIX_MADV_WILLNEED(void) { +#ifdef POSIX_MADV_WILLNEED + assert(POSIX_MADV_WILLNEED != libc_shim_UNDEFINED); + return POSIX_MADV_WILLNEED; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_POSIX_TYPED_MEM_ALLOCATE(void) { +#ifdef POSIX_TYPED_MEM_ALLOCATE + assert(POSIX_TYPED_MEM_ALLOCATE != libc_shim_UNDEFINED); + return POSIX_TYPED_MEM_ALLOCATE; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_POSIX_TYPED_MEM_ALLOCATE_CONTIG(void) { +#ifdef POSIX_TYPED_MEM_ALLOCATE_CONTIG + assert(POSIX_TYPED_MEM_ALLOCATE_CONTIG != libc_shim_UNDEFINED); + return POSIX_TYPED_MEM_ALLOCATE_CONTIG; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_POSIX_TYPED_MEM_MAP_ALLOCATABLE(void) { +#ifdef POSIX_TYPED_MEM_MAP_ALLOCATABLE + assert(POSIX_TYPED_MEM_MAP_ALLOCATABLE != libc_shim_UNDEFINED); + return POSIX_TYPED_MEM_MAP_ALLOCATABLE; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_PROT_EXEC(void) { +#ifdef PROT_EXEC + assert(PROT_EXEC != libc_shim_UNDEFINED); + return PROT_EXEC; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_PROT_NONE(void) { +#ifdef PROT_NONE + assert(PROT_NONE != libc_shim_UNDEFINED); + return PROT_NONE; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_PROT_READ(void) { +#ifdef PROT_READ + assert(PROT_READ != libc_shim_UNDEFINED); + return PROT_READ; +#endif + return libc_shim_UNDEFINED; +} +int64_t libc_shim_get_PROT_WRITE(void) { +#ifdef PROT_WRITE + assert(PROT_WRITE != libc_shim_UNDEFINED); + return PROT_WRITE; +#endif + return libc_shim_UNDEFINED; +} int64_t libc_shim_get_AT_SYMLINK_NOFOLLOW(void) { #ifdef AT_SYMLINK_NOFOLLOW assert(AT_SYMLINK_NOFOLLOW != libc_shim_UNDEFINED); diff --git a/pkgs/unix_api/src/constants.g.h b/pkgs/unix_api/src/constants.g.h index c90aabcb..f1889af4 100644 --- a/pkgs/unix_api/src/constants.g.h +++ b/pkgs/unix_api/src/constants.g.h @@ -28,12 +28,16 @@ int64_t libc_shim_get_DT_UNKNOWN(void); __attribute__((visibility("default"))) __attribute__((used)) int64_t libc_shim_get_EACCES(void); __attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_EBADF(void); +__attribute__((visibility("default"))) __attribute__((used)) int64_t libc_shim_get_EDOM(void); __attribute__((visibility("default"))) __attribute__((used)) int64_t libc_shim_get_EEXIST(void); __attribute__((visibility("default"))) __attribute__((used)) int64_t libc_shim_get_EINTR(void); __attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_EINVAL(void); +__attribute__((visibility("default"))) __attribute__((used)) int64_t libc_shim_get_EMFILE(void); __attribute__((visibility("default"))) __attribute__((used)) int64_t libc_shim_get_ENOENT(void); @@ -70,6 +74,48 @@ int64_t libc_shim_get_PATH_MAX(void); __attribute__((visibility("default"))) __attribute__((used)) int64_t libc_shim_get_L_ctermid(void); __attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_MAP_ANONYMOUS(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_MAP_FIXED(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_MAP_PRIVATE(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_MAP_SHARED(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_MCL_CURRENT(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_MCL_FUTURE(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_MS_ASYNC(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_MS_INVALIDATE(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_MS_SYNC(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_POSIX_MADV_DONTNEED(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_POSIX_MADV_NORMAL(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_POSIX_MADV_RANDOM(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_POSIX_MADV_SEQUENTIAL(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_POSIX_MADV_WILLNEED(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_POSIX_TYPED_MEM_ALLOCATE(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_POSIX_TYPED_MEM_ALLOCATE_CONTIG(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_POSIX_TYPED_MEM_MAP_ALLOCATABLE(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_PROT_EXEC(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_PROT_NONE(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_PROT_READ(void); +__attribute__((visibility("default"))) __attribute__((used)) +int64_t libc_shim_get_PROT_WRITE(void); +__attribute__((visibility("default"))) __attribute__((used)) int64_t libc_shim_get_AT_SYMLINK_NOFOLLOW(void); __attribute__((visibility("default"))) __attribute__((used)) int64_t libc_shim_get_AT_RESOLVE_BENEATH(void); diff --git a/pkgs/unix_api/src/functions.g.c b/pkgs/unix_api/src/functions.g.c index 75ce032b..2d880253 100644 --- a/pkgs/unix_api/src/functions.g.c +++ b/pkgs/unix_api/src/functions.g.c @@ -10,12 +10,15 @@ #include #include #include +#include #include #include int libc_shim_valid_mode_t(long a) { return (long)((mode_t) a) == a; } int libc_shim_valid_size_t(unsigned long a) { return (unsigned long)((size_t) a) == a; } +int libc_shim_valid_off_t(long a) { return (long)((off_t) a) == a; } + int libc_shim_open(const char * arg0, int arg1, long arg2, int * err) { int r; if (!libc_shim_valid_mode_t(arg2)) { @@ -78,6 +81,80 @@ char * libc_shim_strerror(int arg0, int * err) { } +int libc_shim_mlock(const void * arg0, unsigned long arg1, int * err) { + int r; + if (!libc_shim_valid_size_t(arg1)) { + *err = EDOM; + return -1; + } + errno = *err; + r = mlock(arg0, (size_t) arg1); + *err = errno; + return r; +} + + +int libc_shim_mlockall(int arg0, int * err) { + int r; + errno = *err; + r = mlockall(arg0); + *err = errno; + return r; +} + + +void * libc_shim_mmap(void * arg0, unsigned long arg1, int arg2, int arg3, int arg4, long arg5, int * err) { + void * r; + if (!libc_shim_valid_size_t(arg1) && !libc_shim_valid_off_t(arg5)) { + *err = EDOM; + return MAP_FAILED; + } + errno = *err; + r = mmap(arg0, (size_t) arg1, arg2, arg3, arg4, (off_t) arg5); + *err = errno; + return r; +} + + +int libc_shim_mprotect(void * arg0, unsigned long arg1, int arg2, int * err) { + int r; + if (!libc_shim_valid_size_t(arg1)) { + *err = EDOM; + return -1; + } + errno = *err; + r = mprotect(arg0, (size_t) arg1, arg2); + *err = errno; + return r; +} + + +int libc_shim_munlock(const void * arg0, unsigned long arg1, int * err) { + int r; + if (!libc_shim_valid_size_t(arg1)) { + *err = EDOM; + return -1; + } + errno = *err; + r = munlock(arg0, (size_t) arg1); + *err = errno; + return r; +} + + +int libc_shim_munmap(void * arg0, unsigned long arg1, int * err) { + int r; + if (!libc_shim_valid_size_t(arg1)) { + *err = EDOM; + return -1; + } + errno = *err; + r = munmap(arg0, (size_t) arg1); + *err = errno; + return r; +} + + int libc_shim_chmod(const char * arg0, long arg1, int * err) { int r; if (!libc_shim_valid_mode_t(arg1)) { diff --git a/pkgs/unix_api/src/functions.g.h b/pkgs/unix_api/src/functions.g.h index 4bb8d435..6d3f7b5d 100644 --- a/pkgs/unix_api/src/functions.g.h +++ b/pkgs/unix_api/src/functions.g.h @@ -5,6 +5,8 @@ int libc_shim_valid_mode_t(long); int libc_shim_valid_size_t(unsigned long); +int libc_shim_valid_off_t(long); + __attribute__((visibility("default"))) __attribute__((used)) int libc_shim_open(const char *, int, long, int *); @@ -29,6 +31,30 @@ __attribute__((visibility("default"))) __attribute__((used)) char * libc_shim_strerror(int, int *); +__attribute__((visibility("default"))) __attribute__((used)) +int libc_shim_mlock(const void *, unsigned long, int *); + + +__attribute__((visibility("default"))) __attribute__((used)) +int libc_shim_mlockall(int, int *); + + +__attribute__((visibility("default"))) __attribute__((used)) +void * libc_shim_mmap(void *, unsigned long, int, int, int, long, int *); + + +__attribute__((visibility("default"))) __attribute__((used)) +int libc_shim_mprotect(void *, unsigned long, int, int *); + + +__attribute__((visibility("default"))) __attribute__((used)) +int libc_shim_munlock(const void *, unsigned long, int *); + + +__attribute__((visibility("default"))) __attribute__((used)) +int libc_shim_munmap(void *, unsigned long, int *); + + __attribute__((visibility("default"))) __attribute__((used)) int libc_shim_chmod(const char *, long, int *); diff --git a/pkgs/unix_api/src/handwritten_constants.c b/pkgs/unix_api/src/handwritten_constants.c new file mode 100644 index 00000000..57f80ce7 --- /dev/null +++ b/pkgs/unix_api/src/handwritten_constants.c @@ -0,0 +1,11 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include + +#include "handwritten_constants.h" + +void* libc_shim_get_MAP_FAILED(void) { + return MAP_FAILED; +} diff --git a/pkgs/unix_api/src/handwritten_constants.h b/pkgs/unix_api/src/handwritten_constants.h new file mode 100644 index 00000000..dc27b519 --- /dev/null +++ b/pkgs/unix_api/src/handwritten_constants.h @@ -0,0 +1,6 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +__attribute__((visibility("default"))) __attribute__((used)) +void* libc_shim_get_MAP_FAILED(void); diff --git a/pkgs/unix_api/test/mmap_test.dart b/pkgs/unix_api/test/mmap_test.dart new file mode 100644 index 00000000..0f162f2d --- /dev/null +++ b/pkgs/unix_api/test/mmap_test.dart @@ -0,0 +1,106 @@ +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:ffi'; +import 'dart:io'; + +import 'package:ffi/ffi.dart' as ffi; +import 'package:unix_api/unix_api.dart'; +import 'package:test/test.dart'; +import 'package:path/path.dart' as p; + +void main() { + group('mmap', () { + const allocationSize = 1024 * 1024; + late Directory tmp; + late ffi.Arena arena; + + setUp(() { + tmp = Directory.systemTemp.createTempSync('mmap'); + arena = ffi.Arena(); + }); + + tearDown(() { + tmp.deleteSync(recursive: true); + arena.releaseAll(); + }); + + test('mlock/munlock success', () { + final address = mmap( + nullptr, + allocationSize, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, + -1, + 0, + ); + expect(address, isNot(MAP_FAILED)); + addTearDown(() => munmap(address, allocationSize)); + + var r = mlock(address, allocationSize); + + expect(r, 0); + + r = munlock(address, allocationSize); + expect(r, 0); + }); + + test('mmap/munmap success', () { + final path = p.join(tmp.path, 'test1'); + + File(path).writeAsBytesSync([0, 1, 2, 3]); + + final fd = open( + path.toNativeUtf8(allocator: arena).cast(), + O_RDONLY | O_CLOEXEC, + 0, + ); + expect(fd, isNot(0)); + addTearDown(() => close(fd)); + + final address = mmap( + nullptr, + allocationSize, + PROT_READ, + MAP_SHARED, + fd, + 0, + ); + expect(address, isNot(MAP_FAILED)); + + expect(address.cast().value, 0); + expect((address.cast() + 1).value, 1); + expect((address.cast() + 2).value, 2); + expect((address.cast() + 3).value, 3); + + int r = munmap(address, allocationSize); + expect(r, 0); + }); + + test('mmap failure', () { + final address = mmap(nullptr, 0, PROT_READ, MAP_SHARED, -1, 0); + + expect(address, MAP_FAILED); + expect(errno, anyOf([EBADF, EINVAL])); + }); + + test('mprotect success', () { + final address = mmap( + nullptr, + allocationSize, + PROT_READ, + MAP_SHARED | MAP_ANONYMOUS, + -1, + 0, + ); + expect(address, isNot(MAP_FAILED)); + addTearDown(() => munmap(address, allocationSize)); + + int r = mprotect(address, allocationSize, PROT_WRITE); + + expect(r, 0); + address.cast().value = 3; + }); + }); +} diff --git a/pkgs/unix_api/tool/cfunction.dart b/pkgs/unix_api/tool/cfunction.dart index 13f638e2..89ab23fa 100644 --- a/pkgs/unix_api/tool/cfunction.dart +++ b/pkgs/unix_api/tool/cfunction.dart @@ -22,6 +22,9 @@ final _posixToFfiTypes = { 'ssize_t': 'long', // size_t shall be an unsigned integer type. 'size_t': 'unsigned long', + // blkcnt_t and off_t shall be signed integer types. + 'blkcnt_t': 'long', + 'off_t': 'long', }; final _ffiToDartTypes = { diff --git a/pkgs/unix_api/tool/generate.dart b/pkgs/unix_api/tool/generate.dart index 9b79b3b5..866735ca 100755 --- a/pkgs/unix_api/tool/generate.dart +++ b/pkgs/unix_api/tool/generate.dart @@ -40,9 +40,17 @@ void main() async { '--config', 'functions-ffigen.yaml', ]); + await ffigen.main([ + '--no-format', + '-v', + 'severe', + '--config', + 'handwritten-constants-ffigen.yaml', + ]); _formatFile('lib/src/constant_bindings.g.dart'); _formatFile('lib/src/constants.g.dart'); _formatFile('lib/src/function_bindings.g.dart'); _formatFile('lib/src/functions.g.dart'); + _formatFile('lib/src/handwritten_constant_bindings.g.dart'); _formatFile('lib/src/libc_bindings.g.dart'); }