1use linux_unsafe::args::AsRawV;
2use linux_unsafe::void;
3
4use crate::result::{self, Result};
5use crate::seek::SeekFrom;
6
7use core::cell::UnsafeCell;
8use core::ffi::CStr;
9use core::mem::MaybeUninit;
10
11use self::ioctl::SubDevice;
12
13pub mod fcntl;
14pub mod ioctl;
15pub mod sockopt;
16
17mod direntry;
18pub use direntry::*;
19
20#[repr(transparent)]
35pub struct File<Device = ()> {
36 pub(crate) fd: linux_unsafe::int,
37 _phantom: core::marker::PhantomData<Device>,
38}
39
40impl File<()> {
41 #[inline(always)]
47 pub fn open(path: &CStr, options: OpenOptions<OpenWithoutMode>) -> Result<Self> {
48 Self::open_raw(path, options.flags, 0)
49 }
50
51 #[inline(always)]
56 pub fn open_with_mode(
57 path: &CStr,
58 options: OpenOptions<OpenWithMode>,
59 mode: linux_unsafe::mode_t,
60 ) -> Result<Self> {
61 Self::open_raw(path, options.flags, mode)
62 }
63
64 #[inline]
69 pub fn open_raw(
70 path: &CStr,
71 flags: linux_unsafe::int,
72 mode: linux_unsafe::mode_t,
73 ) -> Result<Self> {
74 let path_raw = path.as_ptr() as *const linux_unsafe::char;
75 let result = unsafe {
76 linux_unsafe::openat(
77 linux_unsafe::AT_FDCWD,
78 path_raw,
79 flags as linux_unsafe::int,
80 mode as linux_unsafe::mode_t,
81 )
82 };
83 result
84 .map(|fd| unsafe { Self::from_raw_fd(fd as linux_unsafe::int) })
85 .map_err(|e| e.into())
86 }
87
88 #[inline]
93 pub fn create_raw(path: &CStr, mode: linux_unsafe::mode_t) -> Result<Self> {
94 let path_raw = path.as_ptr() as *const linux_unsafe::char;
95 let result = unsafe {
96 linux_unsafe::openat(
97 linux_unsafe::AT_FDCWD,
98 path_raw,
99 linux_unsafe::O_CREAT | linux_unsafe::O_WRONLY | linux_unsafe::O_TRUNC,
100 mode as linux_unsafe::mode_t,
101 )
102 };
103 result
104 .map(|fd| unsafe { Self::from_raw_fd(fd as linux_unsafe::int) })
105 .map_err(|e| e.into())
106 }
107
108 #[inline]
115 pub fn socket<Protocol: super::socket::SocketProtocol>(
116 domain: linux_unsafe::sa_family_t,
117 typ: crate::socket::sock_type,
118 protocol: Protocol,
119 ) -> Result<File<Protocol::Device>> {
120 let result = unsafe { linux_unsafe::socket(domain, typ, protocol.raw_protocol_num()) };
121 result
122 .map(|fd| unsafe { File::from_raw_fd(fd as linux_unsafe::int) })
123 .map_err(|e| e.into())
124 }
125
126 #[inline]
135 pub fn socket_raw<Protocol: super::socket::SocketProtocol>(
136 domain: linux_unsafe::sa_family_t,
137 typ: crate::socket::sock_type,
138 protocol: linux_unsafe::int,
139 ) -> Result<File<crate::socket::SocketDevice>> {
140 let result = unsafe { linux_unsafe::socket(domain, typ, protocol) };
141 result
142 .map(|fd| unsafe { File::from_raw_fd(fd as linux_unsafe::int) })
143 .map_err(|e| e.into())
144 }
145}
146
147impl<Device> File<Device> {
148 #[inline]
159 pub unsafe fn from_raw_fd(fd: linux_unsafe::int) -> Self {
160 File {
161 fd,
162 _phantom: core::marker::PhantomData,
163 }
164 }
165
166 #[inline]
173 pub fn duplicate(&self) -> Result<Self> {
174 let result = unsafe { linux_unsafe::dup(self.fd) };
175 result
176 .map(|fd| unsafe { Self::from_raw_fd(fd) })
177 .map_err(|e| e.into())
178 }
179
180 #[inline]
183 pub fn open_relative(
184 &self,
185 path: &CStr,
186 options: OpenOptions<OpenWithoutMode>,
187 ) -> Result<File<()>> {
188 self.open_relative_raw(path, options.flags, 0)
189 }
190
191 #[inline]
194 pub fn open_relative_with_mode(
195 &self,
196 path: &CStr,
197 options: OpenOptions<OpenWithMode>,
198 mode: linux_unsafe::mode_t,
199 ) -> Result<File<()>> {
200 self.open_relative_raw(path, options.flags, mode)
201 }
202
203 #[inline]
208 pub fn open_relative_raw(
209 &self,
210 path: &CStr,
211 flags: linux_unsafe::int,
212 mode: linux_unsafe::mode_t,
213 ) -> Result<File<()>> {
214 let path_raw = path.as_ptr() as *const linux_unsafe::char;
215 let result = unsafe {
216 linux_unsafe::openat(
217 self.fd,
218 path_raw,
219 flags as linux_unsafe::int,
220 mode as linux_unsafe::mode_t,
221 )
222 };
223 result
224 .map(|fd| unsafe { File::from_raw_fd(fd as linux_unsafe::int) })
225 .map_err(|e| e.into())
226 }
227
228 #[inline(always)]
229 pub fn fd(&self) -> linux_unsafe::int {
230 self.fd
231 }
232
233 #[inline(always)]
236 pub fn into_raw_fd(self) -> linux_unsafe::int {
237 let ret = self.fd;
238 core::mem::forget(self);
239 ret
240 }
241
242 #[inline]
247 pub fn close(mut self) -> Result<()> {
248 unsafe { self.close_mut() }?;
249 core::mem::forget(self);
253 Ok(())
254 }
255
256 #[inline(always)]
266 pub unsafe fn close_mut(&mut self) -> Result<()> {
267 let result = unsafe { linux_unsafe::close(self.fd) };
268 result.map(|_| ()).map_err(|e| e.into())
269 }
270
271 #[inline(always)]
274 pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
275 let buf_ptr = buf.as_mut_ptr() as *mut linux_unsafe::void;
276 let buf_size = buf.len();
277 unsafe { self.read_raw(buf_ptr, buf_size) }.map(|v| v as _)
278 }
279
280 #[inline]
285 pub unsafe fn read_raw(
286 &self,
287 buf: *mut linux_unsafe::void,
288 count: linux_unsafe::size_t,
289 ) -> Result<linux_unsafe::size_t> {
290 let result = unsafe { linux_unsafe::read(self.fd, buf, count) };
291 result.map(|v| v as _).map_err(|e| e.into())
292 }
293
294 #[inline(always)]
304 pub fn getdents<'a>(&self, buf: &'a mut [u8]) -> Result<DirEntries<'a>> {
305 let buf_ptr = buf.as_mut_ptr() as *mut linux_unsafe::void;
306 let buf_size = buf.len();
307 if buf_size > (linux_unsafe::int::MAX as usize) {
308 return Err(result::EINVAL);
309 }
310 let populated_size =
311 unsafe { self.getdents_raw(buf_ptr, buf_size as linux_unsafe::int) }? as usize;
312 Ok(DirEntries::from_getdents64_buffer(&buf[..populated_size]))
313 }
314
315 #[inline(always)]
332 pub fn getdents_all<'file, 'buf, TF, R>(
333 &'file self,
334 buf: &'buf mut [u8],
335 transform: TF,
336 ) -> AllDirEntries<TF, R, Device>
337 where
338 TF: for<'tmp> FnMut(DirEntry<'tmp>) -> R,
339 'buf: 'file,
340 {
341 AllDirEntries::new(self, buf, transform)
342 }
343
344 #[inline]
349 pub unsafe fn getdents_raw(
350 &self,
351 buf: *mut linux_unsafe::void,
352 buf_len: linux_unsafe::int,
353 ) -> Result<linux_unsafe::size_t> {
354 let result = unsafe { linux_unsafe::getdents64(self.fd, buf, buf_len) };
355 result.map(|v| v as _).map_err(|e| e.into())
356 }
357
358 #[inline(always)]
363 pub fn readlink<'a>(&self, buf: &'a mut [u8]) -> Result<&'a [u8]> {
364 let path = c"";
365 let path_raw = path.as_ptr() as *const linux_unsafe::char;
366 let buf_ptr = buf.as_mut_ptr() as *mut linux_unsafe::char;
367 let buf_size = buf.len();
368 if buf_size > (linux_unsafe::int::MAX as usize) {
369 return Err(result::EINVAL);
370 }
371 let result = unsafe { linux_unsafe::readlinkat(self.fd, path_raw, buf_ptr, buf_size) };
372 match result {
373 Ok(populated_size) => Ok(&buf[..populated_size as usize]),
374 Err(e) => Err(e.into()),
375 }
376 }
377
378 #[inline(always)]
381 pub fn readlink_relative<'a>(&self, path: &CStr, buf: &'a mut [u8]) -> Result<&'a [u8]> {
382 let path_raw = path.as_ptr() as *const linux_unsafe::char;
383 let buf_ptr = buf.as_mut_ptr() as *mut linux_unsafe::char;
384 let buf_size = buf.len();
385 if buf_size > (linux_unsafe::int::MAX as usize) {
386 return Err(result::EINVAL);
387 }
388 let result = unsafe { linux_unsafe::readlinkat(self.fd, path_raw, buf_ptr, buf_size) };
389 match result {
390 Ok(populated_size) => Ok(&buf[..populated_size as usize]),
391 Err(e) => Err(e.into()),
392 }
393 }
394
395 #[inline(always)]
398 pub fn exists_relative(&self, path: &CStr) -> Result<bool> {
399 let path_raw = path.as_ptr() as *const linux_unsafe::char;
400 let mut tmp = unsafe { core::mem::zeroed::<linux_unsafe::statx>() };
401 let result = unsafe { linux_unsafe::statx(self.fd, path_raw, 0, 0, &mut tmp as *mut _) };
402 match result {
403 Ok(_) => Ok(true),
404 Err(e) => {
405 if e.0 == linux_unsafe::result::ENOENT {
406 Ok(false)
407 } else {
408 Err(e.into())
409 }
410 }
411 }
412 }
413
414 #[inline]
416 pub fn seek(&self, pos: impl Into<SeekFrom>) -> Result<u64> {
417 let pos = pos.into();
418 let raw_offs = pos.for_raw_offset();
419
420 #[cfg(not(target_pointer_width = "32"))]
421 {
422 let raw_whence = pos.for_raw_whence();
425 let result = unsafe { linux_unsafe::lseek(self.fd, raw_offs, raw_whence) };
426 result.map(|v| v as u64).map_err(|e| e.into())
427 }
428
429 #[cfg(target_pointer_width = "32")]
430 {
431 let raw_offs_high = ((raw_offs as u64) >> 32) as linux_unsafe::ulong;
434 let raw_offs_low = (raw_offs as u64) as linux_unsafe::ulong;
435 let result: UnsafeCell<linux_unsafe::loff_t> = UnsafeCell::new(0);
436 let result_ptr = result.get();
437 let raw_whence = pos.for_raw_uwhence();
438 let result = unsafe {
439 linux_unsafe::_llseek(self.fd, raw_offs_high, raw_offs_low, result_ptr, raw_whence)
440 };
441 match result {
442 Ok(_) => {
443 let result_offs = unsafe { *result_ptr } as u64;
444 Ok(result_offs)
445 }
446 Err(e) => Err(e.into()),
447 }
448 }
449 }
450
451 #[inline]
454 pub fn sync(&self) -> Result<()> {
455 let result = unsafe { linux_unsafe::fsync(self.fd) };
456 result.map(|_| ()).map_err(|e| e.into())
457 }
458
459 #[inline(always)]
462 pub fn write(&self, buf: &[u8]) -> Result<usize> {
463 let buf_ptr = buf.as_ptr() as *const linux_unsafe::void;
464 let buf_size = buf.len();
465 unsafe { self.write_raw(buf_ptr, buf_size) }.map(|v| v as _)
466 }
467
468 #[inline]
473 pub unsafe fn write_raw(
474 &self,
475 buf: *const linux_unsafe::void,
476 count: linux_unsafe::size_t,
477 ) -> Result<linux_unsafe::size_t> {
478 let result = unsafe { linux_unsafe::write(self.fd, buf, count) };
479 result.map(|v| v as _).map_err(|e| e.into())
480 }
481
482 #[inline]
490 pub fn fcntl<'a, Cmd: fcntl::FcntlCmd<'a>>(
491 &'a self,
492 cmd: Cmd,
493 arg: Cmd::ExtArg,
494 ) -> Result<Cmd::Result> {
495 let (raw_cmd, raw_arg) = cmd.prepare_fcntl_args(arg);
496 let raw_result = unsafe { self.fcntl_raw(raw_cmd, raw_arg) };
497 raw_result.map(|r| cmd.prepare_fcntl_result(r))
498 }
499
500 #[inline]
507 pub unsafe fn fcntl_raw(
508 &self,
509 cmd: linux_unsafe::int,
510 arg: impl AsRawV,
511 ) -> Result<linux_unsafe::int> {
512 let result = unsafe { linux_unsafe::fcntl(self.fd, cmd, arg) };
513 result.map(|v| v as _).map_err(|e| e.into())
514 }
515
516 pub unsafe fn to_device<T: ioctl::IoDevice>(
526 self,
527 #[allow(unused_variables)] devty: T,
528 ) -> File<T> {
529 let ret = File {
530 fd: self.fd,
531 _phantom: core::marker::PhantomData,
532 };
533 core::mem::forget(self); ret
535 }
536
537 #[inline]
544 pub unsafe fn ioctl_raw(
545 &self,
546 request: linux_unsafe::ulong,
547 arg: impl AsRawV,
548 ) -> Result<linux_unsafe::int> {
549 let result = unsafe { linux_unsafe::ioctl(self.fd, request, arg) };
550 result.map(|v| v as _).map_err(|e| e.into())
551 }
552
553 #[inline]
555 pub fn bind(&self, addr: impl crate::socket::SockAddr) -> Result<()> {
556 let (raw_ptr, raw_len) = unsafe { addr.sockaddr_raw_const() };
557 unsafe { self.bind_raw(raw_ptr, raw_len) }
558 }
559
560 #[inline]
562 pub unsafe fn bind_raw(
563 &self,
564 addr: *const linux_unsafe::sockaddr,
565 addrlen: linux_unsafe::socklen_t,
566 ) -> Result<()> {
567 let result = unsafe { linux_unsafe::bind(self.fd, addr, addrlen) };
568 result.map(|_| ()).map_err(|e| e.into())
569 }
570
571 #[inline]
573 pub fn connect(&self, addr: impl crate::socket::SockAddr) -> Result<()> {
574 let (raw_ptr, raw_len) = unsafe { addr.sockaddr_raw_const() };
575 unsafe { self.connect_raw(raw_ptr, raw_len) }
576 }
577
578 #[inline]
580 pub unsafe fn connect_raw(
581 &self,
582 addr: *const linux_unsafe::sockaddr,
583 addrlen: linux_unsafe::socklen_t,
584 ) -> Result<()> {
585 let result = unsafe { linux_unsafe::connect(self.fd, addr, addrlen) };
586 result.map(|_| ()).map_err(|e| e.into())
587 }
588
589 #[inline]
591 pub fn listen(&self, backlog: linux_unsafe::int) -> Result<()> {
592 let result = unsafe { linux_unsafe::listen(self.fd, backlog) };
593 result.map(|_| ()).map_err(|e| e.into())
594 }
595
596 #[inline(always)]
602 pub fn getsockopt<'a, O: sockopt::GetSockOpt<'a>>(&self, opt: O) -> Result<O::Result> {
603 let (level, optname) = opt.prepare_getsockopt_args();
604 let mut buf: MaybeUninit<O::OptVal> = MaybeUninit::zeroed();
605 let optlen = core::mem::size_of::<O::OptVal>() as linux_unsafe::socklen_t;
606 let mut optlen_out = UnsafeCell::new(optlen);
607 let result = unsafe {
608 self.getsockopt_raw(
609 level,
610 optname,
611 buf.as_mut_ptr() as *mut linux_unsafe::void,
612 optlen_out.get(),
613 )
614 }?;
615 if *optlen_out.get_mut() != optlen {
616 return Err(crate::result::Error::new(22)); }
620 let buf = unsafe { buf.assume_init() };
621 Ok(opt.prepare_getsockopt_result(result, buf))
622 }
623
624 #[inline]
627 pub unsafe fn getsockopt_raw(
628 &self,
629 level: linux_unsafe::int,
630 optname: linux_unsafe::int,
631 optval: *mut linux_unsafe::void,
632 optlen: *mut linux_unsafe::socklen_t,
633 ) -> Result<linux_unsafe::int> {
634 let result = unsafe { linux_unsafe::getsockopt(self.fd, level, optname, optval, optlen) };
635 result.map_err(|e| e.into())
636 }
637
638 #[inline(always)]
644 pub fn setsockopt<'a, O: sockopt::SetSockOpt<'a>>(
645 &self,
646 opt: O,
647 arg: O::ExtArg,
648 ) -> Result<O::Result> {
649 let (level, optname, optval, optlen) = opt.prepare_setsockopt_args(&arg);
650 let result = unsafe {
651 self.setsockopt_raw(level, optname, optval as *mut linux_unsafe::void, optlen)
652 }?;
653 Ok(opt.prepare_setsockopt_result(result))
654 }
655
656 #[inline]
659 pub unsafe fn setsockopt_raw(
660 &self,
661 level: linux_unsafe::int,
662 optname: linux_unsafe::int,
663 optval: *const linux_unsafe::void,
664 optlen: linux_unsafe::socklen_t,
665 ) -> Result<linux_unsafe::int> {
666 let result = unsafe { linux_unsafe::setsockopt(self.fd, level, optname, optval, optlen) };
667 result.map_err(|e| e.into())
668 }
669
670 #[inline(always)]
677 pub unsafe fn mmap_raw(
678 &self,
679 offset: linux_unsafe::off_t,
680 length: linux_unsafe::size_t,
681 addr: *mut void,
682 prot: linux_unsafe::int,
683 flags: linux_unsafe::int,
684 ) -> Result<*mut void> {
685 let result = unsafe { linux_unsafe::mmap(addr, length, prot, flags, self.fd, offset) };
686 result.map_err(|e| e.into())
687 }
688}
689
690impl<Device: ioctl::IoDevice> File<Device> {
694 #[inline]
705 pub fn ioctl<'a, ReqDevice: ioctl::IoDevice, Req: ioctl::IoctlReq<'a, ReqDevice>>(
706 &'a self,
707 request: Req,
708 arg: Req::ExtArg,
709 ) -> Result<Req::Result>
710 where
711 Device: SubDevice<ReqDevice>,
712 {
713 let mut temp_mem: MaybeUninit<Req::TempMem> = MaybeUninit::zeroed();
718 let (raw_req, raw_arg) = request.prepare_ioctl_args(&arg, &mut temp_mem);
719 let raw_result = unsafe { self.ioctl_raw(raw_req, raw_arg) };
720 raw_result.map(|r| request.prepare_ioctl_result(r, &arg, &temp_mem))
721 }
722}
723
724impl<Device> Drop for File<Device> {
725 #[allow(unused_must_use)] fn drop(&mut self) {
732 unsafe { self.close_mut() };
733 }
734}
735
736impl<Device> core::fmt::Debug for File<Device> {
737 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
738 f.debug_struct("File").field("fd", &self.fd).finish()
739 }
740}
741
742impl<T> core::fmt::Write for File<T> {
745 fn write_str(&mut self, s: &str) -> core::fmt::Result {
746 let mut bytes = s.as_bytes();
747 while !bytes.is_empty() {
748 let n = match self.write(bytes) {
749 Ok(n) => n,
750 Err(e) => return Err(e.into()),
751 };
752 bytes = &bytes[n..];
753 }
754 Ok(())
755 }
756}
757
758#[cfg(feature = "std")]
759extern crate std;
760
761#[cfg(feature = "std")]
762impl<Device> std::io::Read for File<Device> {
763 #[inline(always)]
764 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
765 Self::read(self, buf).map_err(|e| e.into())
766 }
767}
768
769#[cfg(feature = "std")]
770impl<Device> std::io::Write for File<Device> {
771 #[inline(always)]
772 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
773 Self::write(self, buf).map_err(|e| e.into())
774 }
775
776 #[inline(always)]
777 fn flush(&mut self) -> std::io::Result<()> {
778 Self::sync(self).map_err(|e| e.into())
779 }
780}
781
782#[cfg(feature = "std")]
783impl<Device> std::io::Seek for File<Device> {
784 #[inline(always)]
785 fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
786 Self::seek(self, pos).map_err(|e| e.into())
787 }
788}
789
790#[cfg(feature = "std")]
791impl From<std::os::fd::OwnedFd> for File<()> {
792 fn from(value: std::os::fd::OwnedFd) -> Self {
793 use std::os::fd::IntoRawFd;
794
795 Self {
796 fd: value.into_raw_fd().into(),
797 _phantom: core::marker::PhantomData,
798 }
799 }
800}
801
802#[cfg(feature = "std")]
803impl<Device> std::os::fd::AsFd for File<Device> {
804 fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
805 unsafe { std::os::fd::BorrowedFd::borrow_raw(self.fd) }
806 }
807}
808
809pub const OPEN_READ_ONLY: OpenOptions<OpenWithoutMode> =
813 OpenOptions::<OpenWithoutMode>::read_only();
814
815pub const OPEN_WRITE_ONLY: OpenOptions<OpenWithoutMode> =
819 OpenOptions::<OpenWithoutMode>::write_only();
820
821pub const OPEN_READ_WRITE: OpenOptions<OpenWithoutMode> =
825 OpenOptions::<OpenWithoutMode>::read_write();
826
827#[derive(Clone, Copy, PartialEq, Eq)]
834#[repr(transparent)]
835pub struct OpenOptions<NeedMode: OpenMode> {
836 flags: linux_unsafe::int,
837 _phantom: core::marker::PhantomData<NeedMode>,
838}
839
840impl OpenOptions<OpenWithoutMode> {
841 #[inline(always)]
842 pub const fn read_only() -> Self {
843 Self {
844 flags: linux_unsafe::O_RDONLY, _phantom: core::marker::PhantomData,
846 }
847 }
848
849 #[inline(always)]
850 pub const fn write_only() -> Self {
851 Self {
852 flags: linux_unsafe::O_WRONLY,
853 _phantom: core::marker::PhantomData,
854 }
855 }
856
857 #[inline(always)]
858 pub const fn read_write() -> Self {
859 Self {
860 flags: linux_unsafe::O_RDWR,
861 _phantom: core::marker::PhantomData,
862 }
863 }
864}
865
866impl<NeedMode: OpenMode> OpenOptions<NeedMode> {
867 #[inline(always)]
868 const fn bit_or(self, new: linux_unsafe::int) -> Self {
869 Self {
870 flags: self.flags | new,
871 _phantom: core::marker::PhantomData,
872 }
873 }
874
875 #[inline(always)]
876 pub const fn append(self) -> Self {
877 self.bit_or(linux_unsafe::O_APPEND)
878 }
879
880 #[inline(always)]
881 pub const fn close_on_exec(self) -> Self {
882 self.bit_or(linux_unsafe::O_CLOEXEC)
883 }
884
885 #[inline(always)]
886 pub const fn create(self) -> OpenOptions<OpenWithMode> {
887 OpenOptions {
888 flags: self.bit_or(linux_unsafe::O_CREAT).flags,
889 _phantom: core::marker::PhantomData,
890 }
891 }
892
893 #[inline(always)]
894 pub const fn direct(self) -> Self {
895 self.bit_or(linux_unsafe::O_DIRECT)
896 }
897
898 #[inline(always)]
899 pub const fn directory(self) -> Self {
900 self.bit_or(linux_unsafe::O_DIRECTORY)
901 }
902
903 #[inline(always)]
904 pub const fn excl(self) -> Self {
905 self.bit_or(linux_unsafe::O_EXCL)
906 }
907
908 #[inline(always)]
909 pub const fn no_atime(self) -> Self {
910 self.bit_or(linux_unsafe::O_NOATIME)
911 }
912
913 #[inline(always)]
914 pub const fn no_controlling_tty(self) -> Self {
915 self.bit_or(linux_unsafe::O_NOCTTY)
916 }
917
918 #[inline(always)]
919 pub const fn no_follow_symlinks(self) -> Self {
920 self.bit_or(linux_unsafe::O_NOFOLLOW)
921 }
922
923 #[inline(always)]
924 pub const fn nonblocking(self) -> Self {
925 self.bit_or(linux_unsafe::O_NONBLOCK)
926 }
927
928 #[inline(always)]
929 pub const fn path_only(self) -> Self {
930 self.bit_or(linux_unsafe::O_PATH)
931 }
932
933 #[inline(always)]
934 pub const fn sync(self) -> Self {
935 self.bit_or(linux_unsafe::O_SYNC)
936 }
937
938 #[inline(always)]
939 pub const fn temp_file(self) -> OpenOptions<OpenWithMode> {
940 OpenOptions {
941 flags: self.bit_or(linux_unsafe::O_TMPFILE).flags,
942 _phantom: core::marker::PhantomData,
943 }
944 }
945
946 #[inline(always)]
947 pub const fn truncate(self) -> Self {
948 self.bit_or(linux_unsafe::O_TRUNC)
949 }
950
951 #[inline(always)]
954 pub const fn into_raw_flags(self) -> linux_unsafe::int {
955 self.flags
956 }
957}
958
959impl<NeedMode: OpenMode> Into<linux_unsafe::int> for OpenOptions<NeedMode> {
960 #[inline(always)]
961 fn into(self) -> linux_unsafe::int {
962 self.into_raw_flags()
963 }
964}
965
966pub enum OpenWithMode {}
969
970pub enum OpenWithoutMode {}
973
974pub trait OpenMode {}
977
978impl OpenMode for OpenWithMode {}
979impl OpenMode for OpenWithoutMode {}