file.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. use syscall::{self, O_CLOEXEC, O_STAT, O_CREAT, O_EXCL, O_DIRECTORY, O_WRONLY, O_NOFOLLOW, TimeSpec};
  2. use core::slice;
  3. use libc::{c_int, c_char, off_t, mode_t, size_t, ssize_t};
  4. use ::types::{utimbuf, timeval};
  5. pub const PATH_MAX: usize = 4096;
  6. libc_fn!(unsafe access(path: *mut c_char, _amode: c_int) -> Result<c_int> {
  7. // XXX amode
  8. ::RawFile::open(::cstr_to_slice(path), O_CLOEXEC | O_STAT)?;
  9. Ok(0)
  10. });
  11. libc_fn!(unsafe _close(file: c_int) -> Result<c_int> {
  12. Ok(syscall::close(file as usize)? as c_int)
  13. });
  14. libc_fn!(unsafe dup(file: c_int) -> Result<c_int> {
  15. Ok(syscall::dup(file as usize, &[])? as c_int)
  16. });
  17. libc_fn!(unsafe dup2(file: c_int, newfile: c_int) -> Result<c_int> {
  18. Ok(syscall::dup2(file as usize, newfile as usize, &[])? as c_int)
  19. });
  20. libc_fn!(unsafe _fstat(file: c_int, st: *mut syscall::Stat) -> Result<c_int> {
  21. Ok(syscall::fstat(file as usize, &mut *st)? as c_int)
  22. });
  23. libc_fn!(unsafe _fsync(file: c_int) -> Result<c_int> {
  24. Ok(syscall::fsync(file as usize)? as c_int)
  25. });
  26. libc_fn!(unsafe ftruncate(file: c_int, len: off_t) -> Result<c_int> {
  27. Ok(syscall::ftruncate(file as usize, len as usize)? as c_int)
  28. });
  29. libc_fn!(unsafe _lseek(file: c_int, ptr: off_t, dir: c_int) -> Result<off_t> {
  30. Ok(syscall::lseek(file as usize, ptr as isize, dir as usize)? as off_t)
  31. });
  32. libc_fn!(unsafe mkdir(path: *mut c_char, mode: mode_t) -> Result<c_int> {
  33. let flags = O_CREAT | O_EXCL | O_CLOEXEC | O_DIRECTORY | (mode as usize & 0o777);
  34. ::RawFile::open(::cstr_to_slice(path), flags)?;
  35. Ok(0)
  36. });
  37. libc_fn!(unsafe _open(path: *mut c_char, flags: c_int, mode: mode_t) -> Result<c_int> {
  38. let mut path = ::cstr_to_slice(path);
  39. // XXX hack; use better method if possible
  40. if path == b"/dev/null" {
  41. path = b"null:"
  42. }
  43. Ok(syscall::open(path, flags as usize | (mode as usize & 0o777))? as c_int)
  44. });
  45. libc_fn!(unsafe pipe(pipefd: *mut [c_int; 2]) -> c_int {
  46. pipe2(pipefd, 0)
  47. });
  48. libc_fn!(unsafe pipe2(pipefd: *mut [c_int; 2], flags: c_int) -> Result<c_int> {
  49. let mut syspipefd = [(*pipefd)[0] as usize, (*pipefd)[1] as usize];
  50. syscall::pipe2(&mut syspipefd, flags as usize)?;
  51. (*pipefd)[0] = syspipefd[0] as c_int;
  52. (*pipefd)[1] = syspipefd[1] as c_int;
  53. Ok(0)
  54. });
  55. libc_fn!(unsafe _read(file: c_int, buf: *mut c_char, len: c_int) -> Result<c_int> {
  56. let buf = slice::from_raw_parts_mut(buf as *mut u8, len as usize);
  57. Ok(syscall::read(file as usize, buf)? as c_int)
  58. });
  59. libc_fn!(unsafe rmdir(path: *mut c_char) -> Result<c_int> {
  60. Ok(syscall::rmdir(::cstr_to_slice(path))? as c_int)
  61. });
  62. libc_fn!(unsafe _stat(path: *const c_char, st: *mut syscall::Stat) -> Result<c_int> {
  63. let fd = ::RawFile::open(::cstr_to_slice(path), O_CLOEXEC | O_STAT)?;
  64. Ok(syscall::fstat(*fd, &mut *st)? as c_int)
  65. });
  66. libc_fn!(unsafe lstat(path: *const c_char, st: *mut syscall::Stat) -> Result<c_int> {
  67. let fd = ::RawFile::open(::cstr_to_slice(path), O_CLOEXEC | O_STAT | O_NOFOLLOW)?;
  68. Ok(syscall::fstat(*fd, &mut *st)? as c_int)
  69. });
  70. libc_fn!(unsafe _unlink(path: *mut c_char) -> Result<c_int> {
  71. Ok(syscall::unlink(::cstr_to_slice(path))? as c_int)
  72. });
  73. libc_fn!(unsafe _write(file: c_int, buf: *const c_char, len: c_int) -> Result<c_int> {
  74. let buf = slice::from_raw_parts(buf as *const u8, len as usize);
  75. Ok(syscall::write(file as usize, buf)? as c_int)
  76. });
  77. libc_fn!(unsafe chmod(path: *mut c_char, mode: mode_t) -> Result<c_int> {
  78. Ok(syscall::chmod(::cstr_to_slice(path), mode as usize)? as c_int)
  79. });
  80. libc_fn!(unsafe realpath(path: *const c_char, resolved_path: *mut c_char) -> Result<*mut c_char> {
  81. let fd = ::RawFile::open(::cstr_to_slice(path), O_STAT)?;
  82. let resolved_path = ::MallocNull::new(resolved_path, PATH_MAX);
  83. let buf = slice::from_raw_parts_mut(resolved_path.as_mut_ptr() as *mut u8, PATH_MAX-1);
  84. let length = syscall::fpath(*fd, buf)?;
  85. buf[length] = b'\0';
  86. Ok(resolved_path.into_raw())
  87. });
  88. libc_fn!(unsafe _rename(old: *const c_char, new: *const c_char) -> Result<c_int> {
  89. // XXX fix this horror when the kernel provides rename() or link()
  90. let old = ::cstr_to_slice(old);
  91. let new = ::cstr_to_slice(new);
  92. let buf = ::file_read_all(old)?;
  93. let mut stat = syscall::Stat::default();
  94. let fd = ::RawFile::open(old, syscall::O_STAT)?;
  95. syscall::fstat(*fd, &mut stat)?;
  96. drop(fd);
  97. let mode = (stat.st_mode & 0o777) as usize;
  98. let fd = ::RawFile::open(new, O_CREAT | O_WRONLY | mode)?;
  99. syscall::write(*fd, &buf)?;
  100. syscall::unlink(old)?;
  101. Ok(0)
  102. });
  103. libc_fn!(fsync(fd: c_int) -> Result<c_int> {
  104. Ok(syscall::fsync(fd as usize)? as c_int)
  105. });
  106. libc_fn!(unsafe symlink(path1: *const c_char, path2: *const c_char) -> Result<c_int> {
  107. let fd = ::RawFile::open(::cstr_to_slice(path2), syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777)?;
  108. syscall::write(*fd, ::cstr_to_slice(path1))?;
  109. Ok(0)
  110. });
  111. libc_fn!(unsafe readlink(path: *const c_char, buf: *const c_char, bufsize: size_t) -> Result<ssize_t> {
  112. let fd = ::RawFile::open(::cstr_to_slice(path), syscall::O_SYMLINK | syscall::O_RDONLY)?;
  113. let count = syscall::read(*fd, slice::from_raw_parts_mut(buf as *mut u8, bufsize))?;
  114. Ok(count as ssize_t)
  115. });
  116. libc_fn!(unsafe utime(path: *mut c_char, times: *const utimbuf) -> Result<c_int> {
  117. let times = if times.is_null() {
  118. let mut tp = TimeSpec::default();
  119. syscall::clock_gettime(syscall::flag::CLOCK_REALTIME, &mut tp)?;
  120. [tp, tp]
  121. } else {
  122. [TimeSpec { tv_sec: (*times).actime, tv_nsec: 0 },
  123. TimeSpec { tv_sec: (*times).modtime, tv_nsec: 0 }]
  124. };
  125. let fd = ::RawFile::open(::cstr_to_slice(path), 0)?;
  126. syscall::futimens(*fd, &times)?;
  127. Ok(0)
  128. });
  129. libc_fn!(unsafe utimes(path: *mut c_char, times: *const [timeval; 2]) -> Result<c_int> {
  130. let times = [TimeSpec { tv_sec: (*times)[0].tv_sec, tv_nsec: (*times)[0].tv_usec as i32 * 1000 },
  131. TimeSpec { tv_sec: (*times)[1].tv_sec, tv_nsec: (*times)[0].tv_usec as i32 * 1000 }];
  132. let fd = ::RawFile::open(::cstr_to_slice(path), 0)?;
  133. syscall::futimens(*fd, &times)?;
  134. Ok(0)
  135. });
  136. libc_fn!(unsafe futimens(fd: c_int, times: *const [TimeSpec; 2]) -> Result<c_int> {
  137. // XXX UTIME_NOW and UTIME_OMIT (in redoxfs?)
  138. syscall::futimens(fd as usize, &*times)?;
  139. Ok(0)
  140. });
  141. // XXX variadic
  142. libc_fn!(_fcntl(file: c_int, cmd: c_int, arg: c_int) -> Result<c_int> {
  143. Ok(syscall::fcntl(file as usize, cmd as usize, arg as usize)? as c_int)
  144. });
  145. libc_fn!(_isatty(file: c_int) -> c_int {
  146. if let Ok(fd) = syscall::dup(file as usize, b"termios") {
  147. let _ = syscall::close(fd);
  148. 1
  149. } else {
  150. 0
  151. }
  152. });