Skip to content

Commit aa0b8ee

Browse files
committed
Move symlink to OS specific modules
As described in the RFC, the differences in how creating symlinks works differs sufficiently between Unix and Windows that trying to have a cross-platform API is a compability hazard.
1 parent e8bd990 commit aa0b8ee

File tree

1 file changed

+95
-17
lines changed

1 file changed

+95
-17
lines changed

text/0000-rename-soft-link-to-symlink.md

Lines changed: 95 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,51 @@
55

66
# Summary
77

8-
Rename `std::fs::soft_link` to `std::fs::symlink` and provide a deprecated
9-
`std::fs::soft_link` alias.
8+
Rename `std::fs::soft_link` into platform-specific versions:
9+
`std::os::unix::fs::symlink`, `std::os::windows::fs::symlink_file`, and
10+
`std::os::windows::fs::symlink_dir`.
1011

1112
# Motivation
1213

13-
At some point in the split up version of rust-lang/rfcs#517,
14-
`std::fs::symlink` was renamed to `sym_link` and then to `soft_link`.
14+
Windows Vista introduced the ability to create symbolic links, in order to
15+
[provide compatibility with applications ported from Unix](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680%28v=vs.85%29.aspx):
16+
17+
> Symbolic links are designed to aid in migration and application
18+
> compatibility with UNIX operating systems. Microsoft has implemented its
19+
> symbolic links to function just like UNIX links.
20+
21+
However, symbolic links on Windows behave differently enough than symbolic
22+
links on Unix family operating systems that you can't, in general, assume that
23+
code that works on one will work on the other. On Unix family operating
24+
systems, a symbolic link may refer to either a directory or a file, and which
25+
one is determined when it is resolved to an actual file. On Windows, you must
26+
specify at the time of creation whether a symbolic link refers to a file or
27+
directory.
28+
29+
In addition, an arbitrary process on Windows is not allowed to create a
30+
symlink; you need to have [particular privileges][1] in order to be able to do
31+
so; while on Unix, ordinary users can create symlinks, and any additional
32+
security policy (such as [Grsecurity][2]) generally restricts
33+
whether applications follow symlinks, not whether a user can create them.
34+
35+
[1]: (https://technet.microsoft.com/en-us/library/cc766301%28WS.10%29.aspx) in order to be able to do
36+
[2]: https://en.wikibooks.org/wiki/Grsecurity/Appendix/Grsecurity_and_PaX_Configuration_Options#Linking_restrictions
37+
38+
Thus, there needs to be a way to distinguish between the two operations on
39+
Windows, but that distinction is meaningless on Unix, and any code that deals
40+
with symlinks on Windows will need to depend on having appropriate privilege
41+
or have some way of obtaining appropriate privilege, which is all quite
42+
platform specific.
43+
44+
These two facts mean that it is unlikely that arbitrary code dealing with
45+
symbolic links will be portable between Windows and Unix. Rather than trying
46+
to support both under one API, it would be better to provide platform specific
47+
APIs, making it much more clear upon inspection where portability issues may
48+
arise.
49+
50+
In addition, the current name `soft_link` is fairly non-standard. At some
51+
point in the split up version of rust-lang/rfcs#517, `std::fs::symlink` was
52+
renamed to `sym_link` and then to `soft_link`.
1553

1654
The new name is somewhat surprising and can be difficult to find. After a
1755
poll of a number of different platforms and languages, every one appears to
@@ -44,14 +82,12 @@ of Rust.
4482
The name `soft_link` was chosen to be shorter than `symbolic_link`, but
4583
without using Unix specific jargon like `symlink`, to not give undue weight to
4684
one platform over the other. However, based on the evidence above it doesn't
47-
have any precedent as a formal name for the concept or API. Furthermore,
48-
symbolic links themselves are a conept that were only relatively recently
49-
(2007, with Windows Vista) introduced to Windows, with the [main motivator
50-
being Unix compatibility](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680%28v=vs.85%29.aspx):
85+
have any precedent as a formal name for the concept or API.
5186

52-
> Symbolic links are designed to aid in migration and application
53-
> compatibility with UNIX operating systems. Microsoft has implemented its
54-
> symbolic links to function just like UNIX links.
87+
Furthermore, even on Windows, the name for the [reparse point tag used][3] to
88+
represent symbolic links is `IO_REPARSE_TAG_SYMLINK`.
89+
90+
[3]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365511%28v=vs.85%29.aspx
5591

5692
If you do a Google search for "[windows symbolic link](https://www.google.com/search?q=windows+symbolic+link&ie=utf-8&oe=utf-8)" or "[windows soft link](https://www.google.com/search?q=windows+soft+link&ie=utf-8&oe=utf-8)",
5793
many of the documents you find start using "symlink" after introducing the
@@ -60,9 +96,14 @@ among Windows developers and users.
6096

6197
# Detailed design
6298

63-
Rename `std::fs::soft_link` to `std::fs::symlink`, and provide a deprecated
64-
`std::fs::soft_link` wrapper for backwards compatibility. Update the
65-
documentaiton to use "symbolic link" in prose, rather than "soft link".
99+
Move `std::fs::soft_link` to `std::os::unix::fs::symlink`, and create
100+
`std::os::windows::fs::symlink_file` and `std::os::windows::fs::symlink_dir`
101+
that call `CreateSymbolicLink` with the appropriate arguments.
102+
103+
Keep a deprecated compatibility wrapper `std::fs::soft_link` which wraps
104+
`std::os::unix::fs::symlink` or `std::os::windows::fs::symlink_file`,
105+
depending on the platform (as that is the current behavior of
106+
`std::fs::softlink`, to create a file symbolic link).
66107

67108
# Drawbacks
68109

@@ -71,7 +112,27 @@ around.
71112

72113
# Alternatives
73114

74-
Other choices for the name would be:
115+
* Have a cross platform `symlink` and `symlink_dir`, that do the same thing on
116+
Unix but differ on Windows. This has the drawback of invisible
117+
compatibility hazards; code that works on Unix using `symlink` may fail
118+
silently on Windows, as creating the wrong type of symlink may succeed but
119+
it may not be interpreted properly once a destination file of the other type
120+
is created.
121+
* Have a cross platform `symlink` that detects the type of the destination
122+
on Windows. This is not always possible as it's valid to create dangling
123+
symbolic links.
124+
* Have `symlink`, `symlink_dir`, and `symlink_file` all cross-platform, where
125+
the first dispatches based on the destination file type, and the latter two
126+
panic if called with the wrong destination file type. Again, this is not
127+
always possible as it's valid to create dangling symbolic links.
128+
* Rather than having two separate functions on Windows, you could have a
129+
separate parameter on Windows to specify the type of link to create;
130+
`symlink("a", "b", FILE_SYMLINK)` vs `symlink("a", "b", DIR_SYMLINK)`.
131+
However, having a `symlink` that had different arity on Unix and Windows
132+
would likely be confusing, and since there are only the two possible
133+
choices, simply having two functions seems like a much simpler solution.
134+
135+
Other choices for the naming convention would be:
75136

76137
* The status quo, `soft_link`
77138
* The original proposal from rust-lang/rfcs#517, `sym_link`
@@ -83,12 +144,29 @@ Unix. It is a classic compromise, that makes everyone unhappy.
83144
`sym_link` is slightly more consistent with the complementary `hard_link`
84145
function, and treating "sym link" as two separate words has some precedent in
85146
two of the Windows-targetted APIs, Delphi and some of the PowerShell cmdlets
86-
observed.
147+
observed. However, I have not found any other snake case API that uses that,
148+
and only a couple of Windows-specific APIs that use it in camel case; most
149+
usage prefers the single word "symlink" to the two word "sym link" as the
150+
abbreviation.
87151

88152
The full name `symbolic_link`, is a bit long and cumbersome compared to most
89153
of the rest of the API, but is explicit and is the term used in prose to
90154
describe the concept everywhere, so shouldn't emphasize any one platform over
91-
the other.
155+
the other. However, unlike all other operations for creating a file or
156+
directory (`open`, `create`, `create_dir`, etc), it is a noun, not a verb.
157+
When used as a verb, it would be called "symbolically link", but that sounds
158+
quite odd in the context of an API: `symbolically_link("a", "b")`. "symlink",
159+
on the other hand, can act as either a noun or a verb.
160+
161+
It would be possible to prefix any of the forms above that read as a noun with
162+
`create_`, such as `create_symlink`, `create_sym_link`,
163+
`create_symbolic_link`. This adds further to the verbosity, though it is
164+
consisted with `create_dir`; you would probably need to also rename
165+
`hard_link` to `create_hard_link` for consistency, and this seems like a lot
166+
of churn and extra verbosity for not much benefit, as `symlink` and
167+
`hard_link` already act as verbs on their own. If you picked this, then the
168+
Windows versions would need to be named `create_file_symlink` and
169+
`create_dir_symlink` (or the variations with `sym_link` or `symbolic_link`).
92170

93171
# Unresolved questions
94172

0 commit comments

Comments
 (0)