Lean 4 (Meta)programming Cookbook

Reading File Permissions🔗

To read the permissions of a file, Lean does not provide a built-in API for it(if you know one, please let us know!, I could not find one in the documentation). However, we can use the Linux stat command to get the permissions in octal format and then convert it to an IO.FileRight structure.

/-- Convert an octal digit to an IO.AccessRight structure. -/ def octalToAccessRight (c : Char) : IO.AccessRight := let val := c.toString.toNat! { read := val / 4 % 2 == 1, write := val / 2 % 2 == 1, execution := val % 2 == 1 } /-- Reads the permissions of a file with `stat` command. -/ def getFilePermissions (path : System.FilePath) : IO IO.FileRight := do let out IO.Process.output { cmd := "stat", args := #["-c", "%a", path.toString] } if out.exitCode != 0 then throw <| IO.userError s!"Failed to run stat: {out.stderr}" -- The output is usually 3 digits let s := out.stdout.trimAscii.toString let chars := s.toList -- Handle cases with 3 digits (User, Group, Other) match chars with | [u, g, o] => return { user := octalToAccessRight u, group := octalToAccessRight g, other := octalToAccessRight o } | _ => throw <| IO.userError s!"Unexpected permission format: {s}" def demoPermissions (path : System.FilePath) : IO Unit := do -- Get current permissions let current getFilePermissions path IO.println s!"User can read: {current.user.read}" -- Modify permissions: Add execution for the user let updated := { current with user := { current.user with execution := true }, group := { current.group with write := true }, other := { current.other with execution := true }, } -- Apply updated permissions IO.setAccessRights path updated IO.println "Updated user to allow execution."

This works nicely on Unix systems, you can modify the commands accordingly. Note that when you are setting permissions, you will only change the permissions mentioned in the IO.FileRight structure, previously set permissions that are not mentioned will remain unchanged.