fs.rs 3.2 KB

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