more OsPath conversion (542/749)

Sponsored-by: Luke T. Shumaker
This commit is contained in:
Joey Hess 2025-02-06 11:38:14 -04:00
parent 0d2b805806
commit 0811531b59
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
13 changed files with 127 additions and 116 deletions

View file

@ -5,6 +5,7 @@
- License: BSD-2-clause
-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE CPP #-}
module Utility.Daemon (
@ -25,6 +26,7 @@ import Utility.OpenFd
#else
import System.Win32.Process (terminateProcessById)
import Utility.LockFile
import qualified Utility.OsString as OS
#endif
#ifndef mingw32_HOST_OS
@ -42,7 +44,7 @@ import System.Posix hiding (getEnv, getEnvironment)
- Instead, it runs the cmd with provided params, in the background,
- which the caller should arrange to run this again.
-}
daemonize :: String -> [CommandParam] -> IO Fd -> Maybe FilePath -> Bool -> IO () -> IO ()
daemonize :: String -> [CommandParam] -> IO Fd -> Maybe OsPath -> Bool -> IO () -> IO ()
daemonize cmd params openlogfd pidfile changedirectory a = do
maybe noop checkalreadyrunning pidfile
getEnv envvar >>= \case
@ -70,10 +72,10 @@ daemonize cmd params openlogfd pidfile changedirectory a = do
{- To run an action that is normally daemonized in the foreground. -}
#ifndef mingw32_HOST_OS
foreground :: IO Fd -> Maybe FilePath -> IO () -> IO ()
foreground :: IO Fd -> Maybe OsPath -> IO () -> IO ()
foreground openlogfd pidfile a = do
#else
foreground :: Maybe FilePath -> IO () -> IO ()
foreground :: Maybe OsPath -> IO () -> IO ()
foreground pidfile a = do
#endif
maybe noop lockPidFile pidfile
@ -93,12 +95,12 @@ foreground pidfile a = do
-
- Writes the pid to the file, fully atomically.
- Fails if the pid file is already locked by another process. -}
lockPidFile :: FilePath -> IO ()
lockPidFile :: OsPath -> IO ()
lockPidFile pidfile = do
#ifndef mingw32_HOST_OS
fd <- openFdWithMode (toRawFilePath pidfile) ReadWrite (Just stdFileMode) defaultFileFlags
fd <- openFdWithMode (fromOsPath pidfile) ReadWrite (Just stdFileMode) defaultFileFlags
locked <- catchMaybeIO $ setLock fd (WriteLock, AbsoluteSeek, 0, 0)
fd' <- openFdWithMode (toRawFilePath newfile) ReadWrite (Just stdFileMode) defaultFileFlags
fd' <- openFdWithMode (fromOsPath newfile) ReadWrite (Just stdFileMode) defaultFileFlags
{ trunc = True }
locked' <- catchMaybeIO $ setLock fd' (WriteLock, AbsoluteSeek, 0, 0)
case (locked, locked') of
@ -107,17 +109,17 @@ lockPidFile pidfile = do
_ -> do
_ <- fdWrite fd' =<< show <$> getPID
closeFd fd
rename newfile pidfile
renameFile newfile pidfile
where
newfile = pidfile ++ ".new"
newfile = pidfile <> literalOsPath ".new"
#else
{- Not atomic on Windows, oh well. -}
unlessM (isNothing <$> checkDaemon pidfile)
alreadyRunning
pid <- getPID
writeFile pidfile (show pid)
writeFile (fromOsPath pidfile) (show pid)
lckfile <- winLockFile pid pidfile
writeFile (fromRawFilePath lckfile) ""
writeFile (fromOsPath lckfile) ""
void $ lockExclusive lckfile
#endif
@ -128,17 +130,17 @@ alreadyRunning = giveup "Daemon is already running."
- is locked by the same process that is listed in the pid file.
-
- If it's running, returns its pid. -}
checkDaemon :: FilePath -> IO (Maybe PID)
checkDaemon :: OsPath -> IO (Maybe PID)
#ifndef mingw32_HOST_OS
checkDaemon pidfile = bracket setup cleanup go
where
setup = catchMaybeIO $
openFdWithMode (toRawFilePath pidfile) ReadOnly (Just stdFileMode) defaultFileFlags
openFdWithMode (fromOsPath pidfile) ReadOnly (Just stdFileMode) defaultFileFlags
cleanup (Just fd) = closeFd fd
cleanup Nothing = return ()
go (Just fd) = catchDefaultIO Nothing $ do
locked <- getLock fd (ReadLock, AbsoluteSeek, 0, 0)
p <- readish <$> readFile pidfile
p <- readish <$> readFile (fromOsPath pidfile)
return (check locked p)
go Nothing = return Nothing
@ -147,16 +149,16 @@ checkDaemon pidfile = bracket setup cleanup go
check (Just (pid, _)) (Just pid')
| pid == pid' = Just pid
| otherwise = giveup $
"stale pid in " ++ pidfile ++
"stale pid in " ++ fromOsPath pidfile ++
" (got " ++ show pid' ++
"; expected " ++ show pid ++ " )"
#else
checkDaemon pidfile = maybe (return Nothing) (check . readish)
=<< catchMaybeIO (readFile pidfile)
=<< catchMaybeIO (readFile (fromOsPath pidfile))
where
check Nothing = return Nothing
check (Just pid) = do
v <- lockShared =<< winLockFile pid pidfile
v <- lockShared =<< winLockFile pid (fromOsPath pidfile)
case v of
Just h -> do
dropLock h
@ -165,7 +167,7 @@ checkDaemon pidfile = maybe (return Nothing) (check . readish)
#endif
{- Stops the daemon, safely. -}
stopDaemon :: FilePath -> IO ()
stopDaemon :: OsPath -> IO ()
stopDaemon pidfile = go =<< checkDaemon pidfile
where
go Nothing = noop
@ -181,14 +183,14 @@ stopDaemon pidfile = go =<< checkDaemon pidfile
- when eg, restarting the daemon.
-}
#ifdef mingw32_HOST_OS
winLockFile :: PID -> FilePath -> IO RawFilePath
winLockFile :: PID -> OsPath -> IO OsPath
winLockFile pid pidfile = do
cleanstale
return $ toRawFilePath $ prefix ++ show pid ++ suffix
return $ prefix <> toOsPath (show pid) <> suffix
where
prefix = pidfile ++ "."
suffix = ".lck"
prefix = pidfile <> literalOsPath "."
suffix = literalOsPath ".lck"
cleanstale = mapM_ (void . tryIO . removeFile) =<<
(filter iswinlockfile . map fromRawFilePath <$> dirContents (parentDir (toRawFilePath pidfile)))
iswinlockfile f = suffix `isSuffixOf` f && prefix `isPrefixOf` f
(filter iswinlockfile <$> dirContents (parentDir pidfile))
iswinlockfile f = suffix `OS.isSuffixOf` f && prefix `OS.isPrefixOf` f
#endif