symlink/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
10use std::fs;
11use std::io;
12use std::path::Path;
13
14#[cfg(windows)]
15#[path = "windows/mod.rs"]
16mod internal;
17
18#[cfg(any(target_os = "redox", unix))]
19mod 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]
54pub 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]
72pub 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]
90pub 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]
112pub 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]
123pub 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]
135pub fn remove_symlink_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
136 fs::remove_file(path)
137}