summaryrefslogtreecommitdiffstats
path: root/vendor/xattr/src/sys
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/xattr/src/sys
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/xattr/src/sys')
-rw-r--r--vendor/xattr/src/sys/bsd.rs367
-rw-r--r--vendor/xattr/src/sys/linux_macos/linux.rs52
-rw-r--r--vendor/xattr/src/sys/linux_macos/macos.rs120
-rw-r--r--vendor/xattr/src/sys/linux_macos/mod.rs168
-rw-r--r--vendor/xattr/src/sys/mod.rs40
-rw-r--r--vendor/xattr/src/sys/unsupported.rs77
6 files changed, 824 insertions, 0 deletions
diff --git a/vendor/xattr/src/sys/bsd.rs b/vendor/xattr/src/sys/bsd.rs
new file mode 100644
index 000000000..910fbbdf9
--- /dev/null
+++ b/vendor/xattr/src/sys/bsd.rs
@@ -0,0 +1,367 @@
+//! FreeBSD and NetBSD xattr support.
+
+use std::ffi::{CString, OsStr, OsString};
+use std::io;
+use std::mem;
+use std::os::unix::ffi::{OsStrExt, OsStringExt};
+use std::os::unix::io::RawFd;
+use std::path::Path;
+
+use libc::{c_char, c_int, c_void, size_t, ssize_t, EPERM};
+use util::{allocate_loop, path_to_c};
+
+const EXTATTR_NAMESPACE_USER_STRING: &'static str = "user";
+const EXTATTR_NAMESPACE_SYSTEM_STRING: &'static str = "system";
+const EXTATTR_NAMESPACE_NAMES: [&'static str; 3] = [
+ "empty",
+ EXTATTR_NAMESPACE_USER_STRING,
+ EXTATTR_NAMESPACE_SYSTEM_STRING,
+];
+const EXTATTR_NAMESPACE_USER: c_int = 1;
+const EXTATTR_NAMESPACE_SYSTEM: c_int = 2;
+
+extern "C" {
+ pub fn extattr_list_fd(
+ fd: c_int,
+ attrnamespace: c_int,
+ data: *mut c_void,
+ nbytes: size_t,
+ ) -> ssize_t;
+ pub fn extattr_get_fd(
+ fd: c_int,
+ attrnamespace: c_int,
+ attrname: *const c_char,
+ data: *mut c_void,
+ nbytes: size_t,
+ ) -> ssize_t;
+ pub fn extattr_delete_fd(fd: c_int, attrname: c_int, attrname: *const c_char) -> c_int;
+ pub fn extattr_set_fd(
+ fd: c_int,
+ attrname: c_int,
+ attrname: *const c_char,
+ data: *const c_void,
+ nbytes: size_t,
+ ) -> ssize_t;
+
+ pub fn extattr_list_link(
+ path: *const c_char,
+ attrnamespace: c_int,
+ data: *mut c_void,
+ nbytes: size_t,
+ ) -> ssize_t;
+ pub fn extattr_get_link(
+ path: *const c_char,
+ attrnamespace: c_int,
+ attrname: *const c_char,
+ data: *mut c_void,
+ nbytes: size_t,
+ ) -> ssize_t;
+ pub fn extattr_delete_link(
+ path: *const c_char,
+ attrname: c_int,
+ attrname: *const c_char,
+ ) -> c_int;
+ pub fn extattr_set_link(
+ path: *const c_char,
+ attrname: c_int,
+ attrname: *const c_char,
+ data: *const c_void,
+ nbytes: size_t,
+ ) -> ssize_t;
+}
+
+/// An iterator over a set of extended attributes names.
+pub struct XAttrs {
+ user_attrs: Box<[u8]>,
+ system_attrs: Box<[u8]>,
+ offset: usize,
+}
+
+impl Clone for XAttrs {
+ fn clone(&self) -> Self {
+ XAttrs {
+ user_attrs: Vec::from(&*self.user_attrs).into_boxed_slice(),
+ system_attrs: Vec::from(&*self.system_attrs).into_boxed_slice(),
+ offset: self.offset,
+ }
+ }
+
+ fn clone_from(&mut self, other: &XAttrs) {
+ self.offset = other.offset;
+
+ let mut data = mem::replace(&mut self.user_attrs, Box::new([])).into_vec();
+ data.extend(other.user_attrs.iter().cloned());
+ self.user_attrs = data.into_boxed_slice();
+
+ data = mem::replace(&mut self.system_attrs, Box::new([])).into_vec();
+ data.extend(other.system_attrs.iter().cloned());
+ self.system_attrs = data.into_boxed_slice();
+ }
+}
+
+impl Iterator for XAttrs {
+ type Item = OsString;
+ fn next(&mut self) -> Option<OsString> {
+ if self.user_attrs.is_empty() && self.system_attrs.is_empty() {
+ return None;
+ }
+
+ if self.offset == self.user_attrs.len() + self.system_attrs.len() {
+ return None;
+ }
+
+ let data = if self.offset < self.system_attrs.len() {
+ &self.system_attrs[self.offset..]
+ } else {
+ &self.user_attrs[self.offset - self.system_attrs.len()..]
+ };
+
+ let siz = data[0] as usize;
+
+ self.offset += siz + 1;
+ if self.offset < self.system_attrs.len() {
+ Some(prefix_namespace(
+ OsStr::from_bytes(&data[1..siz + 1]),
+ EXTATTR_NAMESPACE_SYSTEM,
+ ))
+ } else {
+ Some(prefix_namespace(
+ OsStr::from_bytes(&data[1..siz + 1]),
+ EXTATTR_NAMESPACE_USER,
+ ))
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ if self.user_attrs.len() + self.system_attrs.len() == self.offset {
+ (0, Some(0))
+ } else {
+ (1, None)
+ }
+ }
+}
+
+fn name_to_ns(name: &OsStr) -> io::Result<(c_int, CString)> {
+ let mut groups = name.as_bytes().splitn(2, |&b| b == b'.').take(2);
+ let nsname = match groups.next() {
+ Some(s) => s,
+ None => {
+ return Err(io::Error::new(
+ io::ErrorKind::InvalidInput,
+ "couldn't find namespace",
+ ))
+ }
+ };
+
+ let propname = match groups.next() {
+ Some(s) => s,
+ None => {
+ return Err(io::Error::new(
+ io::ErrorKind::InvalidInput,
+ "couldn't find attribute",
+ ))
+ }
+ };
+
+ let ns_int = match EXTATTR_NAMESPACE_NAMES
+ .iter()
+ .position(|&s| s.as_bytes() == nsname)
+ {
+ Some(i) => i,
+ None => {
+ return Err(io::Error::new(
+ io::ErrorKind::InvalidInput,
+ "no matching namespace",
+ ))
+ }
+ };
+
+ Ok((ns_int as c_int, CString::new(propname)?))
+}
+
+fn prefix_namespace(attr: &OsStr, ns: c_int) -> OsString {
+ let nsname = EXTATTR_NAMESPACE_NAMES[ns as usize];
+ let mut v = Vec::with_capacity(nsname.as_bytes().len() + attr.as_bytes().len() + 1);
+ v.extend(nsname.as_bytes());
+ v.extend(".".as_bytes());
+ v.extend(attr.as_bytes());
+ OsString::from_vec(v)
+}
+
+pub fn get_fd(fd: RawFd, name: &OsStr) -> io::Result<Vec<u8>> {
+ let (ns, name) = name_to_ns(name)?;
+ unsafe {
+ allocate_loop(|buf, len| {
+ extattr_get_fd(fd, ns, name.as_ptr(), buf as *mut c_void, len as size_t)
+ })
+ }
+}
+
+pub fn set_fd(fd: RawFd, name: &OsStr, value: &[u8]) -> io::Result<()> {
+ let (ns, name) = name_to_ns(name)?;
+ let ret = unsafe {
+ extattr_set_fd(
+ fd,
+ ns,
+ name.as_ptr(),
+ value.as_ptr() as *const c_void,
+ value.len() as size_t,
+ )
+ };
+ if ret == -1 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+pub fn remove_fd(fd: RawFd, name: &OsStr) -> io::Result<()> {
+ let (ns, name) = name_to_ns(name)?;
+ let ret = unsafe { extattr_delete_fd(fd, ns, name.as_ptr()) };
+ if ret != 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+pub fn list_fd(fd: RawFd) -> io::Result<XAttrs> {
+ let sysvec = unsafe {
+ let res = allocate_loop(|buf, len| {
+ extattr_list_fd(
+ fd,
+ EXTATTR_NAMESPACE_SYSTEM,
+ buf as *mut c_void,
+ len as size_t,
+ )
+ });
+ // On FreeBSD, system attributes require root privileges to view. However,
+ // to mimic the behavior of listxattr in linux and osx, we need to query
+ // them anyway and return empty results if we get EPERM
+ match res {
+ Ok(v) => v,
+ Err(err) => {
+ if err.raw_os_error() == Some(EPERM) {
+ Vec::new()
+ } else {
+ return Err(err);
+ }
+ }
+ }
+ };
+
+ let uservec = unsafe {
+ let res = allocate_loop(|buf, len| {
+ extattr_list_fd(
+ fd,
+ EXTATTR_NAMESPACE_USER,
+ buf as *mut c_void,
+ len as size_t,
+ )
+ });
+ match res {
+ Ok(v) => v,
+ Err(err) => return Err(err),
+ }
+ };
+
+ Ok(XAttrs {
+ system_attrs: sysvec.into_boxed_slice(),
+ user_attrs: uservec.into_boxed_slice(),
+ offset: 0,
+ })
+}
+
+pub fn get_path(path: &Path, name: &OsStr) -> io::Result<Vec<u8>> {
+ let (ns, name) = name_to_ns(name)?;
+ let path = path_to_c(path)?;
+ unsafe {
+ allocate_loop(|buf, len| {
+ extattr_get_link(
+ path.as_ptr(),
+ ns,
+ name.as_ptr(),
+ buf as *mut c_void,
+ len as size_t,
+ )
+ })
+ }
+}
+
+pub fn set_path(path: &Path, name: &OsStr, value: &[u8]) -> io::Result<()> {
+ let (ns, name) = name_to_ns(name)?;
+ let path = path_to_c(path)?;
+ let ret = unsafe {
+ extattr_set_link(
+ path.as_ptr(),
+ ns,
+ name.as_ptr(),
+ value.as_ptr() as *const c_void,
+ value.len() as size_t,
+ )
+ };
+ if ret == -1 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+pub fn remove_path(path: &Path, name: &OsStr) -> io::Result<()> {
+ let (ns, name) = name_to_ns(name)?;
+ let path = path_to_c(path)?;
+ let ret = unsafe { extattr_delete_link(path.as_ptr(), ns, name.as_ptr()) };
+ if ret != 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+pub fn list_path(path: &Path) -> io::Result<XAttrs> {
+ let path = path_to_c(path)?;
+ let sysvec = unsafe {
+ let res = allocate_loop(|buf, len| {
+ extattr_list_link(
+ path.as_ptr(),
+ EXTATTR_NAMESPACE_SYSTEM,
+ buf as *mut c_void,
+ len as size_t,
+ )
+ });
+ // On FreeBSD, system attributes require root privileges to view. However,
+ // to mimic the behavior of listxattr in linux and osx, we need to query
+ // them anyway and return empty results if we get EPERM
+ match res {
+ Ok(v) => v,
+ Err(err) => {
+ if err.raw_os_error() == Some(EPERM) {
+ Vec::new()
+ } else {
+ return Err(err);
+ }
+ }
+ }
+ };
+
+ let uservec = unsafe {
+ let res = allocate_loop(|buf, len| {
+ extattr_list_link(
+ path.as_ptr(),
+ EXTATTR_NAMESPACE_USER,
+ buf as *mut c_void,
+ len as size_t,
+ )
+ });
+ match res {
+ Ok(v) => v,
+ Err(err) => return Err(err),
+ }
+ };
+
+ Ok(XAttrs {
+ system_attrs: sysvec.into_boxed_slice(),
+ user_attrs: uservec.into_boxed_slice(),
+ offset: 0,
+ })
+}
diff --git a/vendor/xattr/src/sys/linux_macos/linux.rs b/vendor/xattr/src/sys/linux_macos/linux.rs
new file mode 100644
index 000000000..6f23fc3e1
--- /dev/null
+++ b/vendor/xattr/src/sys/linux_macos/linux.rs
@@ -0,0 +1,52 @@
+use libc::{c_char, c_int, c_void, size_t, ssize_t};
+
+extern "C" {
+ pub fn flistxattr(fd: c_int, buf: *mut c_char, size: size_t) -> ssize_t;
+ pub fn fgetxattr(fd: c_int, name: *const c_char, value: *mut c_void, size: size_t) -> ssize_t;
+ pub fn fremovexattr(fd: c_int, name: *const c_char) -> c_int;
+
+ pub fn llistxattr(path: *const c_char, buf: *mut c_char, size: size_t) -> ssize_t;
+ pub fn lgetxattr(
+ path: *const c_char,
+ name: *const c_char,
+ value: *mut c_void,
+ size: size_t,
+ ) -> ssize_t;
+ pub fn lremovexattr(path: *const c_char, name: *const c_char) -> c_int;
+}
+
+pub unsafe fn fsetxattr(
+ fd: c_int,
+ name: *const c_char,
+ value: *const c_void,
+ size: size_t,
+) -> ssize_t {
+ extern "C" {
+ fn fsetxattr(
+ fd: c_int,
+ name: *const c_char,
+ value: *const c_void,
+ size: size_t,
+ flags: c_int,
+ ) -> ssize_t;
+ }
+ fsetxattr(fd, name, value, size, 0)
+}
+
+pub unsafe fn lsetxattr(
+ path: *const c_char,
+ name: *const c_char,
+ value: *const c_void,
+ size: size_t,
+) -> ssize_t {
+ extern "C" {
+ fn lsetxattr(
+ path: *const c_char,
+ name: *const c_char,
+ value: *const c_void,
+ size: size_t,
+ flags: c_int,
+ ) -> ssize_t;
+ }
+ lsetxattr(path, name, value, size, 0)
+}
diff --git a/vendor/xattr/src/sys/linux_macos/macos.rs b/vendor/xattr/src/sys/linux_macos/macos.rs
new file mode 100644
index 000000000..734dd88f3
--- /dev/null
+++ b/vendor/xattr/src/sys/linux_macos/macos.rs
@@ -0,0 +1,120 @@
+use libc::{c_char, c_int, c_void, size_t, ssize_t, uint32_t};
+
+const XATTR_NOFOLLOW: c_int = 0x0001;
+
+#[inline(always)]
+pub unsafe fn fremovexattr(fd: c_int, name: *const c_char) -> c_int {
+ extern "C" {
+ fn fremovexattr(fd: c_int, name: *const c_char, options: c_int) -> c_int;
+ }
+ fremovexattr(fd, name, 0)
+}
+
+#[inline(always)]
+pub unsafe fn fsetxattr(
+ fd: c_int,
+ name: *const c_char,
+ value: *const c_void,
+ size: size_t,
+) -> ssize_t {
+ extern "C" {
+ fn fsetxattr(
+ fd: c_int,
+ name: *const c_char,
+ value: *const c_void,
+ size: size_t,
+ position: uint32_t,
+ options: c_int,
+ ) -> ssize_t;
+ }
+ fsetxattr(fd, name, value, size, 0, 0)
+}
+
+#[inline(always)]
+pub unsafe fn fgetxattr(
+ fd: c_int,
+ name: *const c_char,
+ value: *mut c_void,
+ size: size_t,
+) -> ssize_t {
+ extern "C" {
+ fn fgetxattr(
+ fd: c_int,
+ name: *const c_char,
+ value: *mut c_void,
+ size: size_t,
+ position: uint32_t,
+ options: c_int,
+ ) -> ssize_t;
+ }
+ fgetxattr(fd, name, value, size, 0, 0)
+}
+
+#[inline(always)]
+pub unsafe fn flistxattr(fd: c_int, buf: *mut c_char, size: size_t) -> ssize_t {
+ extern "C" {
+ fn flistxattr(fd: c_int, buf: *mut c_char, size: size_t, options: c_int) -> ssize_t;
+ }
+ flistxattr(fd, buf, size, 0)
+}
+
+#[inline(always)]
+pub unsafe fn lremovexattr(path: *const c_char, name: *const c_char) -> c_int {
+ extern "C" {
+ fn removexattr(path: *const c_char, name: *const c_char, options: c_int) -> c_int;
+ }
+ removexattr(path, name, XATTR_NOFOLLOW)
+}
+
+#[inline(always)]
+pub unsafe fn lsetxattr(
+ path: *const c_char,
+ name: *const c_char,
+ value: *const c_void,
+ size: size_t,
+) -> ssize_t {
+ extern "C" {
+ fn setxattr(
+ path: *const c_char,
+ name: *const c_char,
+ value: *const c_void,
+ size: size_t,
+ position: uint32_t,
+ options: c_int,
+ ) -> ssize_t;
+ }
+ setxattr(path, name, value, size, 0, XATTR_NOFOLLOW)
+}
+
+#[inline(always)]
+pub unsafe fn lgetxattr(
+ path: *const c_char,
+ name: *const c_char,
+ value: *mut c_void,
+ size: size_t,
+) -> ssize_t {
+ extern "C" {
+ fn getxattr(
+ path: *const c_char,
+ name: *const c_char,
+ value: *mut c_void,
+ size: size_t,
+ position: uint32_t,
+ options: c_int,
+ ) -> ssize_t;
+ }
+ getxattr(path, name, value, size, 0, XATTR_NOFOLLOW)
+}
+
+#[inline(always)]
+pub unsafe fn llistxattr(path: *const c_char, buf: *mut c_char, size: size_t) -> ssize_t {
+ extern "C" {
+ fn listxattr(
+ path: *const c_char,
+ buf: *mut c_char,
+ size: size_t,
+ options: c_int,
+ ) -> ssize_t;
+ }
+ listxattr(path, buf, size, XATTR_NOFOLLOW)
+}
diff --git a/vendor/xattr/src/sys/linux_macos/mod.rs b/vendor/xattr/src/sys/linux_macos/mod.rs
new file mode 100644
index 000000000..c0e86fe31
--- /dev/null
+++ b/vendor/xattr/src/sys/linux_macos/mod.rs
@@ -0,0 +1,168 @@
+#[cfg(any(target_os = "linux", target_os = "android"))]
+mod linux;
+
+#[cfg(any(target_os = "linux", target_os = "android"))]
+use self::linux::*;
+
+#[cfg(target_os = "macos")]
+mod macos;
+
+#[cfg(target_os = "macos")]
+use self::macos::*;
+
+use std::ffi::{OsStr, OsString};
+use std::io;
+use std::mem;
+use std::os::unix::ffi::OsStrExt;
+use std::os::unix::io::RawFd;
+use std::path::Path;
+
+use libc::{c_char, c_void, size_t};
+
+use util::{allocate_loop, name_to_c, path_to_c};
+
+/// An iterator over a set of extended attributes names.
+pub struct XAttrs {
+ data: Box<[u8]>,
+ offset: usize,
+}
+
+impl Clone for XAttrs {
+ fn clone(&self) -> Self {
+ XAttrs {
+ data: Vec::from(&*self.data).into_boxed_slice(),
+ offset: self.offset,
+ }
+ }
+ fn clone_from(&mut self, other: &XAttrs) {
+ self.offset = other.offset;
+
+ let mut data = mem::replace(&mut self.data, Box::new([])).into_vec();
+ data.extend(other.data.iter().cloned());
+ self.data = data.into_boxed_slice();
+ }
+}
+
+// Yes, I could avoid these allocations on linux/macos. However, if we ever want to be freebsd
+// compatible, we need to be able to prepend the namespace to the extended attribute names.
+// Furthermore, borrowing makes the API messy.
+impl Iterator for XAttrs {
+ type Item = OsString;
+ fn next(&mut self) -> Option<OsString> {
+ let data = &self.data[self.offset..];
+ if data.is_empty() {
+ None
+ } else {
+ // always null terminated (unless empty).
+ let end = data.iter().position(|&b| b == 0u8).unwrap();
+ self.offset += end + 1;
+ Some(OsStr::from_bytes(&data[..end]).to_owned())
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ if self.data.len() == self.offset {
+ (0, Some(0))
+ } else {
+ (1, None)
+ }
+ }
+}
+
+pub fn get_fd(fd: RawFd, name: &OsStr) -> io::Result<Vec<u8>> {
+ let name = name_to_c(name)?;
+ unsafe {
+ allocate_loop(|buf, len| fgetxattr(fd, name.as_ptr(), buf as *mut c_void, len as size_t))
+ }
+}
+
+pub fn set_fd(fd: RawFd, name: &OsStr, value: &[u8]) -> io::Result<()> {
+ let name = name_to_c(name)?;
+ let ret = unsafe {
+ fsetxattr(
+ fd,
+ name.as_ptr(),
+ value.as_ptr() as *const c_void,
+ value.len() as size_t,
+ )
+ };
+ if ret != 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+pub fn remove_fd(fd: RawFd, name: &OsStr) -> io::Result<()> {
+ let name = name_to_c(name)?;
+ let ret = unsafe { fremovexattr(fd, name.as_ptr()) };
+ if ret != 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+pub fn list_fd(fd: RawFd) -> io::Result<XAttrs> {
+ let vec =
+ unsafe { allocate_loop(|buf, len| flistxattr(fd, buf as *mut c_char, len as size_t))? };
+ Ok(XAttrs {
+ data: vec.into_boxed_slice(),
+ offset: 0,
+ })
+}
+
+pub fn get_path(path: &Path, name: &OsStr) -> io::Result<Vec<u8>> {
+ let name = name_to_c(name)?;
+ let path = path_to_c(path)?;
+ unsafe {
+ allocate_loop(|buf, len| {
+ lgetxattr(
+ path.as_ptr(),
+ name.as_ptr(),
+ buf as *mut c_void,
+ len as size_t,
+ )
+ })
+ }
+}
+
+pub fn set_path(path: &Path, name: &OsStr, value: &[u8]) -> io::Result<()> {
+ let name = name_to_c(name)?;
+ let path = path_to_c(path)?;
+ let ret = unsafe {
+ lsetxattr(
+ path.as_ptr(),
+ name.as_ptr(),
+ value.as_ptr() as *const c_void,
+ value.len() as size_t,
+ )
+ };
+ if ret != 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+pub fn remove_path(path: &Path, name: &OsStr) -> io::Result<()> {
+ let name = name_to_c(name)?;
+ let path = path_to_c(path)?;
+ let ret = unsafe { lremovexattr(path.as_ptr(), name.as_ptr()) };
+ if ret != 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+pub fn list_path(path: &Path) -> io::Result<XAttrs> {
+ let path = path_to_c(path)?;
+ let vec = unsafe {
+ allocate_loop(|buf, len| llistxattr(path.as_ptr(), buf as *mut c_char, len as size_t))?
+ };
+ Ok(XAttrs {
+ data: vec.into_boxed_slice(),
+ offset: 0,
+ })
+}
diff --git a/vendor/xattr/src/sys/mod.rs b/vendor/xattr/src/sys/mod.rs
new file mode 100644
index 000000000..4724826b5
--- /dev/null
+++ b/vendor/xattr/src/sys/mod.rs
@@ -0,0 +1,40 @@
+macro_rules! platforms {
+ ($($($platform:expr);* => $module:ident),*) => {
+ $(
+ #[cfg(any($(target_os = $platform),*))]
+ #[cfg_attr(not(any($(target_os = $platform),*)), allow(dead_code))]
+ mod $module;
+
+ #[cfg(any($(target_os = $platform),*))]
+ pub use self::$module::*;
+
+ #[cfg(any($(target_os = $platform),*))]
+ pub const ENOATTR: ::libc::c_int = ::libc::ENOATTR;
+ )*
+
+ #[cfg(all(feature = "unsupported", not(any($($(target_os = $platform),*),*))))]
+ #[cfg_attr(any($($(target_os = $platform),*),*), allow(dead_code))]
+ mod unsupported;
+
+ #[cfg(all(feature = "unsupported", not(any($($(target_os = $platform),*),*))))]
+ pub use self::unsupported::*;
+ #[cfg(all(feature = "unsupported", not(any($($(target_os = $platform),*),*))))]
+ pub const ENOATTR: ::libc::c_int = 0;
+
+
+ /// A constant indicating whether or not the target platform is supported.
+ ///
+ /// To make programmer's lives easier, this library builds on all platforms.
+ /// However, all function calls on unsupported platforms will return
+ /// `io::Error`s.
+ ///
+ /// Note: If you would like compilation to simply fail on unsupported platforms,
+ /// turn of the `unsupported` feature.
+ pub const SUPPORTED_PLATFORM: bool = cfg!(any($($(target_os = $platform),*),*));
+ }
+}
+
+platforms! {
+ "android"; "linux"; "macos" => linux_macos,
+ "freebsd"; "netbsd" => bsd
+}
diff --git a/vendor/xattr/src/sys/unsupported.rs b/vendor/xattr/src/sys/unsupported.rs
new file mode 100644
index 000000000..7eb48a5d4
--- /dev/null
+++ b/vendor/xattr/src/sys/unsupported.rs
@@ -0,0 +1,77 @@
+use std::ffi::{OsStr, OsString};
+use std::io;
+use std::os::unix::io::RawFd;
+use std::path::Path;
+
+use UnsupportedPlatformError;
+
+/// An iterator over a set of extended attributes names.
+#[derive(Clone, Debug)]
+pub struct XAttrs;
+
+impl Iterator for XAttrs {
+ type Item = OsString;
+ fn next(&mut self) -> Option<OsString> {
+ unreachable!("this should never exist")
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ unreachable!("this should never exist")
+ }
+}
+
+pub fn get_fd(_: RawFd, _: &OsStr) -> io::Result<Vec<u8>> {
+ Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnsupportedPlatformError,
+ ))
+}
+
+pub fn set_fd(_: RawFd, _: &OsStr, _: &[u8]) -> io::Result<()> {
+ Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnsupportedPlatformError,
+ ))
+}
+
+pub fn remove_fd(_: RawFd, _: &OsStr) -> io::Result<()> {
+ Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnsupportedPlatformError,
+ ))
+}
+
+pub fn list_fd(_: RawFd) -> io::Result<XAttrs> {
+ Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnsupportedPlatformError,
+ ))
+}
+
+pub fn get_path(_: &Path, _: &OsStr) -> io::Result<Vec<u8>> {
+ Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnsupportedPlatformError,
+ ))
+}
+
+pub fn set_path(_: &Path, _: &OsStr, _: &[u8]) -> io::Result<()> {
+ Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnsupportedPlatformError,
+ ))
+}
+
+pub fn remove_path(_: &Path, _: &OsStr) -> io::Result<()> {
+ Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnsupportedPlatformError,
+ ))
+}
+
+pub fn list_path(_: &Path) -> io::Result<XAttrs> {
+ Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnsupportedPlatformError,
+ ))
+}