@@ -242,6 +242,119 @@ pub fn openat<P: ?Sized + NixPath>(
242
242
Errno :: result( fd)
243
243
}
244
244
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
+
245
358
/// Change the name of a file.
246
359
///
247
360
/// The `renameat` function is equivalent to `rename` except in the case where either `old_path`
0 commit comments