-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sandwich-contexts: find shorter Unix socket paths when necessary
- Loading branch information
Tom McLaughlin
committed
Nov 10, 2024
1 parent
b25cb44
commit eb12946
Showing
3 changed files
with
125 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
sandwich-contexts/lib/Test/Sandwich/Contexts/UnixSocketPath.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
{-# LANGUAGE CPP #-} | ||
|
||
module Test.Sandwich.Contexts.UnixSocketPath ( | ||
withUnixSocketDirectory | ||
, maxUnixSocketLength | ||
) where | ||
|
||
import Control.Monad.IO.Unlift | ||
import Relude | ||
import System.IO.Error (IOError) | ||
import Test.Sandwich.Expectations (expectationFailure) | ||
import UnliftIO.Directory | ||
import UnliftIO.Exception | ||
import UnliftIO.Temporary | ||
|
||
|
||
-- | The longest allowed path for a Unix socket on the current system. | ||
maxUnixSocketLength :: Int | ||
#ifdef mingw32_HOST_OS | ||
maxUnixSocketLength = Infinity | ||
#elif darwin_host_os | ||
maxUnixSocketLength = 103 -- macOS: 104 with null terminator | ||
#else | ||
maxUnixSocketLength = 107 -- Linux: 108 with null terminator | ||
#endif | ||
|
||
-- | Create a temporary directory in which a Unix socket can be safely created, | ||
-- bearing in mind the longest allowed Unix socket path on the system. | ||
withUnixSocketDirectory :: (MonadUnliftIO m) | ||
-- | Name template, as passed to 'withSystemTempDirectory' | ||
=> String | ||
-- | Amount of headroom to leave for a file name in this directory, | ||
-- before hitting the 'maxUnixSocketLength' | ||
-> Int | ||
-- | Callback | ||
-> (FilePath -> m a) -> m a | ||
withUnixSocketDirectory nameTemplate headroom action = do | ||
withSystemTempDirectory nameTemplate $ \dir -> | ||
if | length dir + headroom <= maxUnixSocketLength -> action dir | ||
| otherwise -> withShortTempDir nameTemplate headroom action | ||
|
||
withShortTempDir :: ( | ||
MonadUnliftIO m | ||
) | ||
=> String | ||
-> Int | ||
-> (FilePath -> m a) | ||
-> m a | ||
withShortTempDir nameTemplate headroom action = doesDirectoryExist "/tmp" >>= \case | ||
True -> isDirectoryWritable "/tmp" >>= \case | ||
True -> withTempDirectory "/tmp" nameTemplate $ \dir -> | ||
if | length dir + headroom <= maxUnixSocketLength -> action dir | ||
| otherwise -> doFail | ||
False -> doFail | ||
_ -> doFail | ||
where | ||
doFail = expectationFailure "Couldn't create a short enough Unix socket path on this system." | ||
|
||
isDirectoryWritable :: MonadUnliftIO m => FilePath -> m Bool | ||
isDirectoryWritable dir = do | ||
try (getPermissions dir) >>= \case | ||
Left (_ :: IOError) -> return False | ||
Right perms -> return $ writable perms |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters