1 //! A small, cross-platform crate for creating symlinks.
3 #![cfg_attr(not(any(target_os = "redox", unix, windows)), doc = "**This platform is not Unix, Windows or Redox; symlinks are not available.**")]
5 //! For efficiency, you should prefer to use `symlink_file` or `symlink_dir`—whichever is
6 //! appropriate—rather than `symlink_auto`
8 // It’s generally nicer to produce an empty crate on unsupported platforms than to explode.
16 pub use std
::os
::windows
::fs
::{symlink_file
, symlink_dir
};
17 pub use std
::fs
::remove_dir
as remove_symlink_dir
;
24 pub fn symlink_auto
<P
: AsRef
<Path
>, Q
: AsRef
<Path
>>(src
: P
, dst
: Q
) -> io
::Result
<()> {
25 if fs
::metadata(src
.as_ref())?
.is_dir() {
26 symlink_dir(src
.as_ref(), dst
.as_ref())
28 symlink_file(src
.as_ref(), dst
.as_ref())
32 // Copied from the Rust standard library, src/libstd/sys/windows/fs.rs, because it’s an
33 // implementation detail that isn’t currently exposed in the public interface; I decided to do
34 // it this way rather than depending on the Debug implementation (which likewise could change).
37 Dir
, File
, SymlinkFile
, SymlinkDir
, ReparsePoint
, MountPoint
,
41 pub fn is_symlink_dir(&self) -> bool
{
42 *self == FileType
::SymlinkDir
|| *self == FileType
::MountPoint
47 pub fn remove_symlink_auto
<P
: AsRef
<Path
>>(path
: P
) -> io
::Result
<()> {
48 // We need to know whether it’s wrapping a SymlinkFile or SymlinkDir, but in the interests
49 // of consistency this crucial information is concealed. This is why unsafe transmutation
50 // is necessary: to determine whether it’s a symlink file or a symlink dir.
51 let file_type
= fs
::metadata(path
.as_ref())?
.file_type();
52 let fs_imp_file_type
= unsafe { mem
::transmute
::<fs
::FileType
, FileType
>(file_type
) };
53 if fs_imp_file_type
.is_symlink_dir() {
55 } else if file_type
.is_symlink() {
58 Err(io
::Error
::new(io
::ErrorKind
::InvalidInput
, "path is not a symlink"))
63 #[cfg(any(target_os = "redox", unix))]
65 pub use std
::fs
::remove_file
as remove_symlink_dir
;
66 pub use std
::fs
::remove_file
as remove_symlink_auto
;
67 // Note that this symlink function takes src and dst as &Path rather than as impl AsRef<Path>.
68 // I don’t know why that is, but I think we’ll go with impl AsRef<Path> in our public
69 // functions. Because of this disparity of signature, when I say that things are equivalent to
70 // calling std::os::unix::fs::symlink on Unix, you can see that I’m not being *quite* rigorous.
71 pub use std
::os
::unix
::fs
::{symlink
as symlink_auto
,
72 symlink
as symlink_file
,
73 symlink
as symlink_dir
};
76 /// Create a symlink (non-preferred way).
78 /// On Windows, file and directory symlinks are created by distinct methods; to cope with that,
79 /// this function checks whether the destination is a file or a folder and creates the appropriate
80 /// type of symlink based on that result. Therefore, if the destination does not exist or if you do
81 /// not have permission to fetch its metadata, this will return an error on Windows.
83 /// On Unix platforms there is no distinction, so this isn’t magic: it’s precisely equivalent to
84 /// calling `std::os::unix::fs::symlink`.
86 /// # A note on using this function
88 /// Because this is slightly less efficient and more hazardous on Windows, you should prefer to use
89 /// [`symlink_file`](fn.symlink_file.html) or [`symlink_dir`](fn.symlink_dir.html) instead. Only
90 /// use this if you don’t know or care whether the destination is a file or a directory (but even
91 /// then, you do need to know that it exists).
95 /// An error will be returned if the symlink cannot be created, or—on Windows—if the destination
96 /// does not exist or cannot be read.
97 #[cfg(any(target_os = "redox", unix, windows))]
99 pub fn symlink_auto
<P
: AsRef
<Path
>, Q
: AsRef
<Path
>>(src
: P
, dst
: Q
) -> io
::Result
<()> {
100 internal
::symlink_auto(src
.as_ref(), dst
.as_ref())
103 /// Create a symlink to a file.
105 /// On Windows, this is equivalent to `std::os::windows::fs::symlink_file`. If you call it with a
106 /// directory as the destination, TODO CONSEQUENCES.
108 /// On Unix, this is equivalent to `std::os::unix::fs::symlink`. If you call it with a directory as
109 /// the destination, nothing bad will happen, but you’re ruining your cross-platform technique and
110 /// ruining the point of this crate, so please don’t.
114 /// An error will be returned if the symlink cannot be created.
115 #[cfg(any(target_os = "redox", unix, windows))]
117 pub fn symlink_file
<P
: AsRef
<Path
>, Q
: AsRef
<Path
>>(src
: P
, dst
: Q
) -> io
::Result
<()> {
118 internal
::symlink_file(src
.as_ref(), dst
.as_ref())
121 /// Create a symlink to a directory.
123 /// On Windows, this is equivalent to `std::os::windows::fs::symlink_dir`. If you call it with a
124 /// directory as the destination, TODO CONSEQUENCES.
126 /// On Unix, this is equivalent to `std::os::unix::fs::symlink`. If you call it with a directory as
127 /// the destination, nothing bad will happen, but you’re ruining your cross-platform technique and
128 /// ruining the point of this crate, so please don’t.
132 /// An error will be returned if the symlink cannot be created.
133 #[cfg(any(target_os = "redox", unix, windows))]
135 pub fn symlink_dir
<P
: AsRef
<Path
>, Q
: AsRef
<Path
>>(src
: P
, dst
: Q
) -> io
::Result
<()> {
136 internal
::symlink_dir(src
.as_ref(), dst
.as_ref())
139 /// Remove a symlink (non-preferred way).
141 /// This inspects the path metadata to remove the symlink as a file or directory, whichever is
144 /// # A note on using this function
146 /// Because this is slightly less efficient on Windows, you should prefer to use
147 /// [`remove_symlink_file`](fn.remove_symlink_file.html) or
148 /// [`remove_symlink_dir`](fn.remove_symlink_dir.html) instead. Only use this if you don’t know or
149 /// care whether the destination is a file or a directory (but even then, you do need to know that
154 /// An error will be returned if the symlink cannot be removed.
155 #[cfg(any(target_os = "redox", unix, windows))]
157 pub fn remove_symlink_auto
<P
: AsRef
<Path
>>(path
: P
) -> io
::Result
<()> {
158 internal
::remove_symlink_auto(path
)
161 /// Remove a directory symlink.
163 /// On Windows, this corresponds to `std::fs::remove_dir`.
165 /// On Unix, this corresponds to `std::fs::remove_file`.
166 #[cfg(any(target_os = "redox", unix, windows))]
168 pub fn remove_symlink_dir
<P
: AsRef
<Path
>>(path
: P
) -> io
::Result
<()> {
169 internal
::remove_symlink_dir(path
)
172 /// Remove a file symlink.
174 /// This just calls `std::fs::remove_file`, but the function is provided here to correspond to
175 /// `remove_symlink_dir`.
177 /// On Unix, this corresponds to `std::fs::remove_file`.
178 #[cfg(any(target_os = "redox", unix, windows))]
180 pub fn remove_symlink_file
<P
: AsRef
<Path
>>(path
: P
) -> io
::Result
<()> {
181 fs
::remove_file(path
)