Add ?follow option to Unix.link#1061
Conversation
3f8de51 to
f0f8e1b
Compare
otherlibs/win32unix/symlink.c
Outdated
| DWORD flags = | ||
| Is_block(to_dir) && Bool_val(Field(to_dir, 0)) | ||
| ? SYMBOLIC_LINK_FLAG_DIRECTORY | ||
| : 0; |
There was a problem hiding this comment.
I'll can't do a full review today, but I can say immediately that this is wrong - see otherlibs/win32unix/unix.ml
|
and provide an |
|
Also, some motivation on why we really need to hardlink symlinks would be welcome. |
|
If I'm reading the binding correctly,
Additionally, at least on OS X,
|
|
Why not instead add |
|
madroach (2017/02/23 17:14 -0800):
This allows hardlinking symlinks.
Also fix a bug in win32 symlink stub code, which interpreted an
optional parameter (bool option) as simple bool.
Shouldn't the bug fix be submitted in a different PR so that it can get
integrated separately and cherry-picked in 4.05?
|
|
Concerning the "bug fix" I confirm there is no bug and the fix would break the win32 code. @madroach : if you want to keep this PR up for discussion, please remove the 'bug fix", correct the default behavior of Unix.link, and add a fallback implementation if linkat() is not available. Otherwise we'll close this PR. |
e458097 to
3e99f64
Compare
|
I updated the pull request in the following ways:
On the behavior of link the linux manpage on link(2) says this:
Also http://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html may be of interest. I have no strong preference, but the not dereferencing approach seems saner to me because one could still dereference the symlink with As to why this change is needed:Creating hardlinks of symlinks is error prone:
Therefore the programmer often will need some control on what behaviour he prefers. |
|
Thanks for the revised code, much appreciated. I have two more suggestions based on the discussion above and on the code:
Taken together, this would give a different code logic such as: |
3e99f64 to
c8ce8e2
Compare
|
Thanks for your input. This is indeed the most sensible behaviour. I adapted the code as you suggest, but kept the parsing of the option out of the blocking section because I'm not sure whether access to the option is protected from interference by the garbage collector. |
|
It would be great to have the documentation updated to describe the |
|
documentation added. |
dra27
left a comment
There was a problem hiding this comment.
Sorry to bang on about it, but I'm still unconvinced why this is being done as an optional parameter, and not simply a separate binding as Unix.linkat, given that the new behaviour can only be triggered by specifying the new optional argument.
It also seems potentially unwise, however unlikely it may be for this particular syscall to gain flags, to bind something that is int flags in C effectively with bool in OCaml.
otherlibs/unix/link.c
Outdated
| caml_unix_check_path(path2, "link"); | ||
| p1 = caml_strdup(String_val(path1)); | ||
| p2 = caml_strdup(String_val(path2)); | ||
| ret = |
There was a problem hiding this comment.
Memory is cheap - can we risk having another int flags; rather than confusingly co-opting one called ret? That said, see below...
| : 0; | ||
| caml_enter_blocking_section(); | ||
| ret = link(p1, p2); | ||
| if (follow == Val_int(0) /* None */) |
There was a problem hiding this comment.
FWIW, if (!Is_block(follow)) /* None */?
otherlibs/unix/link.c
Outdated
| ret = link(p1, p2); | ||
| else /* Some bool */ | ||
| # if _XOPEN_VERSION >= 700 || _POSIX_VERSION >= 200809L | ||
| ret = linkat(AT_FDCWD, p1, AT_FDCWD, p2, ret); |
There was a problem hiding this comment.
Why not, instead of ret, just do (Bool_val(Field(follow, 0)) ? AT_SYMLINK_FOLLOW : 0) here, and not need a variable (ret or otherwise)? You already know that follow is a block by this branch.
There was a problem hiding this comment.
Can I safely dereference follow here in the nonblocking section?
There was a problem hiding this comment.
That's a very good point (I don't think the access in the if is correct, therefore, either) - it would be better to have two lots of enter_blocking_section around both link and linkat (which again, begs my previous question of why this isn't just a separate binding).
There was a problem hiding this comment.
The if (follow == Val_int(0)) is correct. It does not dereference follow.
There was a problem hiding this comment.
Indeed. Assuming this version is kept, it's therefore up to you whether to wrap the two syscalls with their own leave/enter_blocking_section or declare a flags variable earlier (my comment about co-opting ret still stands!!)
otherlibs/unix/link.c
Outdated
| # if _XOPEN_VERSION >= 700 || _POSIX_VERSION >= 200809L | ||
| ret = linkat(AT_FDCWD, p1, AT_FDCWD, p2, ret); | ||
| # else | ||
| { ret = -1; errno = ENOSYS } |
There was a problem hiding this comment.
To me, this looks so horribly like some kind of struct initialiser, I'd just move the braces outside the #if...
otherlibs/unix/link.c
Outdated
| if (follow == Val_int(0) /* None */) | ||
| ret = link(p1, p2); | ||
| else /* Some bool */ | ||
| # if _XOPEN_VERSION >= 700 || _POSIX_VERSION >= 200809L |
There was a problem hiding this comment.
RHEL 5 is about to go out of support, but is it definitely OK to be ignoring the glibc < 2.10 version of this check?
There was a problem hiding this comment.
How would that look like?
There was a problem hiding this comment.
Looking here, I think it just means adding || defined(_ATFILE_SOURCE) /* For 2.4 <= glibc < 2.10 */
There was a problem hiding this comment.
ok. I included the change in my tree. But I have to admit I don't understand feature_test_macros(7). Aren't those macros used to request, not check for features?
There was a problem hiding this comment.
Indeed - I'm not certain how this is supposed to work with glibc, as you do not appear to be permitted to check the version of the glibc headers you are compiling. My (quite possibly incorrect) understanding is that if someone is using glibc < 2.10 then they should ensure that -D_ATFILE_SOURCE gets into CFLAGS at configure-time (it's possible that this is something configure itself should determine is required, that's not clear at all).
However, it does seem to me to be OK to test it here.
|
What about this interface? type link_flag =
|L_FOLLOW
val fd_cwd:dir_handle
val linkat ~flags:link_flag array ->
?src_dir:dir_handle -> ~src:string ->
?dst_dir:dir_handle -> ~dst:string -> unitBut on the other hand the |
|
I agree that the I would push for the separate interface (if a user - such as yourself - needs the version with optional argument, it is easy to define) but with the following changes:
|
|
I think this PR is getting out of hand and turning into a design discussion for a much bigger extension than initially offered. In particular, if |
|
I updated the pull request to include most suggestions by dra27. According to CreateHardLink the only behavior on win32 is following hardlinks. |
|
Since we are talking about the |
4cdc229 to
e66d41f
Compare
|
@dra27 @xavierleroy can we get consensus on whether to include this? |
| Is_block(follow) && Bool_val(Field(follow, 0)) /* Some true */ | ||
| ? AT_SYMLINK_FOLLOW | ||
| : 0; | ||
| caml_unix_check_path(path1, "link"); |
There was a problem hiding this comment.
This int flags computation should be moved to the else part below, and protected by the #if linkat_is_available, since AT_SYMLINK_FOLLOW may not be defined.
|
What can I say?
|
|
@madroach if you fix the |
41701de to
67e4f2f
Compare
|
done and rebased. |
damiendoligez
left a comment
There was a problem hiding this comment.
Fix Changes and we're good.
Changes
Outdated
| now uses nanosleep(1) for enabling better preemption. | ||
| (b) Thread.delay is now an alias for Unix.sleepf. | ||
|
|
||
| - Add ?follow parameter to Unix.link. This allows hardlinking symlinks. |
There was a problem hiding this comment.
You need to add the GPR number, move the entry to the right place (not under 4.07) add the real names of everyone involved, and cut your lines to 80 characters, as documented in https://github.com/ocaml/ocaml/blob/trunk/CONTRIBUTING.md#changelog
Changes
Outdated
| (Leo White, Xavier Clerc, report by Alex, review by Gabriel Scherer | ||
| and Pierre Chambart) | ||
|
|
||
| ### Tools: |
There was a problem hiding this comment.
Looks like you added this by mistake.
This allows hardlinking symlinks.
|
fixed |
|
The CI reports failing macos-10.3 and freebsd builds with the same error: |
|
Seems like I used the feature test macros in the wrong way. |
|
It may be a missing |
|
A fix is proposed in #1862 |
This allows hardlinking symlinks.
Also fix a bug in win32 symlink stub code, which interpreted an
optional parameter (bool option) as simple bool. [EDIT: there was no bug, in fact]