
#8741: `System.Directory.getPermissions` fails on read-only filesystem -------------------------------------+------------------------------------- Reporter: hvr | Owner: AlainODea Type: bug | Status: patch Priority: high | Milestone: Component: libraries/unix | Version: 7.6.3 Resolution: | Keywords: Operating System: POSIX | Architecture: Unknown/Multiple Type of failure: Incorrect result | Difficulty: Easy (less than 1 at runtime | hour) Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------- Comment (by duncan): So the patch looks ok. I think I would also add ETXTBSY as another alternative, i.e. {{{ (err == eACCES || err == eROFS || err == eTXTBSY) }}} Since according to `access(2)` {{{ ETXTBSY Write access was requested to an executable which is being exe‐ cuted. }}} and `open(2)`: {{{ ETXTBSY pathname refers to an executable image which is currently being executed and write access was requested. }}} So the patch on its own is fine, but looking at `System.Directory.getPermissions` leaves me aghast: {{{ read_ok <- Posix.fileAccess name True False False write_ok <- Posix.fileAccess name False True False exec_ok <- Posix.fileAccess name False False True stat <- Posix.getFileStatus name }}} Four! Four? Four calls to stat? (`access()` is just a C lib function that calls `stat()`.) Surely we can do better than that? One call to stat should be enough. Also, `access` doesn't do quite what we want. What we want to know is "if I tried to read/write/exec/traverse this file/dir, would it work?". But access answerss a subtly different question: {{{ The check is done using the calling process's real UID and GID, rather than the effective IDs as is done when actually attempting an operation (e.g., open(2)) on the file. This allows set-user-ID programs to eas‐ ily determine the invoking user's authority. }}} Well, that's all very good and useful, but it's not what we want here. So yes, ideally we'd do one stat call and work it all out from there. {{{ stat <- Posix.getFileStatus name let mode = Posix.fileMode stat read_ok = -- bit twiddling on mode using constants like Posix.ownerReadMode write_ok = -- etc exec_ok = -- etc }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8741#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler