Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate std::fs::soft_link in favor of platform-specific versions #24222

Merged
merged 1 commit into from
Apr 22, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions src/libstd/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
/// Given a path, query the file system to get information about a file,
/// directory, etc.
///
/// This function will traverse soft links to query information about the
/// This function will traverse symbolic links to query information about the
/// destination file.
///
/// # Examples
Expand Down Expand Up @@ -814,9 +814,13 @@ pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<(
fs_imp::link(src.as_ref(), dst.as_ref())
}

/// Creates a new soft link on the filesystem.
/// Creates a new symbolic link on the filesystem.
///
/// The `dst` path will be a soft link pointing to the `src` path.
/// The `dst` path will be a symbolic link pointing to the `src` path.
/// On Windows, this will be a file symlink, not a directory symlink;
/// for this reason, the platform-specific `std::os::unix::fs::symlink`
/// and `std::os::windows::fs::{symlink_file, symlink_dir}` should be
/// used instead to make the intent explicit.
///
/// # Examples
///
Expand All @@ -828,17 +832,20 @@ pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<(
/// # Ok(())
/// # }
/// ```
#[deprecated(since = "1.0.0",
reason = "replaced with std::os::unix::fs::symlink and \
std::os::windows::fs::{symlink_file, symlink_dir}")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
fs_imp::symlink(src.as_ref(), dst.as_ref())
}

/// Reads a soft link, returning the file that the link points to.
/// Reads a symbolic link, returning the file that the link points to.
///
/// # Errors
///
/// This function will return an error on failure. Failure conditions include
/// reading a file that does not exist or reading a file that is not a soft
/// reading a file that does not exist or reading a file that is not a symbolic
/// link.
///
/// # Examples
Expand Down Expand Up @@ -931,8 +938,8 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
/// Removes a directory at this path, after removing all its contents. Use
/// carefully!
///
/// This function does **not** follow soft links and it will simply remove the
/// soft link itself.
/// This function does **not** follow symbolic links and it will simply remove the
/// symbolic link itself.
///
/// # Errors
///
Expand Down
34 changes: 34 additions & 0 deletions src/libstd/sys/unix/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,12 @@ pub mod ffi {
#[unstable(feature = "fs_ext",
reason = "may want a more useful mode abstraction")]
pub mod fs {
use sys;
use sys_common::{FromInner, AsInner, AsInnerMut};
use fs::{Permissions, OpenOptions};
use path::Path;
use convert::AsRef;
use io;

/// Unix-specific extensions to `Permissions`
pub trait PermissionsExt {
Expand Down Expand Up @@ -220,6 +224,36 @@ pub mod fs {
self.as_inner_mut().mode(mode); self
}
}

/// Creates a new symbolic link on the filesystem.
///
/// The `dst` path will be a symbolic link pointing to the `src` path.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These docs are the ones that primarily show up (because our doc builders are linux), so could you expand this a bit to include the information about Windows as well? Just something along the lines of "If you're on windows...".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also add some notes about how windows requires a special permission to create symlinks? Otherwise this all looks great to me!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, added a brief note to that effect. I was a little hard to summarize the situation without a very verbose explanation, so I just made sure to include the name of the specific privilege required that allows you to find the explanation on StackOverflow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks!

///
/// # Note
///
/// On Windows, you must specify whether a symbolic link points to a file
/// or directory. Use `os::windows::fs::symlink_file` to create a
/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
/// symbolic link to a directory. Additionally, the process must have
/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
/// symbolic link.
///
/// # Examples
///
/// ```
/// #![feature(fs_ext)]
/// use std::os::unix::fs;
///
/// # fn foo() -> std::io::Result<()> {
/// try!(fs::symlink("a.txt", "b.txt"));
/// # Ok(())
/// # }
/// ```
pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
{
sys::fs2::symlink(src.as_ref(), dst.as_ref())
}

}

////////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 2 additions & 0 deletions src/libstd/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
pub const FSCTL_GET_REPARSE_POINT: libc::DWORD = 0x900a8;
pub const IO_REPARSE_TAG_SYMLINK: libc::DWORD = 0xa000000c;

pub const SYMBOLIC_LINK_FLAG_DIRECTORY: libc::DWORD = 0x1;

// Note that these are not actually HANDLEs, just values to pass to GetStdHandle
pub const STD_INPUT_HANDLE: libc::DWORD = -10i32 as libc::DWORD;
pub const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD;
Expand Down
48 changes: 48 additions & 0 deletions src/libstd/sys/windows/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,11 @@ pub mod ffi {
#[unstable(feature = "fs_ext", reason = "may require more thought/methods")]
pub mod fs {
use fs::OpenOptions;
use sys;
use sys_common::AsInnerMut;
use path::Path;
use convert::AsRef;
use io;

/// Windows-specific extensions to `OpenOptions`
pub trait OpenOptionsExt {
Expand Down Expand Up @@ -235,6 +239,50 @@ pub mod fs {
self.as_inner_mut().share_mode(access); self
}
}

/// Creates a new file symbolic link on the filesystem.
///
/// The `dst` path will be a file symbolic link pointing to the `src`
/// path.
///
/// # Examples
///
/// ```ignore
/// #![feature(fs_ext)]
/// use std::os::windows::fs;
///
/// # fn foo() -> std::io::Result<()> {
/// try!(fs::symlink_file("a.txt", "b.txt"));
/// # Ok(())
/// # }
/// ```
pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
-> io::Result<()>
{
sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), false)
}

/// Creates a new directory symlink on the filesystem.
///
/// The `dst` path will be a directory symbolic link pointing to the `src`
/// path.
///
/// # Examples
///
/// ```ignore
/// #![feature(fs_ext)]
/// use std::os::windows::fs;
///
/// # fn foo() -> std::io::Result<()> {
/// try!(fs::symlink_file("a", "b"));
/// # Ok(())
/// # }
/// ```
pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>> (src: P, dst: Q)
-> io::Result<()>
{
sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), true)
}
}

/// A prelude for conveniently writing platform-specific code.
Expand Down
7 changes: 6 additions & 1 deletion src/libstd/sys/windows/fs2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,11 +402,16 @@ pub fn readlink(p: &Path) -> io::Result<PathBuf> {
}

pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
symlink_inner(src, dst, false)
}

pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
use sys::c::compat::kernel32::CreateSymbolicLinkW;
let src = to_utf16(src);
let dst = to_utf16(dst);
let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 };
try!(cvt(unsafe {
CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), 0) as libc::BOOL
CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as libc::BOOL
}));
Ok(())
}
Expand Down