| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- //! Extended attribute support for darwin
- extern crate libc;
- use std::ffi::CString;
- use std::ptr;
- use std::old_io as io;
- use self::libc::{size_t, ssize_t, c_char, c_void};
- extern "C" {
- fn listxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t;
- fn llistxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t;
- fn getxattr(path: *const c_char, name: *const c_char,
- value: *mut c_void, size: size_t
- ) -> ssize_t;
- fn lgetxattr(path: *const c_char, name: *const c_char,
- value: *mut c_void, size: size_t
- ) -> ssize_t;
- }
- /// Attributes which can be passed to `Attribute::list_with_flags`
- #[derive(Copy)]
- pub enum FollowSymlinks {
- Yes,
- No
- }
- /// Extended attribute
- #[derive(Debug, Clone)]
- pub struct Attribute {
- name: String,
- size: usize,
- }
- impl Attribute {
- /// Lists the extended attribute of `path`.
- /// Does follow symlinks by default.
- pub fn list(path: &Path, do_follow: FollowSymlinks) -> io::IoResult<Vec<Attribute>> {
- let (listxattr, getxattr) = match do_follow {
- FollowSymlinks::Yes => (listxattr, getxattr),
- FollowSymlinks::No => (llistxattr, lgetxattr),
- };
- let c_path = try!(CString::new(path.as_vec()));
- let bufsize = unsafe {
- listxattr(c_path.as_ptr(), ptr::null_mut(), 0)
- };
- if bufsize > 0 {
- let mut buf = vec![0u8; bufsize as usize];
- let err = unsafe { listxattr(
- c_path.as_ptr(),
- buf.as_mut_ptr() as *mut c_char,
- bufsize as size_t
- )};
- if err > 0 {
- // End indicies of the attribute names
- // the buffer contains 0-terminates c-strings
- let idx = buf.iter().enumerate().filter_map(|(i, v)|
- if *v == 0 { Some(i) } else { None }
- );
- let mut names = Vec::new();
- let mut start = 0;
- for end in idx {
- let size = unsafe {
- getxattr(
- c_path.as_ptr(),
- buf[start..end+1].as_ptr() as *const c_char,
- ptr::null_mut(), 0
- )
- };
- if size > 0 {
- names.push(Attribute {
- name: String::from_utf8_lossy(&buf[start..end]).into_owned(),
- size: size as usize
- });
- }
- start = end + 1;
- }
- Ok(names)
- } else {
- Err(io::IoError {
- kind: io::OtherIoError,
- desc: "could not read extended attributes",
- detail: None
- })
- }
- } else {
- Err(io::IoError {
- kind: io::OtherIoError,
- desc: "could not read extended attributes",
- detail: None
- })
- }
- }
-
- /// Getter for name
- pub fn name(&self) -> &str {
- &self.name
- }
- /// Getter for size
- pub fn size(&self) -> usize {
- self.size
- }
- }
- /// Lists the extended attributes.
- /// Follows symlinks like `stat`
- pub fn list(path: &Path) -> io::IoResult<Vec<Attribute>> {
- Attribute::list(path, FollowSymlinks::Yes)
- }
- /// Lists the extended attributes.
- /// Does not follow symlinks like `lstat`
- pub fn llist(path: &Path) -> io::IoResult<Vec<Attribute>> {
- Attribute::list(path, FollowSymlinks::No)
- }
- /// Returns true if the extended attribute feature is implemented on this platform.
- #[inline(always)]
- pub fn feature_implemented() -> bool { true }
|