folder.rs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. extern crate libc;
  2. extern crate core;
  3. use ::{c_int, c_char};
  4. use syscall::{self, O_CLOEXEC, O_RDONLY, O_DIRECTORY};
  5. use core::ptr::null;
  6. use core::default::Default;
  7. use alloc::boxed::Box;
  8. use ::file::PATH_MAX;
  9. use ::types::{ino_t, off_t};
  10. use libc::*;
  11. #[repr(C)]
  12. pub struct dirent {
  13. pub d_ino: ino_t,
  14. pub d_off: off_t,
  15. pub d_reclen: c_ushort,
  16. pub d_type: c_uchar,
  17. pub d_name: [c_char; PATH_MAX]
  18. }
  19. impl core::default::Default for dirent {
  20. fn default() -> dirent {
  21. dirent {
  22. d_ino: 0,
  23. d_off: 0,
  24. d_reclen: 0,
  25. d_type: 0,
  26. d_name: [0; PATH_MAX],
  27. }
  28. }
  29. }
  30. pub struct DIR {
  31. pub fd: ::RawFile,
  32. pub ent: dirent,
  33. pub buf: [u8; PATH_MAX],
  34. pub count: usize,
  35. pub pos: usize
  36. }
  37. libc_fn!(unsafe opendir(path: *mut c_char) -> Result<*mut DIR> {
  38. let path = ::cstr_to_slice(path);
  39. let fd = ::RawFile::open(path, O_RDONLY | O_CLOEXEC | O_DIRECTORY)?;
  40. let dir = Box::new(DIR {
  41. fd,
  42. ent: dirent::default(),
  43. buf: [0; PATH_MAX],
  44. count: 0,
  45. pos: 0
  46. });
  47. Ok(Box::into_raw(dir))
  48. });
  49. libc_fn!(unsafe readdir(dir: *mut DIR) -> Result<*const dirent> {
  50. if let Some(dir) = dir.as_mut() {
  51. let mut i = 0;
  52. 'outer: while i < PATH_MAX - 1 {
  53. while dir.pos < dir.count {
  54. dir.ent.d_name[i] = dir.buf[dir.pos] as c_char;
  55. dir.pos += 1;
  56. if dir.buf[dir.pos-1] == b'\n' {
  57. break 'outer;
  58. }
  59. i += 1;
  60. }
  61. dir.count = syscall::read(*dir.fd, &mut dir.buf)?;
  62. if dir.count == 0 {
  63. break;
  64. }
  65. dir.pos = 0;
  66. }
  67. if i != 0 {
  68. dir.ent.d_name[i] = 0;
  69. return Ok(&dir.ent);
  70. }
  71. }
  72. Ok(null())
  73. });
  74. libc_fn!(unsafe rewinddir(dir: *mut DIR) {
  75. if let Some(dir) = dir.as_mut() {
  76. dir.count = 0;
  77. let _ = syscall::lseek(*dir.fd, 0, syscall::SEEK_SET);
  78. }
  79. });
  80. libc_fn!(unsafe closedir(dir: *mut DIR) -> Result<c_int> {
  81. Box::from_raw(dir);
  82. Ok(0)
  83. });
  84. libc_fn!(unsafe dirfd(dir: *mut DIR) -> Result<c_int> {
  85. Ok(*(*dir).fd as i32)
  86. });