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

Try removing the RO bit when unlinking files on Windows #849

Conversation

MisterDA
Copy link
Contributor

On Windows, some programs may set the read-only bit on files. For
instance, git marks its index files as read-only. Calling
Unix.unlink on such a file will result in an
Unix.Unix_error(Unix.EACCES, "unlink", _) exception.

Lwt_io.with_temp_dir creates a temporary directory in which it is
possible that a read-only file is created. In such case, the
delete_recursively function will not be able to clean the temporary
directory and will also raise an exception.

This patch allows by setting the file writable (removing the RO bit)
to delete the file.

This code was copied from Dune:
https://github.com/ocaml/dune/blob/ed361ebc4f37a81d3e6ffc905b0d45f61bc17e9c/otherlibs/stdune-unstable/fpath.ml#L74-L88

src/unix/lwt_io.ml Outdated Show resolved Hide resolved
On Windows, some programs may set the read-only bit on files. For
instance, git marks its index files as read-only. Calling
`Unix.unlink` on such a file will result in an
`Unix.Unix_error(Unix.EACCES, "unlink", _)` exception.

`Lwt_io.with_temp_dir` creates a temporary directory in which it is
possible that a read-only file is created. In such case, the
`delete_recursively` function will not be able to clean the temporary
directory and will also raise an exception.

This patch allows by setting the file writable (removing the RO bit)
to delete the file.

This code was copied from Dune:
https://github.com/ocaml/dune/blob/ed361ebc4f37a81d3e6ffc905b0d45f61bc17e9c/otherlibs/stdune-unstable/fpath.ml#L74-L88
@MisterDA MisterDA force-pushed the windows-chmod-readonly-delete-recursively branch from 817dd12 to 5fb5215 Compare April 27, 2021 10:52
Copy link
Collaborator

@avsm avsm left a comment

Choose a reason for hiding this comment

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

This lgtm!

Lwt_unix.chmod fn 0o666 >>= fun () ->
Lwt_unix.unlink fn
with
| _ -> raise e)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe it complicates things a bit but is it worth resetting the mod to the original setting in case the second unlink fails?

It does complicate the code to do so (read stats before chmod, catch exceptions of unlink specifically,restore perms before reraising), but at least it'd be more likely to leave the file in its original state.


In addition, I think you should be using Lwt.catch to handle exceptions here. (Although I might be missing something so please don't hesitate to let me know if there's a reason that try-with is appropriate here specifically.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I applied the two suggestions. The original permissions are fetched with lstat, if I'm not mistaken that's the correct syscall in our case.
I hadn't thought about using Lwt.catch, I converted the code to it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I noticed that you made a subtle change and I'm not sure if it's on purpose: You now reraise the exception from the second unlink whereas you previously reraised the original exception.

I don't think one is necessary better than the other (in the specific case of a system programming library for windows), but I'd rather the semantic was not chosen accidentally. Is the change intended or not?

@MisterDA
Copy link
Contributor Author

MisterDA commented Apr 30, 2021 via email

@raphael-proust raphael-proust merged commit 9cbf3a9 into ocsigen:master May 3, 2021
@MisterDA
Copy link
Contributor Author

MisterDA commented May 3, 2021

@raphael-proust Thanks for merging, but I didn't have the time to apply the change to re-raise the first exception!
MisterDA@8ebc9cc

raphael-proust pushed a commit that referenced this pull request May 25, 2021
* Try removing the RO bit when unlinking files on Windows

On Windows, some programs may set the read-only bit on files. For
instance, git marks its index files as read-only. Calling
`Unix.unlink` on such a file will result in an
`Unix.Unix_error(Unix.EACCES, "unlink", _)` exception.

`Lwt_io.with_temp_dir` creates a temporary directory in which it is
possible that a read-only file is created. In such case, the
`delete_recursively` function will not be able to clean the temporary
directory and will also raise an exception.

This patch allows by setting the file writable (removing the RO bit)
to delete the file.

This code was copied from Dune:
https://github.com/ocaml/dune/blob/ed361ebc4f37a81d3e6ffc905b0d45f61bc17e9c/otherlibs/stdune-unstable/fpath.ml#L74-L88

* Use Lwt.catch instead of try-with and restore perms if unlink fails
raphael-proust added a commit that referenced this pull request May 27, 2021
raphael-proust added a commit that referenced this pull request May 27, 2021
@raphael-proust raphael-proust added this to the 5.4.1 milestone May 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants