fs.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. use crate::c_str::CStr;
  2. use core::ops::Deref;
  3. use crate::header::fcntl::O_CREAT;
  4. use crate::header::unistd::{SEEK_CUR, SEEK_END, SEEK_SET};
  5. use crate::io;
  6. use crate::platform::types::*;
  7. use crate::platform::{Pal, Sys};
  8. pub struct File {
  9. pub fd: c_int,
  10. /// To avoid self referential FILE struct that needs both a reader and a writer,
  11. /// make "reference" files that share fd but don't close on drop.
  12. pub reference: bool,
  13. }
  14. impl File {
  15. pub fn new(fd: c_int) -> Self {
  16. Self {
  17. fd,
  18. reference: false,
  19. }
  20. }
  21. pub fn open(path: &CStr, oflag: c_int) -> io::Result<Self> {
  22. match Sys::open(path, oflag, 0) {
  23. -1 => Err(io::last_os_error()),
  24. ok => Ok(Self::new(ok)),
  25. }
  26. }
  27. pub fn create(path: &CStr, oflag: c_int, mode: mode_t) -> io::Result<Self> {
  28. match Sys::open(path, oflag | O_CREAT, mode) {
  29. -1 => Err(io::last_os_error()),
  30. ok => Ok(Self::new(ok)),
  31. }
  32. }
  33. pub fn sync_all(&self) -> io::Result<()> {
  34. match Sys::fsync(self.fd) {
  35. -1 => Err(io::last_os_error()),
  36. _ok => Ok(()),
  37. }
  38. }
  39. pub fn set_len(&self, size: u64) -> io::Result<()> {
  40. match Sys::ftruncate(self.fd, size as off_t) {
  41. -1 => Err(io::last_os_error()),
  42. _ok => Ok(()),
  43. }
  44. }
  45. pub fn try_clone(&self) -> io::Result<Self> {
  46. match Sys::dup(self.fd) {
  47. -1 => Err(io::last_os_error()),
  48. ok => Ok(Self::new(ok)),
  49. }
  50. }
  51. /// Create a new file pointing to the same underlying descriptor. This file
  52. /// will know it's a "reference" and won't close the fd. It will, however,
  53. /// not prevent the original file from closing the fd.
  54. pub unsafe fn get_ref(&self) -> Self {
  55. Self {
  56. fd: self.fd,
  57. reference: true,
  58. }
  59. }
  60. }
  61. impl io::Read for &File {
  62. fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
  63. match Sys::read(self.fd, buf) {
  64. -1 => Err(io::last_os_error()),
  65. ok => Ok(ok as usize),
  66. }
  67. }
  68. }
  69. impl io::Write for &File {
  70. fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
  71. match Sys::write(self.fd, buf) {
  72. -1 => Err(io::last_os_error()),
  73. ok => Ok(ok as usize),
  74. }
  75. }
  76. fn flush(&mut self) -> io::Result<()> {
  77. Ok(())
  78. }
  79. }
  80. impl io::Seek for &File {
  81. fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
  82. let (offset, whence) = match pos {
  83. io::SeekFrom::Start(start) => (start as off_t, SEEK_SET),
  84. io::SeekFrom::Current(current) => (current as off_t, SEEK_CUR),
  85. io::SeekFrom::End(end) => (end as off_t, SEEK_END),
  86. };
  87. match Sys::lseek(self.fd, offset, whence) {
  88. -1 => Err(io::last_os_error()),
  89. ok => Ok(ok as u64),
  90. }
  91. }
  92. }
  93. impl io::Read for File {
  94. fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
  95. (&mut &*self).read(buf)
  96. }
  97. }
  98. impl io::Write for File {
  99. fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
  100. (&mut &*self).write(buf)
  101. }
  102. fn flush(&mut self) -> io::Result<()> {
  103. (&mut &*self).flush()
  104. }
  105. }
  106. impl io::Seek for File {
  107. fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
  108. (&mut &*self).seek(pos)
  109. }
  110. }
  111. impl Deref for File {
  112. type Target = c_int;
  113. fn deref(&self) -> &Self::Target {
  114. &self.fd
  115. }
  116. }
  117. impl Drop for File {
  118. fn drop(&mut self) {
  119. if !self.reference {
  120. let _ = Sys::close(self.fd);
  121. }
  122. }
  123. }