1
0

xattr_linux.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //! Extended attribute support for darwin
  2. extern crate libc;
  3. use std::ffi::CString;
  4. use std::ptr;
  5. use std::old_io as io;
  6. use self::libc::{size_t, ssize_t, c_char, c_void};
  7. extern "C" {
  8. fn listxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t;
  9. fn llistxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t;
  10. fn getxattr(path: *const c_char, name: *const c_char,
  11. value: *mut c_void, size: size_t
  12. ) -> ssize_t;
  13. fn lgetxattr(path: *const c_char, name: *const c_char,
  14. value: *mut c_void, size: size_t
  15. ) -> ssize_t;
  16. }
  17. /// Attributes which can be passed to `Attribute::list_with_flags`
  18. #[derive(Copy)]
  19. pub enum FollowSymlinks {
  20. Yes,
  21. No
  22. }
  23. /// Extended attribute
  24. #[derive(Debug, Clone)]
  25. pub struct Attribute {
  26. name: String,
  27. size: usize,
  28. }
  29. impl Attribute {
  30. /// Lists the extended attribute of `path`.
  31. /// Does follow symlinks by default.
  32. pub fn list(path: &Path, do_follow: FollowSymlinks) -> io::IoResult<Vec<Attribute>> {
  33. let (listxattr, getxattr) = match do_follow {
  34. FollowSymlinks::Yes => (listxattr, getxattr),
  35. FollowSymlinks::No => (llistxattr, lgetxattr),
  36. };
  37. let c_path = try!(CString::new(path.as_vec()));
  38. let bufsize = unsafe {
  39. listxattr(c_path.as_ptr(), ptr::null_mut(), 0)
  40. };
  41. if bufsize > 0 {
  42. let mut buf = vec![0u8; bufsize as usize];
  43. let err = unsafe { listxattr(
  44. c_path.as_ptr(),
  45. buf.as_mut_ptr() as *mut c_char,
  46. bufsize as size_t
  47. )};
  48. if err > 0 {
  49. // End indicies of the attribute names
  50. // the buffer contains 0-terminates c-strings
  51. let idx = buf.iter().enumerate().filter_map(|(i, v)|
  52. if *v == 0 { Some(i) } else { None }
  53. );
  54. let mut names = Vec::new();
  55. let mut start = 0;
  56. for end in idx {
  57. let size = unsafe {
  58. getxattr(
  59. c_path.as_ptr(),
  60. buf[start..end+1].as_ptr() as *const c_char,
  61. ptr::null_mut(), 0
  62. )
  63. };
  64. if size > 0 {
  65. names.push(Attribute {
  66. name: String::from_utf8_lossy(&buf[start..end]).into_owned(),
  67. size: size as usize
  68. });
  69. }
  70. start = end + 1;
  71. }
  72. Ok(names)
  73. } else {
  74. Err(io::IoError {
  75. kind: io::OtherIoError,
  76. desc: "could not read extended attributes",
  77. detail: None
  78. })
  79. }
  80. } else {
  81. Err(io::IoError {
  82. kind: io::OtherIoError,
  83. desc: "could not read extended attributes",
  84. detail: None
  85. })
  86. }
  87. }
  88. /// Getter for name
  89. pub fn name(&self) -> &str {
  90. &self.name
  91. }
  92. /// Getter for size
  93. pub fn size(&self) -> usize {
  94. self.size
  95. }
  96. }
  97. /// Lists the extended attributes.
  98. /// Follows symlinks like `stat`
  99. pub fn list(path: &Path) -> io::IoResult<Vec<Attribute>> {
  100. Attribute::list(path, FollowSymlinks::Yes)
  101. }
  102. /// Lists the extended attributes.
  103. /// Does not follow symlinks like `lstat`
  104. pub fn llist(path: &Path) -> io::IoResult<Vec<Attribute>> {
  105. Attribute::list(path, FollowSymlinks::No)
  106. }
  107. /// Returns true if the extended attribute feature is implemented on this platform.
  108. #[inline(always)]
  109. pub fn feature_implemented() -> bool { true }