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

Implementing the chmod support #772

Closed
wants to merge 68 commits into from

Conversation

webbunivAdmin
Copy link

@webbunivAdmin webbunivAdmin commented Oct 24, 2024

Add chmod Support to Eio

This PR implements support for changing file permissions using the chmod operation in the Eio library.
#764

Key Changes:

  • Added chmod function that allows setting file permissions on a target resource:
    • Parameters:
      • ~follow: Determines whether to follow symlinks.
      • ~perm: Specifies the permission bits to set.
      • t: The target file or directory.
  • Exception Handling:
    • Exceptions are handled to provide robust error reporting.
    • Context-aware re-raising of exceptions in case of failure for better debugging.
  • Seamless Integration with Eio’s resource abstraction, supporting various permission modes.

Tests:

Copy link
Collaborator

@patricoferris patricoferris left a comment

Choose a reason for hiding this comment

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

Thanks @webbunivAdmin !

For future reference, it would be good to correctly attribute code to the original author. I believe most of this was from the branch I pointed to. You could have committed using co-authored-by or by cherry-picking from my branch.

I think we're going to need some tests here too, similar to those in the symlink PR

Copy link
Collaborator

@patricoferris patricoferris left a comment

Choose a reason for hiding this comment

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

Also seems to be a tmp/test_file that shouldn't be committed.

let permissions = get_permissions (Eio.Path.native_exn file_path) env in
Printf.printf "Permissions: %o\n" permissions;

Eio.Path.chmod ~follow:true ~perm:0o600 file_path;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we could remove this example and make the code a test in tests/fs.md. Also it would be good to change the permissions to something other that the same permissions used to create the file, that way we can see chmod working.

Copy link
Collaborator

@patricoferris patricoferris left a comment

Choose a reason for hiding this comment

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

Thanks @webbunivAdmin -- getting there :))

tests/fs.md Outdated
@@ -18,7 +18,6 @@ open Eio.Std
let ( / ) = Path.( / )

let run ?clear:(paths = []) fn =
Eio_main.run @@ fun env ->
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why did you remove this @webbunivAdmin ? It is very important as it is the effect handler for Eio code. Without this none of this tests will work.

@@ -1011,3 +1017,23 @@ Exception: Failure "Simulated error".
+"/" / "" = "/"
- : unit = ()
```

```ocaml
Copy link
Collaborator

Choose a reason for hiding this comment

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

To run the test make sure you run dune runtest and dune promote the output back to this file.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This still holds true.

@webbunivAdmin
Copy link
Author

@patricoferris for checkout for the new tests have written

1 similar comment
@webbunivAdmin
Copy link
Author

@patricoferris for checkout for the new tests have written

@patricoferris
Copy link
Collaborator

Hey @webbunivAdmin,

A few notes from me here. Firstly, in terms of co-authoring, you only need to add this to your commits that are indeed co-authored by me. Everything after the initial commit is your own work and need not have co-authored on them.

Secondly, I do wonder what these pushes of update fs.md are for? Do you not have the code building and running locally to be able to run dune runtest to see if it is working before pushing. It is also possible to undo commits on your branch:

git reset --hard HEAD~n        # Reset head backwards n commits, dropping the commits
edit edit edit
git add foo                    # add new changes
git commit -m "Useful message" # commit them
git push -f                    # force push to your branch to undo the commits

Some of the failures right now are not due to the code (just flakey tests/CI). However, the latest code still has no test of the chmod feature.

@@ -1011,3 +1017,23 @@ Exception: Failure "Simulated error".
+"/" / "" = "/"
- : unit = ()
```

```ocaml
Copy link
Collaborator

Choose a reason for hiding this comment

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

This still holds true.


let file_path = cwd / "test-file" in
Path.save ~create:(`Exclusive 0o644) file_path "test data";
traceln "+create <cwd:test-file> with permissions 0o644 -> ok";
Copy link
Collaborator

Choose a reason for hiding this comment

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

The idea of these tests is that the try_x variant of all of the Path functions does two things. (1) it invokes the function it is named after e.g. chmod and (2) it prints something using traceln that we can then inspect to see what it did.


let file_path = cwd / "test-file" in
Path.save ~create:(`Exclusive 0o644) file_path "test data";
traceln "+create <cwd:test-file> with permissions 0o644 -> ok";
Copy link
Collaborator

Choose a reason for hiding this comment

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

So we don't need this.

Suggested change
traceln "+create <cwd:test-file> with permissions 0o644 -> ok";

tests/fs.md Outdated
traceln "+<cwd:test-file> initial permissions = %o" initial_perm;
assert (initial_perm = 0o644);

