1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*!
Library for working with NTFS junctions.

Junction Points are a little known NTFS v5+ feature roughly equivalent to Unix
directory symbolic links.

They are supported in Windows 2000 and onwards, where a directory
serves as a symbolic link to another directory on the computer. For example,
if the directory `D:\SYMLINK` specified `C:\WINNT\SYSTEM32` as its target, then
an application accessing `D:\SYMLINK\DRIVERS` would in reality be accessing
`C:\WINNT\SYSTEM32\DRIVERS`.
*/
#![doc(html_root_url = "https://docs.rs/junction/~1")]
#![cfg(windows)]
#![deny(rust_2018_idioms)]

mod internals;

#[cfg(test)]
mod tests;

use std::io;
use std::path::{Path, PathBuf};

/// Creates a junction point from the specified directory to the specified target directory.
///
/// N.B. Only works on NTFS.
///
/// # Error
///
/// This function may error if the `junction` path already exists.
///
/// # Example
///
/// ```rust
/// use std::io;
/// use std::path::Path;
/// # use std::fs;
/// # use junction::create;
/// fn main() -> io::Result<()> {
///     let tmpdir = tempfile::tempdir()?;
///     let target = tmpdir.path().join("target");
///     let junction = tmpdir.path().join("junction");
///     # fs::create_dir_all(&target)?;
///     create(&target, &junction)
/// }
/// ```
pub fn create<P, Q>(target: P, junction: Q) -> io::Result<()>
where
    P: AsRef<Path>,
    Q: AsRef<Path>,
{
    internals::create(target.as_ref(), junction.as_ref())
}

/// Deletes a `junction` reparse point from the specified file or directory.
///
/// N.B. Only works on NTFS.
///
/// This function delete the junction point only, leaving the target directory
/// and its content as is. It does nothing if the `junction` point does not exist.
///
/// # Example
///
/// ```rust
/// use std::io;
/// use std::path::Path;
/// # use std::fs;
/// # use junction::{create, delete};
/// fn main() -> io::Result<()> {
///     let tmpdir = tempfile::tempdir()?;
///     let target = tmpdir.path().join("target");
///     let junction = tmpdir.path().join("junction");
///     # fs::create_dir_all(&target)?;
///     create(&target, &junction)?;
///     delete(&junction)
/// }
/// ```
pub fn delete<P: AsRef<Path>>(junction: P) -> io::Result<()> {
    internals::delete(junction.as_ref())
}

/// Determines whether the specified path exists and refers to a junction point.
///
/// # Example
///
/// ```rust
/// use std::io;
/// # use junction::exists;
/// fn main() -> io::Result<()> {
///     # #[cfg(feature = "unstable_admin")]
///     assert!(exists(r"C:\Users\Default User")?);
///     Ok(())
/// }
/// ```
pub fn exists<P: AsRef<Path>>(junction: P) -> io::Result<bool> {
    internals::exists(junction.as_ref())
}

/// Gets the target of the specified junction point.
///
/// N.B. Only works on NTFS.
///
/// # Example
///
/// ```rust
/// use std::io;
/// # use junction::get_target;
/// fn main() -> io::Result<()> {
///     # #[cfg(feature = "unstable_admin")]
///     assert_eq!(get_target(r"C:\Users\Default User")?.to_str(), Some(r"C:\Users\Default"));
///     Ok(())
/// }
/// ```
pub fn get_target<P: AsRef<Path>>(junction: P) -> io::Result<PathBuf> {
    internals::get_target(junction.as_ref())
}