@@ -242,6 +242,80 @@ pub fn openat<P: ?Sized + NixPath>(
242
242
Errno :: result( fd)
243
243
}
244
244
245
+ #[ cfg( target_os = "linux" ) ]
246
+ libc_bitflags! {
247
+ /// Path resolution flags.
248
+ pub struct ResolveFlag : libc:: c_ulonglong {
249
+ /// Do not permit the path resolution to succeed if any component of
250
+ /// the resolution is not a descendant of the directory indicated by
251
+ /// dirfd. This causes absolute symbolic links (and absolute values of
252
+ /// pathname) to be rejected.
253
+ RESOLVE_BENEATH ;
254
+
255
+ /// Treat the directory referred to by dirfd as the root directory
256
+ /// while resolving pathname.
257
+ RESOLVE_IN_ROOT ;
258
+
259
+ /// Disallow all magic-link resolution during path resolution. Magic
260
+ /// links are symbolic link-like objects that are most notably found
261
+ /// in proc(5); examples include `/proc/[pid]/exe` and `/proc/[pid]/fd/*`.
262
+ ///
263
+ /// See symlink(7) for more details.
264
+ RESOLVE_NO_MAGICLINKS ;
265
+
266
+ /// Disallow resolution of symbolic links during path resolution. This
267
+ /// option implies RESOLVE_NO_MAGICLINKS.
268
+ RESOLVE_NO_SYMLINKS ;
269
+
270
+ /// Disallow traversal of mount points during path resolution (including
271
+ /// all bind mounts).
272
+ RESOLVE_NO_XDEV ;
273
+ }
274
+ }
275
+
276
+ /// open or create a file for reading, writing or executing.
277
+ ///
278
+ /// `openat2` is an extension of the [`openat`] function that allows the caller
279
+ /// to control how path resolution happens.
280
+ ///
281
+ /// See [the man page](man) for more information.
282
+ ///
283
+ /// [man]: https://man7.org/linux/man-pages/man2/openat2.2.html
284
+ #[ cfg( target_os = "linux" ) ]
285
+ pub fn openat2<P : ?Sized + NixPath >(
286
+ dirfd: RawFd ,
287
+ path: & P ,
288
+ oflag: OFlag ,
289
+ mode: Mode ,
290
+ resolve: ResolveFlag ,
291
+ ) -> Result <RawFd > {
292
+ let mut how = open_how( oflag, mode, resolve) ;
293
+ let fd = path. with_nix_path( |cstr| unsafe {
294
+ libc:: syscall(
295
+ libc:: SYS_openat2 ,
296
+ dirfd,
297
+ cstr. as_ptr( ) ,
298
+ & mut how as * mut _,
299
+ std:: mem:: size_of:: <libc:: open_how>( ) ,
300
+ )
301
+ } ) ?;
302
+ Errno :: result( fd as i32 )
303
+ }
304
+
305
+ #[ cfg( target_os = "linux" ) ]
306
+ fn open_how( oflag: OFlag , mode: Mode , resolve: ResolveFlag ) -> libc:: open_how {
307
+ use std:: ptr:: addr_of_mut;
308
+
309
+ let mut how = std:: mem:: MaybeUninit :: <libc:: open_how>:: uninit( ) ;
310
+ let ptr = how. as_mut_ptr( ) ;
311
+ unsafe {
312
+ addr_of_mut!( ( * ptr) . flags) . write( oflag. bits( ) as libc:: c_ulonglong) ;
313
+ addr_of_mut!( ( * ptr) . mode) . write( mode. bits( ) as libc:: c_ulonglong) ;
314
+ addr_of_mut!( ( * ptr) . resolve) . write( resolve. bits( ) ) ;
315
+ how. assume_init( )
316
+ }
317
+ }
318
+
245
319
/// Change the name of a file.
246
320
///
247
321
/// The `renameat` function is equivalent to `rename` except in the case where either `old_path`
0 commit comments