Path.chmod ~follow:true ~perm:0o400 file_path;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I envisage this code to look something like:

try_chmod ~follow:true ~perm:0o400 file_path;
try_stat ~info_type:`Perm file_path;

Note:

  1. It uses try_chmod which prints the information about the execution of chmod.
  2. It uses try_stat to print information about the file, I've modified it slightly so that try_stat would look something like
-let try_stat path =
+let try_stat ?(info_type=`Kind) path =
   let stat ~follow =
-    match Eio.Path.stat ~follow path with
-    | info -> Fmt.str "@[<h>%a@]" Eio.File.Stat.pp_kind info.kind
+    match Eio.Path.stat ~follow path, info_type with
+    | info, `Perm -> Fmt.str "@[<h>%o@]" info.perm
+    | info, `Kind -> Fmt.str "@[<h>%a@]" Eio.File.Stat.pp_kind info.kind
     | exception Eio.Io (e, _) -> Fmt.str "@[<h>%a@]" Eio.Exn.pp_err e
   in

@@ -176,6 +181,7 @@ end = struct
with_parent_dir t path @@ fun dirfd path ->
Err.run (Low_level.symlink ~link_to dirfd) path


Copy link
Collaborator

Choose a reason for hiding this comment

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

Make sure your commits don't have unnecessary changes like this newline.

@@ -89,6 +89,11 @@ end = struct

let v ~label ~sandbox dir_path = { dir_path; sandbox; label; closed = false }

let chmod (_t : t) ~(follow : bool) ~(perm : int) (_path : string) : unit =
Copy link
Collaborator

Choose a reason for hiding this comment

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

Like with the other functions that do not have an implementation, we should actually still create a stub in eio_windows_stubs.c that fails. See, for example, how symlink does it. This reduces the burden for someone to come along and do a chmod implementation for Windows.

@webbunivAdmin
Copy link
Author

@patricoferris At last i made

@patricoferris
Copy link
Collaborator

Before reviewing @webbunivAdmin could you tidy up the Git history a little here. 35 of the 49 commits are called Update fs.md ^^" ! Mostly you could just squash the history with a soft reset and a force push to your branch.

@webbunivAdmin
Copy link
Author

@patricoferris i thing am done

@patricoferris
Copy link
Collaborator

Hey @webbunivAdmin, sorry if I wasn't clear enough in my previous post. To make reviewing this easier could you tidy up the git history please. For example there is a pretty good stackoverflow post about how you can do that here: https://stackoverflow.com/questions/5189560/how-do-i-squash-my-last-n-commits-together

Does that make sense? If you don't want to squash the history do let me know and I'll take over the PR at some point to get it in a reviewable shape. Thanks :))

talex5 and others added 17 commits November 21, 2024 13:32
It's quicker to do it in a single call.
path.mli says:

> In Eio, the directory separator is always "/", even on Windows.

However, `Path.(/)` used `Filename.concat` to create paths, which uses
the native separator ("\" on Windows).
This allows e.g. using the result of the `import_socket_stream` as a
`stream_socket_ty` without needing a cast.
This can take quite a long time.
Instead of having separate Alloc, Alloc_or_wait and Free effects,
the scheduler now provides a single Get effect to return itself,
and the actual work is now done in the calling fiber. This is cleaner,
and seems to be slightly faster too.

Note that `alloc_fixed_or_wait` is currently not cancellable (it wasn't
before either, but it's more obvious now).

It would be possible to use DLS to store the scheduler rather than using
an effect. However, the improvement in speed is minimal and there are
some complications with sys-threads, so probably better to wait for
OCaml to support thread-local-storage first.
webbunivAdmin and others added 21 commits November 21, 2024 13:36
Co-Authored-By: Patrick Ferris <[email protected]>
Co-Authored-By: Patrick Ferris <[email protected]>
Co-Authored-By: Patrick Ferris <[email protected]>
Co-Authored-By: Patrick Ferris <[email protected]>
Co-Authored-By: Patrick Ferris <[email protected]>
Co-Authored-By: Patrick Ferris <[email protected]>
Co-Authored-By: Patrick Ferris <[email protected]>
Co-Authored-By: Patrick Ferris <[email protected]>
Co-Authored-By: Patrick Ferris <[email protected]>
Co-Authored-By: Patrick Ferris <[email protected]>
If the fiber fails, record the backtrace when failing the switch. `fork`
itself already did this, but `fork_daemon` and `fork_promise_exn`
didn't.
@patricoferris
Copy link
Collaborator

Closing this in favour of #785

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.

6 participants