@@ -242,6 +242,119 @@ pub fn openat<P: ?Sized + NixPath>(
242242 Errno :: result( fd)
243243}
244244
245+ cfg_if:: cfg_if! {
246+ if #[ cfg( target_os = "linux" ) ] {
247+ libc_bitflags! {
248+ /// Path resolution flags.
249+ ///
250+ /// See [path resolution(7)](https://man7.org/linux/man-pages/man7/path_resolution.7.html)
251+ /// for details of the resolution process.
252+ pub struct ResolveFlag : libc:: c_ulonglong {
253+ /// Do not permit the path resolution to succeed if any component of
254+ /// the resolution is not a descendant of the directory indicated by
255+ /// dirfd. This causes absolute symbolic links (and absolute values of
256+ /// pathname) to be rejected.
257+ RESOLVE_BENEATH ;
258+
259+ /// Treat the directory referred to by dirfd as the root directory
260+ /// while resolving pathname.
261+ RESOLVE_IN_ROOT ;
262+
263+ /// Disallow all magic-link resolution during path resolution. Magic
264+ /// links are symbolic link-like objects that are most notably found
265+ /// in proc(5); examples include `/proc/[pid]/exe` and `/proc/[pid]/fd/*`.
266+ ///
267+ /// See symlink(7) for more details.
268+ RESOLVE_NO_MAGICLINKS ;
269+
270+ /// Disallow resolution of symbolic links during path resolution. This
271+ /// option implies RESOLVE_NO_MAGICLINKS.
272+ RESOLVE_NO_SYMLINKS ;
273+
274+ /// Disallow traversal of mount points during path resolution (including
275+ /// all bind mounts).
276+ RESOLVE_NO_XDEV ;
277+ }
278+ }
279+
280+ /// Specifies how [openat2] should open a pathname.
281+ ///
282+ /// See <https://man7.org/linux/man-pages/man2/open_how.2type.html>
283+ #[ repr( transparent) ]
284+ #[ derive( Clone , Copy , Debug ) ]
285+ pub struct OpenHow ( libc:: open_how) ;
286+
287+ impl OpenHow {
288+ /// Create a new zero-filled `open_how`.
289+ pub fn new( ) -> Self {
290+ // safety: according to the man page, open_how MUST be zero-initialized
291+ // on init so that unknown fields are also zeroed.
292+ Self ( unsafe {
293+ std:: mem:: MaybeUninit :: zeroed( ) . assume_init( )
294+ } )
295+ }
296+
297+ /// Set the open flags used to open a file, completely overwriting any
298+ /// existing flags.
299+ pub fn flags( mut self , flags: OFlag ) -> Self {
300+ let flags = flags. bits( ) as libc:: c_ulonglong;
301+ self . 0 . flags = flags;
302+ self
303+ }
304+
305+ /// Set the file mode new files will be created with, overwriting any
306+ /// existing flags.
307+ pub fn mode( mut self , mode: Mode ) -> Self {
308+ let mode = mode. bits( ) as libc:: c_ulonglong;
309+ self . 0 . mode = mode;
310+ self
311+ }
312+
313+ /// Set resolve flags, completely overwriting any existing flags.
314+ ///
315+ /// See [ResolveFlag] for more detail.
316+ pub fn resolve( mut self , resolve: ResolveFlag ) -> Self {
317+ let resolve = resolve. bits( ) ;
318+ self . 0 . resolve = resolve;
319+ self
320+ }
321+ }
322+
323+ // safety: default isn't derivable because libc::open_how must be zeroed
324+ impl Default for OpenHow {
325+ fn default ( ) -> Self {
326+ Self :: new( )
327+ }
328+ }
329+
330+ /// Open or create a file for reading, writing or executing.
331+ ///
332+ /// `openat2` is an extension of the [`openat`] function that allows the caller
333+ /// to control how path resolution happens.
334+ ///
335+ /// # See also
336+ ///
337+ /// [openat2](https://man7.org/linux/man-pages/man2/openat2.2.html)
338+ pub fn openat2<P : ?Sized + NixPath >(
339+ dirfd: RawFd ,
340+ path: & P ,
341+ mut how: OpenHow ,
342+ ) -> Result <RawFd > {
343+ let fd = path. with_nix_path( |cstr| unsafe {
344+ libc:: syscall(
345+ libc:: SYS_openat2 ,
346+ dirfd,
347+ cstr. as_ptr( ) ,
348+ & mut how as * mut OpenHow ,
349+ std:: mem:: size_of:: <libc:: open_how>( ) ,
350+ )
351+ } ) ?;
352+
353+ Errno :: result( fd as RawFd )
354+ }
355+ }
356+ }
357+
245358/// Change the name of a file.
246359///
247360/// The `renameat` function is equivalent to `rename` except in the case where either `old_path`
0 commit comments