a03d15b303aa5b8a203a246a22cc6ff942bac272
[symlink] / src / lib.rs
1 //! A small, cross-platform crate for creating symlinks.
2 //!
3 #![cfg_attr(not(any(target_os = "redox", unix, windows)), doc = "**This platform is not Unix, Windows or Redox; symlinks are not available.**")]
4 //!
5 //! For efficiency, you should prefer to use `symlink_file` or `symlink_dir`—whichever is
6 //! appropriate—rather than `symlink_auto`
7
8 // It’s generally nicer to produce an empty crate on unsupported platforms than to explode.
9
10 use std::fs;
11 use std::io;
12 use std::path::Path;
13
14 #[cfg(windows)]
15 #[path = "windows/mod.rs"]
16 mod internal;
17
18 #[cfg(any(target_os = "redox", unix))]
19 mod internal {
20 pub use std::fs::remove_file as remove_symlink_dir;
21 pub use std::fs::remove_file as remove_symlink_auto;
22 // Note that this symlink function takes src and dst as &Path rather than as impl AsRef<Path>.
23 // I don’t know why that is, but I think we’ll go with impl AsRef<Path> in our public
24 // functions. Because of this disparity of signature, when I say that things are equivalent to
25 // calling std::os::unix::fs::symlink on Unix, you can see that I’m not being *quite* rigorous.
26 pub use std::os::unix::fs::{symlink as symlink_auto,
27 symlink as symlink_file,
28 symlink as symlink_dir};
29 }
30
31 /// Create a symlink (non-preferred way).
32 ///
33 /// On Windows, file and directory symlinks are created by distinct methods; to cope with that,
34 /// this function checks whether the destination is a file or a folder and creates the appropriate
35 /// type of symlink based on that result. Therefore, if the destination does not exist or if you do
36 /// not have permission to fetch its metadata, this will return an error on Windows.
37 ///
38 /// On Unix platforms there is no distinction, so this isn’t magic: it’s precisely equivalent to
39 /// calling `std::os::unix::fs::symlink`.
40 ///
41 /// # A note on using this function
42 ///
43 /// Because this is slightly less efficient and more hazardous on Windows, you should prefer to use
44 /// [`symlink_file`](fn.symlink_file.html) or [`symlink_dir`](fn.symlink_dir.html) instead. Only
45 /// use this if you don’t know or care whether the destination is a file or a directory (but even
46 /// then, you do need to know that it exists).
47 ///
48 /// # Errors
49 ///
50 /// An error will be returned if the symlink cannot be created, or—on Windows—if the destination
51 /// does not exist or cannot be read.
52 #[cfg(any(target_os = "redox", unix, windows))]
53 #[inline]
54 pub fn symlink_auto<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
55 internal::symlink_auto(src.as_ref(), dst.as_ref())
56 }
57
58 /// Create a symlink to a file.
59 ///
60 /// On Windows, this is equivalent to `std::os::windows::fs::symlink_file`. If you call it with a
61 /// directory as the destination, TODO CONSEQUENCES.
62 ///
63 /// On Unix, this is equivalent to `std::os::unix::fs::symlink`. If you call it with a directory as
64 /// the destination, nothing bad will happen, but you’re ruining your cross-platform technique and
65 /// ruining the point of this crate, so please don’t.
66 ///
67 /// # Errors
68 ///
69 /// An error will be returned if the symlink cannot be created.
70 #[cfg(any(target_os = "redox", unix, windows))]
71 #[inline]
72 pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
73 internal::symlink_file(src.as_ref(), dst.as_ref())
74 }
75
76 /// Create a symlink to a directory.
77 ///
78 /// On Windows, this is equivalent to `std::os::windows::fs::symlink_dir`. If you call it with a
79 /// directory as the destination, TODO CONSEQUENCES.
80 ///
81 /// On Unix, this is equivalent to `std::os::unix::fs::symlink`. If you call it with a directory as
82 /// the destination, nothing bad will happen, but you’re ruining your cross-platform technique and
83 /// ruining the point of this crate, so please don’t.
84 ///
85 /// # Errors
86 ///
87 /// An error will be returned if the symlink cannot be created.
88 #[cfg(any(target_os = "redox", unix, windows))]
89 #[inline]
90 pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
91 internal::symlink_dir(src.as_ref(), dst.as_ref())
92 }
93
94 /// Remove a symlink (non-preferred way).
95 ///
96 /// This inspects the path metadata to remove the symlink as a file or directory, whichever is
97 /// necessary.
98 ///
99 /// # A note on using this function
100 ///
101 /// Because this is slightly less efficient on Windows, you should prefer to use
102 /// [`remove_symlink_file`](fn.remove_symlink_file.html) or
103 /// [`remove_symlink_dir`](fn.remove_symlink_dir.html) instead. Only use this if you don’t know or
104 /// care whether the destination is a file or a directory (but even then, you do need to know that
105 /// it exists).
106 ///
107 /// # Errors
108 ///
109 /// An error will be returned if the symlink cannot be removed.
110 #[cfg(any(target_os = "redox", unix, windows))]
111 #[inline]
112 pub fn remove_symlink_auto<P: AsRef<Path>>(path: P) -> io::Result<()> {
113 internal::remove_symlink_auto(path)
114 }
115
116 /// Remove a directory symlink.
117 ///
118 /// On Windows, this corresponds to `std::fs::remove_dir`.
119 ///
120 /// On Unix, this corresponds to `std::fs::remove_file`.
121 #[cfg(any(target_os = "redox", unix, windows))]
122 #[inline]
123 pub fn remove_symlink_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
124 internal::remove_symlink_dir(path)
125 }
126
127 /// Remove a file symlink.
128 ///
129 /// This just calls `std::fs::remove_file`, but the function is provided here to correspond to
130 /// `remove_symlink_dir`.
131 ///
132 /// On Unix, this corresponds to `std::fs::remove_file`.
133 #[cfg(any(target_os = "redox", unix, windows))]
134 #[inline]
135 pub fn remove_symlink_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
136 fs::remove_file(path)
137 }